Repository navigation
Deploy Recipes
One section per host. The framework ships no host config file, no generator and no adapter: every
host below builds the same docker/Dockerfile and runs the same image once per role. A recipe is
the handful of settings that host asks for, and nothing more. A host joins this page by a PR that
ran it, and each section says whether it was executed or not executed, with its date.
What every host needs, whatever its words for it:
| Setting | Value |
|---|---|
| build source |
docker/Dockerfile, context the app root |
| port | the host injects PORT; web binds exactly it, every interface |
| health path |
/readyz (may it take traffic) — never a TCP check |
| release command | the image's own entry with ROLE=migrate: env ROLE=migrate bun apps/web/server.ts, exit 0 before any role serves |
| services | one per role from the one image, ROLE set on each: web, worker, scheduler; sync only once realtime is on (Deployment) |
| environment |
ULTIMATE_ENV=production, DATABASE_URL, ULTIMATE_CURSOR_SECRET, STORAGE_SIGNING_SECRET (unless S3_ENDPOINT and S3_BUCKET are set), SESSION_SECRET, APP_URL — x env init --production writes them all with fresh secrets; copy the values into the host's secret store. NODE_ENV=production x env check --json asks what a deployed boot would refuse |
As of 2026-11-03 — executed, and on every push: the compose-deploy CI job runs
docker/deploy-proof/compose.sh
on a fresh scaffold.
x env init --production # .env.production: secrets generated, gitignored, mode 600
x build --target docker # ultimate-app:dev
x deploy # migrate, then web, worker, scheduler; backfill last
curl -fsS http://127.0.0.1:3000/readyz| Setting | Here |
|---|---|
| build source |
x build --target docker; --image names any other tag |
| port |
3000:3000 published by web, 3001:3001 by sync
|
| health path | each service's healthcheck: /readyz for web/sync, /metrics for the rest |
| release command | the migrate service, run --rm; every role waits on service_completed_successfully
|
| services |
docker/docker-compose.prod.yml, one per role |
| what it loses | nothing to a free tier — it is your box. web and sync stay at one replica each: one host port, one binder |
APP_URL and SYNC_URL are written for localhost: set the host your users reach before they do.
As of 2026-11-03 — executed: the deploy-proof CI job installs a scaffold into kind with
x deploy --method helm and upgrades it under load with zero failed requests.
| Setting | Here |
|---|---|
| build source | your registry; x deploy --method helm --image <repo>:<tag>
|
| port | the chart's per-role Service; ingress.host sets APP_URL on sync
|
| health path |
startupProbe, readinessProbe on /readyz, liveness on /healthz
|
| release command | the chart's migrate Job, a pre-install/pre-upgrade hook |
| services | one Deployment per role, an HPA each |
| what it loses | nothing to a free tier; the cluster is the cost |
As of 2026-11-03 — not executed.
| Setting | Here |
|---|---|
| build source |
fly launch --no-deploy --dockerfile docker/Dockerfile; the fly.toml it writes is yours |
| port |
[http_service] internal_port = 8080 and [env] PORT = "8080"
|
| health path | [[http_service.checks]] path = "/readyz" |
| release command | [deploy] release_command = "env ROLE=migrate bun apps/web/server.ts" |
| services |
[processes] is a command per group, and the image's ENTRYPOINT reads ROLE: one Fly app per role (fly apps create <app>-worker), each with ROLE in [env]
|
| what it loses | machines that stop when idle stop worker and scheduler with them (Tutorial 5) |
As of 2026-11-03 — not executed.
| Setting | Here |
|---|---|
| build source | a Docker web service, Dockerfile path docker/Dockerfile, context .
|
| port | Render injects PORT
|
| health path | Health Check Path /readyz
|
| release command | Pre-Deploy Command env ROLE=migrate bun apps/web/server.ts — a paid instance type only |
| services | a web service with ROLE=web; a background worker per other role, same repository and Dockerfile |
| what it loses | a free web service sleeps when idle, and free has no background worker and no pre-deploy command: run the migrate one-off yourself before promoting |
As of 2026-11-03 — not executed.
| Setting | Here |
|---|---|
| build source |
RAILWAY_DOCKERFILE_PATH=docker/Dockerfile on each service |
| port | Railway injects PORT
|
| health path | Healthcheck Path /readyz
|
| release command | Pre-Deploy Command env ROLE=migrate bun apps/web/server.ts on the web service |
| services | one service per role from the same repository, ROLE set on each |
| what it loses | the trial's credit, then usage billing; a service with serverless sleep on stops worker and scheduler with it |
As of 2026-11-03 — not executed. Heroku has had no free dynos since 2022-11-28.
| Setting | Here |
|---|---|
| build source |
heroku stack:set container, then a heroku.yml with build: { docker: { web: docker/Dockerfile } }
|
| port | Heroku injects PORT
|
| health path | none on the router; the drain still answers /readyz for a check you run |
| release command |
release: { image: web, command: ['env', 'ROLE=migrate', 'bun', 'apps/web/server.ts'] } in heroku.yml
|
| services | one process type per role in run:, each env ROLE=<role> bun apps/web/server.ts
|
| what it loses | no free tier at all |
As of 2026-11-03 — not executed as a deploy. The windows CI job boots a scaffold's binary
and gets 200 from /healthz; no scaffold has been served from a VM this way
(Tutorial 5, Bare VM).
| Setting | Here |
|---|---|
| build source |
x build --target binary --out .x/app, started from the app root with the source beside it |
| port |
PORT in each unit's environment |
| health path |
/readyz, from your proxy or monitor |
| release command |
ROLE=migrate .x/app once, before the units restart |
| services | one systemd unit per role, Environment=ROLE=<role>
|
| what it loses | the image's reproducibility: the box's Bun and node_modules are the runtime |
Ultimate — v29.4.0 As of 2026-10. The full-stack framework where the primary developer is an AI agent: bunx create-ultimate myapp → Getting started · live demo. MIT licensed. What npm serves is npm view @ultimat3/core version, never this line, and this footer is the only page that stamps a version.
Repository · Issues · Changelog · llms.txt
Edits to these pages are synced from wiki/ in the repository — change the file there, not the wiki, or the next sync overwrites it.
Start
- Getting started
- Installation
- Shapes
- Bare VM
- Project layout
- Migrating an existing app
- Compared to other stacks
Tutorials
- 1 · First app
- 2 · First feature
- 3 · Auth and admin
- 4 · Jobs and realtime
- 5 · Deploy free
- 6 · Growing up
Primitives
- The eight primitives
- Building your own base
- Actions
- Entities and migrations
- Policies and authz
- Queries and live queries
- Client data
- Jobs and workflows
- Scheduled tasks
- Routes and render modes
Capabilities
- Realtime
- Caching and invalidation
- Batching and preloading
- N+1 detection
- PWA and offline
- Client navigation
- MCP and AI
- Agents
- Admin dashboard
- Scraping
- Auth
- Notify
- Storage and uploads
- Feature flags
- SEO
- Static assets
Cross-cutting
- I18n
- Theming
- UI components
- Interface rules
- Timezones and dates
- Money
- Outbound HTTP
- Resource management
- Migrations and backfills
- Testing
- CI: the gate across parallel jobs
Reference