What the wizard writes
The tree the wizard leaves on disk, why the design system and the API client are copied in as source, and what that costs you.
Nothing in the project's package.json points back at our repository. That is deliberate, and
everything below follows from it: the design system, the API client, the schema and the proxy are
copied in as source, so nothing we publish can break your app — and an upgrade is a command that
reports a diff, never npm update.
The tree
src/modules/<id>/— one directory per module you picked, each mounting as its own root.index.tsbeside them is the registry, generated from what you chose;navGroups.tsxis the sidebar's grouping table, filtered to the same set.src/vendor/ui— the design system, imported as~ui.src/vendor/api— the typed GraphQL client, imported as~api. Both aliases are declared invite.config.tsandtsconfig.json.src/vendor/schemaandsrc/vendor/api/operations/are the two inputs the client was generated from: the Chatfuel SDL, and one document file per module.codegen.tsat the root andscripts/codegen/beside it are the generator, sonpm run codegenrewritessrc/vendor/api/generated/from a document you edited. Adding an operation is the cycle.src/operationDocs.tsis the barrel of everything the app is allowed to send. All three proxy hosts hand it over at startup, and a document that is not in it is refused.vendor/chatfuel-proxy— one proxy source tree with three hosts. In development it runs as a Vite plugin inside the dev server;server/entry.tsis the Node HTTP server that also serves the built client;api/chatfuel.tsis the Vercel function behind a rewrite. All three share the request handling, the WebSocket relay and the log scrubber.src/config/is the deployment's own settings —defaults.tsis ours and keeps receiving updates,app.tsis the overrides file, yours, and never touched again..env— your Chatfuel token, the workspace id, the app's name and mark. Written with mode0600, with.env.examplebeside it as the readable list of what the app takes..chatfuel/lock.json— every file the wizard wrote, where it came from, and the digest it had when it landed, plus the modules, the skills and the commit the content was pinned to. It is what makes an update a diff rather than a re-scaffold..claude/skills/chatfuel-<id>/(Codex:.agents/skills/chatfuel-<id>/) — one skill per installed module, each carrying that module's operations and the edges of the API behind it, pluschatfuel-update, which belongs to no module and is installed whatever you picked.CLAUDE.md(Codex:AGENTS.md) is the instructions file, with each module's handoff note inlined into it.supabase/migrations/— only when the modules that bring one are installed:0001_chatfuel_auth.sqlwithauth,0010_chatfuel_publishing.sqlwithpublishing,0020_chatfuel_admin.sqlwithadmin. They are idempotent and re-runnable, in the order they must be applied.public/logo.svgis the markVITE_APP_LOGOpoints at. Replace that one file and the app is marked; point the variable elsewhere to use a different name or an absolute URL.Dockerfile,.vercelignoreandscripts/deploy-vercel.mjsare the production paths that ship with the app. Deploy covers them.
Nothing you did not pick
Scaffolding is subtractive. The wizard copies content/shell whole, deletes the modules you did
not choose, regenerates the registry, filters the navigation table and prunes the tsconfig
paths that no longer resolve.
So a module you left out leaves no dead import, no commented-out route and no tsconfig path
pointing at nothing. What you get is not a template with holes in it — it is a project where the
code you did not ask for was never written. Adding one later is a re-run with --embed.
Vendored, not depended on
| In our repository | In your app | Reached as |
|---|---|---|
content/ui/src | src/vendor/ui | ~ui |
content/api-client/src | src/vendor/api | ~api |
content/schema | src/vendor/schema | read from disk by codegen |
content/codegen | scripts/codegen | run by npm run codegen |
content/vite-plugin-proxy/src | vendor/chatfuel-proxy | relative paths |
Two rules keep those trees portable: every internal import is relative, and ~ui imports nothing
but react and react-dom. Both hold in the code, and nothing checks either — they are
conventions kept by hand, and breaking one shows up in somebody's app rather than in our CI.
The copy is not quite byte-for-byte: the vendored trees' own unit tests are filtered out, because those tests are ours and shipping them would hand you failing runs for code you did not write. The shell is the exception and arrives whole, tests included — that suite is the app's own.
What it costs you: when we fix something in ~ui, your copy does not change until you ask for it.
In exchange, a component you disagree with is a file you can edit, and a release of ours cannot
break a deployment of yours. Upgrading an app is how you ask.
Standalone, or into a project you already have
npx @chatfuel/wizardThe default. You get the tree above: a Vite + React + TypeScript app, its dependencies
installed, .env written, skills in place, and npm run dev ready to run.
Next: your first change, or deploy.