> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bijection.com/llms.txt
> Use this file to discover all available pages before exploring further.

# React Quickstart

> Add Bijection to a React project

Learn how to create a React app, built with Vite, with a Bijection backend,
starting from the `react-vite` template of `bijection init`.

<Steps>
  <Step title="Install the Bijection CLI">
    ```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    curl -fsSL https://bijection.com/install.sh | sh
    ```

    If `bijection` is not on your `PATH` afterwards, add it as the installer
    explains. See [Install Bijection](/get-started/install).
  </Step>

  <Step title="Create the app">
    ```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    bijection init my-app --template react-vite
    ```

    This writes a React app and its Bijection backend into `my-app/`, then
    installs the app's dependencies, including the Bijection SDK, with your
    JavaScript package manager: the one of an enclosing workspace, otherwise
    the first of pnpm, bun, yarn and npm on your `PATH`. The app needs Node.js
    and one of them; the backend does not. Last, it generates
    `bijection/_generated/`, the typed API of your functions, so the project
    typechecks before it has a deployment.

    ```text theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    my-app/
    ├── bijection/
    │   ├── _generated/     the typed API of your functions
    │   ├── messages.ts     a query and a mutation
    │   ├── schema.ts       the messages table
    │   └── tsconfig.json
    ├── src/
    │   ├── App.tsx         the page that calls them
    │   └── main.tsx        creates the Bijection client
    ├── bijection.json
    ├── index.html
    ├── package.json
    └── vite.config.ts
    ```
  </Step>

  <Step title="Log in">
    Log this machine in to Bijection. You only do this once per machine.

    ```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    cd my-app
    bijection login
    ```

    <Note>
      Bijection's hosted service is not yet open for public sign-up, and the CLI
      has no default management service. Before running `bijection login`, set
      `BIJECTION_MANAGEMENT_URL` to the management service URL you were given, in
      your shell's startup file so that every later `bijection` command sees it too:

      ```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
      export BIJECTION_MANAGEMENT_URL=https://<your management service>
      ```
    </Note>
  </Step>

  <Step title="Start the backend">
    ```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    bijection dev
    ```

    The first run creates your dev deployment and writes its URL to
    `.env.local`, where the app reads it as `VITE_BIJECTION_URL`. `bijection dev`
    then keeps running: on every change it pushes `bijection/` to your dev
    deployment and regenerates `bijection/_generated/`. Keep it running.
  </Step>

  <Step title="Start the app">
    In another terminal, start the app with the command `bijection init`
    printed for your package manager, for example:

    ```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    npm run dev
    ```

    Open [http://localhost:5173/](http://localhost:5173/) and send a message.
    Open a second window: messages appear in both as soon as they are sent.
  </Step>

  <Step title="Read the backend">
    `bijection/schema.ts` declares the `messages` table, and
    `bijection/messages.ts` exports a query and a mutation. Each export is an API
    function named after the file and the export: `api.messages.list` and
    `api.messages.send`.

    ```ts bijection/messages.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    import { v } from "bijection/values";
    import { mutation, query } from "./_generated/server";

    // The 50 most recent messages, newest first.
    export const list = query({
      args: {},
      handler: async (ctx) => {
        return await ctx.db.query("messages").order("desc").take(50);
      },
    });

    export const send = mutation({
      args: { author: v.string(), body: v.string() },
      handler: async (ctx, args) => {
        await ctx.db.insert("messages", args);
      },
    });
    ```
  </Step>

  <Step title="Read the app">
    `src/main.tsx` creates a `BijectionReactClient` for the deployment URL and
    provides it to the app with `BijectionProvider`:

    ```tsx src/main.tsx theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    import { BijectionProvider, BijectionReactClient } from "bijection/react";
    import { StrictMode } from "react";
    import { createRoot } from "react-dom/client";
    import App from "./App";

    const client = new BijectionReactClient(import.meta.env.VITE_BIJECTION_URL);

    createRoot(document.getElementById("root")!).render(
      <StrictMode>
        <BijectionProvider client={client}>
          <App />
        </BijectionProvider>
      </StrictMode>,
    );
    ```

    `src/App.tsx` subscribes to the query with `useQuery` and calls the
    mutation with `useMutation`. The query result updates by itself whenever
    the messages change:

    ```tsx src/App.tsx theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    const messages = useQuery(api.messages.list);
    const send = useMutation(api.messages.send);
    ```
  </Step>

  <Step title="Call a function from the CLI">
    With the app open, send a message from another terminal. It appears in the
    app at once:

    ```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    bijection run messages:send '{"author": "me", "body": "Hello"}'
    ```
  </Step>
</Steps>

See the complete [React documentation](/client/react/overview).
