# Scripts in depth

A script's three shapes, when its code runs, scripts inside data, and what a splice checks.

To your server, a script is a value, a `Client<T>`: something the phone will
compute as a `T`. This page is what follows from that, for when a screen does
something you didn't expect.

## Three shapes

```ts title="server/shapes.ts"
import { type Client, cs } from "@backtickjs/core";

// An expression is what it computes.
export const greeting: Client<string> = cs`new Date().getHours() < 12
  ? "Good morning"
  : "Good afternoon"`;

// A block is what it returns.
export const meal: Client<string> = cs`{
  const hour = new Date().getHours();
  return hour < 11 ? "Breakfast" : "Lunch";
}`;

// A function is the function.
export const double: Client<(n: number) => number> = cs`(n: number) => n * 2`;
```

A script is an expression, a block of statements, or a function. An
expression is a `Client` of its value; a block, of what it returns; a
function, of the function itself. A function that returns JSX is a client
component. TypeScript infers each type; the annotations above only show
them.

Your server can't read the `T`, which doesn't exist until the phone runs the
script. It can splice the script into another, pass it around, and return it
from a server component. Annotate a function that builds scripts with
`Client<T>`, taking the phone's number and giving back the phone's string:

```ts title="server/formatted.ts"
import { type Client, cs } from "@backtickjs/core";

// A script built from another: the phone computes `amount`, then formats it.
export function formatted(amount: Client<number>): Client<string> {
  return cs`"$" + $amount.toFixed(2)`;
}

export const total = formatted(cs`4.5 + 4`);
```

## Reading a script

How a splice of a script behaves follows from its shape, as the same code
written by hand in TypeScript would:

- **A function is one function.** `$logTap` is the same function at every
  read, and its body runs each time it's called.
- **An expression or a block is code, run each time it's read.** Reading
  `$logVisit` twice runs it twice.

```tsx title="server/Log.tsx"
import { cs } from "@backtickjs/core";
import { Text } from "@backtickjs/react-native";

// A block: its code runs each time it's read.
const logVisit = cs`{
  console.log("visit");
}`;

// A function: one function, whose body runs each time it's called.
const logTap = cs`(what: string) => console.log("tap " + what)`;

export async function Home() {
  return cs`{
    $logVisit;
    $logVisit;
    $logTap("a");
    $logTap("b");
    return <$Text>Logged</$Text>;
  }`;
}
```

This is why a client component is written as a function: one function for the
bundle, so React sees the same component on every render and keeps its
state. A component made by an expression or a block is new code at each read,
so React remounts it on every render of its parent, as it would one defined
inside a render function.

A component made by a call, such as `memo(…)`, is made once where React would
make it, in `useMemo`:

```tsx title="server/Rows.tsx"
import { cs } from "@backtickjs/core";
import { memo, useMemo, useState } from "@backtickjs/react";
import { Pressable, Text, View } from "@backtickjs/react-native";

// A client component, written as a function: one component for the bundle.
const Row = cs`(props: { label: string }) => {
  const [count, setCount] = $useState(0);
  return (
    <$Pressable onPress={() => setCount(count + 1)}>
      <$Text>
        {props.label} {count}
      </$Text>
    </$Pressable>
  );
}`;

export const List = cs`() => {
  // memo(…) is a call: made once per list, so it is one component too.
  const MemoRow = $useMemo(() => $memo($Row), []);
  const [taps, setTaps] = $useState(0);
  return (
    <$View>
      <$Pressable onPress={() => setTaps(taps + 1)}>
        <$Text>list {taps}</$Text>
      </$Pressable>
      <MemoRow label="row" />
    </$View>
  );
}`;

export async function Home() {
  return cs`<$List />`;
}
```

## No template literals inside a script

