Installation & Updating
Generate Thunder UI into public/app with deno task generate:app, and know which of the two updates you need.
Thunder UI is not installed with a package manager. It is generated into your Thunder Framework project, from that project's root, so the app and the API it talks to live in the same repository.
Installing
Install thunder-core
Thunder UI depends on the thunder-core plugin for permissions, tenants, users and upload authentication. Install it and run its setup lifecycle first:
deno task add:plugin -n Huruf-Tech/thunder-core --setupConfigure the environment
Copy .env.example to .env inside public/app/ and fill in the values you need - at minimum the backend base URL and your auth strategy. See Environment Variables.
What generate:app Does
| Step | Result |
|---|---|
| 1 | Clones Thunder UI into public/app/ |
| 2 | Generates an SDK from your routes and schemas into public/www/sdk@<version>/ |
| 3 | Rewrites the app's package.json to point thunder-sdk at that SDK |
| 4 | Runs the install and the first build for you |
| 5 | The app derives its navigation and CRUD screens from that SDK |
Step 3 produces a local file: link to a versioned directory on the backend, not a package downloaded from a registry:
"thunder-sdk": "file:///../www/sdk@<latest-version>/npm"The thunder-sdk entry committed in the Thunder UI repository points at a published tarball instead. That is only the standalone default so the boilerplate can be built on its own - generate:app replaces it with the file: link above.
The web build outputs to www/ inside the app directory and is served under the base path /app (vite.config.ts sets build.outDir: "./www"; the build passes --base=/app).
www/ is gitignored - it is a build artifact, produced by generate:app on install and by npm run build afterwards. The .env files, by contrast, are committed deliberately.
Two Kinds of Update
Do not conflate these. It is the distinction developers get wrong most often - two independent things can go stale, with two different commands:
| What changed | What to run | What it refreshes |
|---|---|---|
| Your backend - a schema, or a route's shape | deno task generate:sdk, then rebuild | the generated screens: columns, filters, form fields |
| Thunder UI itself - a fix or new feature upstream | deno task generate:app --forceSync | src/core/ |
After changing a backend schema or route
The UI reads everything from the generated SDK, so a backend change is invisible until the SDK is rebuilt:
deno task generate:sdk -v <latest-version> --overwriteThen pick up the new SDK in the app:
generate:app relinks package.json to the new SDK version, reinstalls and rebuilds:
deno task generate:app --forceSyncThe file: link is still valid, so a rebuild from public/app is enough:
npm run buildChoose by whether the version changed: the thunder-sdk entry names a specific sdk@<version> directory, so a new version needs generate:app to rewrite that link. Overwriting the same version in place leaves the link valid.
Nothing in src/ needs editing. New modules appear in navigation on their own, new properties appear as columns and form fields, and a changed fieldHint or ref changes the control that renders - all from the schema. See Controlling the UI From the Backend.
Symptom to recognise: you added a field - or a whole module - on the backend and Thunder UI isn't showing it. The answer is almost always that the SDK has not been regenerated.
Updating Thunder UI itself
deno task generate:app --forceSyncReplaces src/core/ with the latest Thunder UI, relinks the SDK, reinstalls and rebuilds. Everything outside src/core/ is left alone. This is how bug fixes and security patches reach an existing app without discarding what you built on top of it.
It replaces src/core/ unconditionally and does not warn. Any edit inside that directory is lost, every time. Commit your own work first so the resulting diff is reviewable.