# Server components

Functions your server runs for every request: they read your data and return the screen.

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

// A server component: a function of its props, run on your server for every
// request. Its props stay on your server, so they can be anything.
export async function ProductScreen({
  id,
  catalog,
}: {
  id: string;
  catalog: Catalog;
}) {
  const product = await catalog.find(id);

  if (product === undefined) {
    return cs`<$Text>This product is gone.</$Text>`;
  }

  const name = product.name;
  const inStock = product.stock > 0;

  return cs`(
    <$View style={{ padding: 24, gap: 8 }}>
      <$Text style={{ fontSize: 28, fontWeight: "bold" }}>{$name}</$Text>
      <$Text>{$inStock ? "In stock" : "Sold out"}</$Text>
    </$View>
  )`;
}
```

A server component is a function your server runs for every request. It takes
props, reads whatever it needs, and returns a client script: the screen the
phone draws. It can be `async`, and usually is.

## Draw one from a route

Your server draws a server component the way React draws any component, with
JSX, and hands it to the bundler:

```tsx title="server/index.tsx"
import { createServer } from "node:http";
import { bundler } from "@backtickjs/bundler";
import { Catalog } from "./catalog.js";
import { ProductScreen } from "./ProductScreen.js";

const packageVersions = { react: "19.2.3", "react-native": "0.86.3" };
const catalog = new Catalog();

createServer(async (request, response) => {
  // `/products/p1` draws product p1.
  const id = request.url?.match(/^\/products\/(\w+)$/)?.[1];
  if (id === undefined) {
    response.statusCode = 404;
    response.end();
    return;
  }
  const bundle = await bundler.build({
    input: <ProductScreen id={id} catalog={catalog} />,
    packageVersions,
  });
  response.setHeader("content-type", "text/javascript");
  response.end(bundle.generate({ format: "cjs" }).code);
}).listen(3000);
```

`bundler.build` runs `ProductScreen` with these props, then bundles the script
it returns. Each request gets its own run, so each user can get their own
screen.

## Props stay on your server

A server component's props never cross to the phone, so they can be anything:
a database client, a class instance like `Catalog`, a request, a function.
Only what you splice into the script crosses.

## Decide on your server

A server component can return a different script depending on what it found,
as `ProductScreen` does for a product that's gone. The decision runs on your
server, and the phone gets only the screen it led to.

## Ship only what the screen needs

The product has a `cost`, what you paid for it, and the screen shouldn't send
it to every phone. `ProductScreen` splices `name` and `inStock`, so they're all
that crosses:

```js title="server/ProductScreen.bundle.js" details="What the phone receives"
"use strict";
const { View: $i0 } = require("react-native");
const { Text: $i1 } = require("react-native");
const $module0 = require("react/jsx-runtime");
const $modules = {
"1qlemy4wvzr85:23:9": (module, exports, require) => {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
exports.default = ($splice0, $splice1, $splice2, $splice3) => ($View => /*#__PURE__*/ (0, jsx_runtime_1.jsxs)($View, {
    style: {
        padding: 24,
        gap: 8
    },
    children: [($Text => /*#__PURE__*/ (0, jsx_runtime_1.jsx)($Text, {
            style: {
                fontSize: 28,
                fontWeight: "bold"
            },
            children: $splice2()
        }))($splice1()), ($Text => /*#__PURE__*/ (0, jsx_runtime_1.jsx)($Text, {
            children: $splice3() ? "In stock" : "Sold out"
        }))($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("1qlemy4wvzr85:23:9").default;
module.exports = ($cs0(() => ($i0), () => ($i1), () => ("Ceramic dripper"), () => (true)));
```

The last line is everything the phone learns about the product: its name, and
whether it's in stock. [Splices](/docs/splices) explains what crosses, and how
to keep a value from crossing by accident.

## State belongs on the phone

A server component runs once per request and returns, so it has no state, and
React's hooks aren't available to it. The hooks from `@backtickjs/react` are
client values, and calling one on your server is a type error:

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

export function Counter() {
  // @ts-expect-error: hooks are client code, and this runs on your server.
  const [count, setCount] = useState(0);
  return cs`<$Text>{$count}</$Text>`;
}
```

```text
This expression is not callable.
  Type 'Client<…>' has no call signatures.
```

State goes in a [client component](/docs/client-components), which a server
component can draw.