A script is a template literal itself, so it can't hold one: a backtick in
its code is refused, with "A `cs` client script can't hold a template
literal". Build the string with `+` instead: `n + "%"`, not `` `${n}%` ``.
In a string or a comment, write a backtick as `` \` ``, as anywhere in a
template literal.

## A script in data

A splice can carry scripts inside data. On the phone, each `Client<U>` in it
is the `U` it computes; everything else is unchanged. `Spliced<T>` names that
type, and TypeScript applies it to every splice:

```ts title="server/menu.ts"
import { type Client, cs, type Spliced } from "@backtickjs/core";

type Item = {
  name: string;
  price: number;
  // Computed on the phone, from its own clock.
  available: Client<boolean>;
};

export const menu: Item[] = [
  { name: "Flat white", price: 4.5, available: cs`true` },
  { name: "Croissant", price: 3, available: cs`new Date().getHours() < 11` },
];

// On the phone, each `available` is the boolean its script computes.
export type MenuOnPhone = Spliced<Item[]>;
// { name: string; price: number; available: boolean }[]

export const names = cs`$menu
  .filter((item) => item.available)
  .map((item) => item.name)`;
```

## Client code handed to a server component

A server component drawn inside a client component can be handed that
component's local values, as client code:

```tsx title="server/LiveSection.tsx"
import { type Client, cs } from "@backtickjs/core";
import { useState } from "@backtickjs/react";
import { Pressable, Text, View } from "@backtickjs/react-native";

const Like = cs`() => {
  const [liked, setLiked] = $useState(false);
  return (
    <$Pressable onPress={() => setLiked(!liked)}>
      <$Text>{liked ? "♥" : "♡"}</$Text>
    </$Pressable>
  );
}`;

// A server component handed client code: its title is the phone's to compute.
async function Section({ title }: { title: Client<string> }) {
  return cs`(
    <$View>
      <$Text>{$title}</$Text>
      <$Like />
    </$View>
  )`;
}

// A client component drawing that server component, handing it a local.
const Cart = cs`() => {
  const [count, setCount] = $useState(0);
  return (
    <$View>
      <$Pressable onPress={() => setCount(count + 1)}>
        <$Text>Add</$Text>
      </$Pressable>
      {${(<Section title={cs`count + " in your cart"`} />)}}
    </$View>
  );
}`;

export async function Home() {
  return cs`<$Cart />`;
}
```

`` cs`count + " in your cart"` `` is a fragment of `Cart`'s code, reading its
`count`. `Section` splices it as `$title`, and the phone computes it each
time it's read, so the title follows the count. `Section` itself runs once,
on your server: it decides the layout, and the phone fills in what depends on
its state.

## Data, never code

A spliced string arrives as a string, whatever it holds. A note that reads
like code is still only text:

```tsx title="server/Data.tsx"
import { cs } from "@backtickjs/core";
import { Text } from "@backtickjs/react-native";

// A splice is written into the bundle as data, never as code: whatever this
// string holds, the phone shows it as text.
export async function Note({ text }: { text: string }) {
  return cs`<$Text>{$text}</$Text>`;
}
```

For a note holding `"); require("fs").rmSync("/"); ("`, the bundle writes it
escaped, inside quotes:

```js
const $thunk1 = () => ("\"); require(\"fs\").rmSync(\"/\"); (\"");
```

Nothing a user types can become code on the phone.

## What a splice checks

A splice checks a value member by member, so an object typed with an
interface splices as one typed with a type alias does. `Spliceable` written
by hand, in an annotation or a `satisfies`, matches an object through an index
signature, which TypeScript never gives an interface: annotate with your own
types and let the splice check them.

Numbers include `NaN`, `Infinity` and `-0`, which arrive as themselves, as do
bigints. A class whose members are all data looks like a plain object to
TypeScript, so the bundler is what refuses it, when it builds the screen. A
value that contains itself is refused too: a bundle writes each value out in
full. [Errors](/docs/errors#from-the-bundler) has each message.

The rest of `@backtickjs/core` is how Backtick's own pieces talk to each
other; its
[README](https://github.com/backtickjs/backtick/tree/main/packages/core#api)
lists them. An app doesn't need it.
