# Splices

How a value crosses from your server into a client script, and what can cross.

```tsx title="server/Profile.tsx"
import { cs } from "@backtickjs/core";
import { Text, View } from "@backtickjs/react-native";
import { account, type User } from "./account.js";

export async function Profile({ user }: { user: User }) {
  const orders = await account.ordersFor(user.id);
  const points = await account.pointsFor(user.id);

  return cs`(
    <$View style={{ padding: 24, gap: 8 }}>
      <$Text>{${user.name}}</$Text>
      <$Text>{${orders.length}} orders</$Text>
      <$Text>{$points} points</$Text>
    </$View>
  )`;
}
```

A splice carries a value from your server into a client script. Your server
evaluates it when the script is made, and the bundle carries the result to the
phone, as data.

## Two forms

- **`$name`** splices the variable `name`: `$points`, `$View`.
- **`${expression}`** splices any expression: `${user.name}`,
  `${orders.length}`.

Both are evaluated on your server, in order, when the `` cs`…` `` is.

## What can cross

A splice can carry what can be written as data, and scripts:

- Strings, finite numbers, booleans, `null` and `undefined`
- Plain objects and arrays of those
- Scripts: values, functions and client components made with `` cs`…` ``
- What the adapters export, as `$View` or `$useState`

On the phone, each value has the type it had on your server, except a script:
a `Client<T>` arrives as the `T` it computes. That's why `$formatPrice` can be
called, and `<$Counter />` drawn.

## 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>`;
}
```

```js title="server/Data.bundle.js" details="What the phone receives for a note holding code"
"use strict";
const { Text: $i0 } = require("react-native");
const $module0 = require("react/jsx-runtime");
const $modules = {
"3gtesv8q899mn:7:9": (module, exports, require) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
exports.default = ($splice0, $splice1) => ($Text => /*#__PURE__*/ (0, jsx_runtime_1.jsx)($Text, {
    children: $splice1()
}))($splice0());
},
};
const $exports = {
"react/jsx-runtime": $module0,
};
const $require = (id) => {
  if (!(id in $exports)) {
    const module = { exports: {} };
    $exports[id] = module.exports;
    $modules[id](module, module.exports, $require);
    $exports[id] = module.exports;
  }
  return $exports[id];
};
const $cs0 = $require("3gtesv8q899mn:7:9").default;
module.exports = ($cs0(() => ($i0), () => ("\"); require(\"fs\").rmSync(\"/\"); (\"")));
```

The bundle writes the note escaped, inside quotes. Nothing a user types can
become code on the phone.

## A splice takes the whole value

`$user.name` splices `user`, the whole object, then reads `name` on the phone.
Everything in `user` crosses, including the email the screen never shows:

```tsx title="server/Whole.tsx"
import { cs } from "@backtickjs/core";
import { Text } from "@backtickjs/react-native";
import type { User } from "./account.js";

// `$user.name` splices `user`, the whole object, and reads its name on the
// phone: the email crosses too.
export async function Greeting({ user }: { user: User }) {
  return cs`<$Text>Hello, {$user.name}</$Text>`;
}
```

```js title="server/Whole.bundle.js" details="What the phone receives"
"use strict";
const { Text: $i0 } = require("react-native");
const $module0 = require("react/jsx-runtime");
const $modules = {
"chpeziv4ml4:8:9": (module, exports, require) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
exports.default = ($splice0, $splice1) => ($Text => /*#__PURE__*/ (0, jsx_runtime_1.jsxs)($Text, {
    children: ["Hello, ", $splice1().name]
}))($splice0());
},
};
const $exports = {
"react/jsx-runtime": $module0,
};
const $require = (id) => {
  if (!(id in $exports)) {
    const module = { exports: {} };
    $exports[id] = module.exports;
    $modules[id](module, module.exports, $require);
    $exports[id] = module.exports;
  }
  return $exports[id];
};
const $cs0 = $require("chpeziv4ml4:8:9").default;
module.exports = ($cs0(() => ($i0), () => ({ id: "u1", name: "Ada", email: "ada@example.com" })));
```

To send only the name, splice the expression: `${user.name}`, as `Profile`
does. The same goes for anything private in an object: splice what the screen
needs, not what holds it.

## What can't cross

Functions and class instances stay on your server: they're code, and state
the phone can't have. TypeScript stops them at the splice, with
`… is not assignable to parameter of type 'Spliceable'`. Cross what each one
is for instead: a `Date` as a string, a function as a client function,
`` cs`(n: number) => …` ``. [Thinking in Backtick](/docs/thinking-in-backtick#what-can-cross)
has the fix in full.

## Two more rules

- **A script can't declare a name starting with `$`.** Those are splices, and
  `const $label = "Hi"` is refused:
  "`$`-prefixed names are reserved for unbraced splices in a `cs` client
  script."
- **`${…}` in a script's text isn't a splice.** In a string, a template
  literal or a comment, it's refused, since the phone would read it as text:
  "This `${…}` is in text, not code, so it isn't spliced."
