# Architecture

> Three things with three lifetimes — a CLI that writes an app, an app you own, and the Chatfuel API it talks to.

Page: https://sdk.chatfuel.com/docs/concepts/architecture
Markdown: https://sdk.chatfuel.com/docs/concepts/architecture.md

`npx @chatfuel/wizard` is a CLI that writes an app. When it finishes it is gone — no framework of
ours between you and your code, nothing in `package.json` pointing back at our repository, and
nothing we publish later that can change what is already on your disk.

So "Chatfuel SDK" is three things with three lifetimes, and most confusion about it comes from
treating them as one.

```
@chatfuel/wizard  ──writes──▶  your app  ──talks to──▶  Chatfuel
   (npx, once)                (yours, forever)          (GraphQL + WebSocket)
```

## The CLI runs once [#the-cli-runs-once]

The wizard's whole job is a directory copy with edits. It copies `apps/shell` whole, deletes the
module subtrees you did not pick, regenerates the module registry, filters the navigation table,
copies the three source packages in, and rewrites the marked import lines that point at them.

Module manifests are read at that moment and never again: there is no manifest, no registry and no
plugin loader inside the app at runtime. What the manifests decided is already baked into the files
you have.

## The app is yours [#the-app-is-yours]

What lands is a React + Vite project. Three trees inside it came from us as source rather than as
dependencies — the design system under `~ui`, the typed API client under `~api`, and the proxy
under `vendor/chatfuel-proxy` — and none of them is reachable through `node_modules`. That trade is
the subject of its own page: [vendoring, not depending](/docs/concepts/vendoring).

## The API it talks to [#the-api-it-talks-to]

`~api` is a generated, typed GraphQL client: queries and mutations over HTTP, live updates over
`graphql-ws`, and REST only for uploads. The schema snapshot and the generated documents are
refreshed by scripts rather than hand-edited.

In the browser the client is created with no token at all — it points at your own origin and the
proxy attaches the token server-side. See [the token boundary](/docs/concepts/token-boundary).

Errors arrive in one envelope shape, and classification reads the GraphQL `extensions.code` rather
than the HTTP status. A module therefore never parses a transport error itself; it gets a typed
refusal with a code it can branch on.

## What lives where in the repository [#what-lives-where-in-the-repository]

If you are reading the source rather than the app it writes, the three sides are three directories.

| Path                                                               | What it is                                                          |
| ------------------------------------------------------------------ | ------------------------------------------------------------------- |
| `packages/wizard`                                                  | the CLI                                                             |
| `apps/shell`                                                       | the app it writes — the template is the real app, not a copy of one |
| `packages/ui`, `packages/api-client`, `packages/vite-plugin-proxy` | the source trees it copies in                                       |
| `modules/<id>`                                                     | per module: the manifest, the handoff note and the agent skill      |
| `apps/shell/src/modules/<id>`                                      | per module: the React tree                                          |

A module is two halves in two places, which is the one thing about this layout that surprises
people — see [modules](/docs/concepts/modules).

## What this costs you [#what-this-costs-you]

Owning the code means owning the bugs in it. Nothing we publish can break your app, and equally
nothing we publish can fix it: an upgrade is a re-run of the wizard or a diff you apply yourself,
never `npm update`.
