# Picking a host

> Which host to run your app on, and the two rules that hold whichever one you pick.

Page: https://sdk.chatfuel.com/docs/deploy
Markdown: https://sdk.chatfuel.com/docs/deploy.md

Nothing about the app is Vercel-specific except `vercel.json` and `api/chatfuel.ts`; delete both
and you have a working Node app. So the host you pick decides who manages TLS, whether you can
serve from a sub-path and how long a WebSocket stays open — not what the code is.

## Picking a host [#picking-a-host]

|                     | Vercel                                                                  | Your own server              | Docker                        |
| ------------------- | ----------------------------------------------------------------------- | ---------------------------- | ----------------------------- |
| Command             | `npm run deploy`                                                        | `npm run build && npm start` | `docker build` + `docker run` |
| Needs an account    | Vercel                                                                  | none                         | none                          |
| TLS, domain         | managed                                                                 | yours                        | yours                         |
| Sub-path (`/app/`)  | no, root only                                                           | yes                          | yes                           |
| WebSocket lifetime  | capped by the function duration (300 s on Hobby); the client reconnects | unbounded                    | unbounded                     |
| Where the env lives | the Vercel project (`.env` is never uploaded)                           | your process                 | `--env-file` and build args   |

<Callout type="info">
  All three run the same proxy source, so the auth gate, the bot fence and the error codes are
  identical between them.
</Callout>

## Every host has to answer an unknown path with `index.html` [#every-host-has-to-answer-an-unknown-path-with-indexhtml]

The router is path-based, so `/deals/board` is a real address. A host that 404s it produces a
failure that looks like a routing bug and is not one: a reload of that URL fails while clicking
through to the same page works fine.

* **Vercel** — the last rewrite in `vercel.json`.
* **nginx** — `try_files $uri /index.html;`
* **Static hosts** — their SPA-fallback, or "rewrite everything to `index.html`".
* **The bundled Node server** does it already.

## The rule that catches everyone once [#the-rule-that-catches-everyone-once]

`VITE_*` variables are compiled into the browser bundle **at build time**. Everything else is read
by the server **at runtime**. A deployment where those two disagree does not fail at the mismatch;
it fails later, at the gate:

* client built with Supabase, server started without it → the sign-in screen renders and every
  request comes back `ProxyAuthMisconfigured` or `AuthSessionRequired`;
* server gated, client built without it → nobody is ever asked to sign in, and the server rejects
  everything.

Neither is fixable at runtime. Rebuild with the same values the server is running with.

The server prints its mode on startup, and `/healthz` answers
`{"ok":true,"auth":"on|off|misconfigured"}`. Read that before any other symptom.

## Deploying without the wizard [#deploying-without-the-wizard]

`npm run deploy` is a convenience, not a dependency: it is `scripts/deploy-vercel.mjs` inside your
own project, driving the Vercel CLI. Any pipeline that builds the client, builds the server and
sets the environment produces the same result, and any CI that can run `npm run build` can deploy
this app.

<Cards>
  <Card title="Vercel" href="/docs/deploy/vercel" description="One command: links the project, pushes the environment, deploys, verifies." />

  <Card title="Your own server" href="/docs/deploy/node-server" description="npm run build && npm start, and what to put in front of it." />

  <Card title="Docker" href="/docs/deploy/docker" description="The shipped Dockerfile, and the build-arg split that leaks secrets." />

  <Card title="Environment variables" href="/docs/deploy/environments" description="Every variable the app reads, which side reads it, and what it is." />
</Cards>
