# Scripts in the generated app

> Every npm script the scaffolded app ships with — what it runs, when you reach for it, and what has to be true first.

Page: https://sdk.chatfuel.com/docs/reference/scripts
Markdown: https://sdk.chatfuel.com/docs/reference/scripts.md

Every command below is `npm run <name>` from the app root, except `npm start` and `npm test`,
which npm lets you type without the `run`.

## The scripts [#the-scripts]

| Script         | What it runs                                        | When you reach for it                                                                                                                                                                                                                                       | What has to be true first                                                                       |
| -------------- | --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `dev`          | `vite`                                              | Day to day. Serves the app on port 5173 with the Chatfuel proxy plugin registered, so the token stays server-side.                                                                                                                                          | Dependencies installed, and a `.env` with `CHATFUEL_TOKEN`.                                     |
| `build`        | `vite build && vite build -c vite.server.config.ts` | Before `start`, and in a Docker image. Builds both halves.                                                                                                                                                                                                  | The `VITE_*` values you build with must match the ones the server will run with.                |
| `build:client` | `vite build`                                        | The browser bundle alone. This is also what Vercel runs.                                                                                                                                                                                                    | Same.                                                                                           |
| `build:server` | `vite build -c vite.server.config.ts`               | The server bundle alone, into `server/dist/entry.js`. Plugin-free on purpose — it never touches the client.                                                                                                                                                 | —                                                                                               |
| `start`        | `node server/dist/entry.js`                         | Running the built app on your own host. Serves `dist/` and proxies Chatfuel traffic, HTTP and WebSocket, with the token injected server-side.                                                                                                               | `build` or `build:server` has run. Listens on `PORT`, default 3000.                             |
| `deploy`       | `node scripts/deploy-vercel.mjs`                    | Putting the app on Vercel, with no Git repository and no dashboard.                                                                                                                                                                                         | A `.env` that passes its checks.                                                                |
| `connect-git`  | `node scripts/connect-git.mjs`                      | Making `git push` deploy, once there is a repository.                                                                                                                                                                                                       | A linked Vercel project — `.vercel/project.json`, written by `deploy` — and an `origin` remote. |
| `check`        | `tsc --noEmit && tsc -p tsconfig.scripts.json`      | Before a commit. Two passes, because the app's `tsconfig.json` covers `src`, `server`, `api` and the two Vite configs and nothing else; the second pass is `scripts/`, which is JavaScript and is only type-checked because that config turns `checkJs` on. | —                                                                                               |
| `test`         | `vitest run`                                        | Before a commit, and after any change to a module's root component.                                                                                                                                                                                         | —                                                                                               |

<Callout type="warn">
  Vercel builds with `build:client` only. `server/entry.ts` is never built or run there — the
  Vercel deployment answers Chatfuel traffic from `api/chatfuel.ts` instead, through the rewrite in
  `vercel.json`. A change you make to the Node server shows up under `npm start` and in Docker, and
  nowhere on Vercel.
</Callout>

## What `deploy` actually does [#what-deploy-actually-does]

<Accordions>
  <Accordion title="The seven steps, in order">
    Check the CLI runs at all, check the login, link the project, push the environment, deploy,
    resolve the public URL, then ask the deployment itself whether it came up configured. The first
    step earns its place twice over: it is where a first-run CLI download happens, and it separates
    "the CLI cannot start" from every later step's own failure.
  </Accordion>

  <Accordion title="Which Vercel CLI it uses">
    `vercel` when it is on PATH, `npx --yes vercel@latest` when it is not. The npx path downloads
    around 50 MB on its first call and says so, because the call is captured rather than shown and
    the wait otherwise reads as a hang. `VERCEL_TOKEN`, when set, is appended to every call.
  </Accordion>

  <Accordion title="What goes up, and what does not">
    Twelve named variables, to production and preview, with `vercel env add --force` — which
    overwrites the value for that target instead of adding a second one. `CHATFUEL_TOKEN`,
    `SUPABASE_SERVICE_ROLE_KEY`, `PUBLISHING_SECRET` and `ADMIN_PASSWORD` go up sensitive and cannot
    be read back out of the dashboard; the rest stay readable, because a workspace id nobody can
    look at is a debugging tax for no security. Variables that exist on Vercel but not in your
    `.env` are left alone — the script never deletes. `.env` itself is never uploaded.
  </Accordion>

  <Accordion title="The configurations it refuses">
    No `CHATFUEL_TOKEN`, or exactly one of `VITE_SUPABASE_URL` and `VITE_SUPABASE_ANON_KEY` — half
    a pair is a deployment that builds, starts and serves nothing but `ProxyAuthMisconfigured`. With
    both set it also requires `SUPABASE_SERVICE_ROLE_KEY` and `CHATFUEL_WORKSPACE_ID`, without which
    nobody can finish signing up. A missing `VITE_CHATFUEL_WORKSPACE_ID` is a warning, not a refusal.
  </Accordion>

  <Accordion title="The project name">
    It is the address: `<name>.vercel.app`. Precedence is `--project`, then `VERCEL_PROJECT_NAME`
    (which the wizard sets when it runs the script for you), then the terminal, then the directory
    name. A name that already exists is a warning and a confirm, because deploying into it would
    overwrite its environment variables and replace whatever is live there.
  </Accordion>
</Accordions>

Re-running is the normal case, so every step is idempotent: an existing `.vercel/project.json` is
kept and the project is never re-created.

## What `test` covers [#what-test-covers]

Every module ships a render test that mounts its root component and renders the tree to a string.
It runs without a browser, which is the point: nothing else in the app can catch a component that
type-checks, passes every other gate and renders nothing.

The suite is the app's own. The design system and the API client are vendored as sources, but their
tests are stripped on the way in — a scaffolded app should not hand you failing runs for code you
did not write. Modules you did not select are deleted from the tree, so their tests go with them.
