Skip to content
ChatfuelSDK

Deploy

Your app, on your own domain, at an address you hand to your customers. The same source runs on Vercel, on a server of your own and in a container.

One command, from a terminal to a live URL

Every step is idempotent, so shipping an update later is the same command again.

  1. 01

    The Vercel CLI

    Yours if it is installed, fetched with npx for the run if it is not.

  2. 02

    Signed in

    The browser login, or VERCEL_TOKEN in a pipeline and nothing opens.

  3. 03

    A project of your own

    Named by you, because the name is also the address the app answers on.

  4. 04

    Your environment, pushed

    Every variable your .env fills in, into production and preview, secrets write-only.

  5. 05

    Built and deployed

    The build log on screen, and the line that says why a failure failed at the bottom.

  6. 06

    A URL that works

    Each address tried until one opens without a sign-in wall, then asked for its own health.

Three commands, one per host

Pick one. The client, the server and the proxy are the same in all three; what changes is who runs the process and who holds the domain.

npm run deploy                     # Vercel

npm run build && npm start         # your own server, PORT defaults to 3000

# Docker — VITE_* are baked into the client, so they are build args as well
docker build -t chatfuel-app \
  --build-arg VITE_CHATFUEL_WORKSPACE_ID=<workspace> \
  --build-arg VITE_SUPABASE_URL=<url> \
  --build-arg VITE_SUPABASE_ANON_KEY=<key> \
  --build-arg VITE_APP_NAME="Your app" .
docker run -p 3000:3000 --env-file .env chatfuel-app

The environment it reads

One .env, read in two places: VITE_ names are compiled into the browser bundle at build time, everything else is read by the server at runtime. On Vercel the deploy copies the values into the project itself — the file is never uploaded — and overwrites them rather than duplicating when you run it again.

NameWhen you need it
Always
CHATFUEL_TOKENEvery deployment, and the one the deploy refuses to start without: with no token the proxy has nothing to reach Chatfuel with. It is server-side only and has no VITE_ prefix, so it cannot be baked into the browser bundle even in principle.
With Accounts
VITE_SUPABASE_URLWhen your own customers sign up. Set it together with the anon key or leave both out — with exactly one of the two the proxy fails closed and answers every request ProxyAuthMisconfigured, so the deploy stops rather than shipping that.
VITE_SUPABASE_ANON_KEYThe other half of that pair. Both, or neither.
SUPABASE_SERVICE_ROLE_KEYWith Accounts, and not optional there: it is what registers the bot the server just created. Without it a sign-up ends on a workspace that is not ready, and nobody who signs up gets a bot.
CHATFUEL_WORKSPACE_IDWith Accounts. The Chatfuel workspace every account’s bot is created in — the one whose plan pays for them all, so its bot limit is the ceiling for the whole deployment.
With Admin and Publishing
ADMIN_PASSWORDWhen you want the operator panel. Sixteen characters at least or it refuses to run; unset, the admin routes are not mounted at all and /admin says there is no panel here.
PUBLISHING_SECRETFor scheduled posts, and only for those. Without it the app still composes and publishes on the spot — it just offers no schedule.
Optional
VITE_CHATFUEL_WORKSPACE_IDWithout Accounts, to say which workspace the app opens on; leave it out and it opens on whichever one the account lists first. It is not a fence — every workspace the token owns is in the picker either way — and with Accounts on it is unused.
VITE_APP_NAMEYour name for the app, in the tab, the top bar and the sign-in screen. The wizard writes it at install and you can change it whenever.
VITE_APP_LOGOYour mark. A file in public/ — the wizard copies in the one you gave it — or an absolute URL.
CHATFUEL_API_BASEOnly to point the proxy at a staging environment instead of the live API.
PUBLIC_URLWhen scheduling is on and more than one name reaches the app. Without it the address the database posts back to is taken from whichever request turned scheduling on, which is fine on a single domain and not behind a load balancer.
PORTOn your own server, to move it off 3000. Vercel and Docker set their own.
VITE_BASE_PATH / BASE_PATHWhen the app does not own the domain root. The first is the build-time prefix and the second the runtime one; they must match, and Vercel is root-only.

Vercel, your own server, or Docker

All three run the same proxy source, so the auth gate, the bot fence and the error codes are identical between them. Nothing about the app is Vercel-specific except vercel.json and api/chatfuel.ts; deleting both leaves a working Node app.

NameVercelYour own serverDocker
Commandnpm run deploynpm run build && npm startdocker build, then docker run
Needs an accountA Vercel accountNoneNone
TLS and domainManaged for youYoursYours
Sub-path, as in /app/Root onlyYesYes
WebSocket lifetimeCapped by the function duration — 300 s on Hobby; the client reconnectsUnboundedUnbounded
Where the environment livesThe Vercel project, and .env is never uploadedYour process--env-file, plus build args for the VITE_ names

The rules that hold whichever host you pick

An unknown path must answer with index.html

The router is path-based, so /deals/board is a real address and a host that 404s it looks like a routing bug. The bundled Node server and vercel.json already do it; nginx needs one try_files line.

Build time and runtime have to agree

VITE_ names are compiled into the bundle, everything else is read by the server, and a deployment where the two disagree fails later at the gate rather than at the mismatch. /healthz says whether the auth gate is on, off or misconfigured — read that first.

Your own domain

TLS and the domain are managed for you on Vercel, and yours on a server of your own or in Docker. With Accounts, Supabase also has to be told the origin may receive auth redirects, or sign-in there fails.

npm run deploy is a convenience, not a dependency

It is a script inside your own project driving the Vercel CLI, and nothing in the app depends on it. Any CI that can run npm run build can deploy this app.

FAQs

What it costs to run, where it will not fit, and the one thing that makes a good deploy look broken.

Whatever you already pay for it. Vercel’s free tier runs the app; so does a Node process on a box you own, or a Docker container next to your other containers. None of the three report anything back to us.

See pricing

One command, and it is live on your own domain

npx @chatfuel/wizard