Build Command#
zonai build --flavor prod --release
This deletes any existing build/ directory and creates a new one containing everything needed to run on a server. No Dart SDK is required on the target machine.
-
--flavor prodselectsdb_config.prod.dartand.env.prod— see Config Flavors. -
--releasecompiles the workers without Dart asserts — see Release mode. -
buildSettingsinzonai.yamlpicks the target OS/architecture — see Cross-Compilation.
What Gets Bundled#
Paths inside build/ mirror your project's configured paths; with the defaults:
build/
├── zonai # Server + CLI (zonai.exe for a Windows target)
├── zonai.yaml # Copy of your settings file (host, port, paths)
├── .zonai/
│ ├── executables/ # Worker binaries (config, rules, operations, extensions, rate limits, crons)
│ ├── migrations/ # SQL migrations (<migrationsPath>)
│ ├── data/images/ # favicon.ico / logo.png, if present (<imagesPath>)
│ └── lib/ # Target's native libraries (cross-compiled builds only)
└── lib/src/email_templates/ # HTML email templates, if any (<emailTemplatesPath>)
Not included: source code, the SQLite database, and .env files — their values are already compiled into the binaries.
build/zonai is one of two things, and both serve identically:
-
Project-linked (when your project resolves
package:zonai): compiled from your project's generated entry, with operations and rules running in-process. -
The published
zonaibinary (the usual case): operations and rules run in the worker binaries beside it. The build log saysBundling the published zonai binary: <reason>.
The OpenAPI spec and the /db/stream* live-stream routes are built into the server, so /swagger.json,
/swagger.yaml and db.listen work in production without extra files.
Release mode#
--release switches Zonai from development to production behavior. Pass it to build
(or compile) when building, and to serve when running.
| Development (default) | --release | |
|---|---|---|
| Worker compile |
--enable-asserts
—
assert(...)
in your config, rules, extensions, operations, rate limits and crons runs
|
No asserts |
serve file watchers / recompiling |
On — edits recompile workers | Off — serves the binaries already built |
serve
keyboard shortcuts (
c
,
m
,
p
,
r
,
q
)
|
On | Off |
| Generating migrations from schema changes | On | Off |
| Applying pending migration SQL at startup | On | On |
build/zonai itself is always compiled without asserts; --release controls the workers beside it. A server started with
--release still shuts down gracefully on SIGTERM / SIGINT.
Migrations are generated during development and committed; build copies them into the bundle, and
serve --release applies any that are pending when it opens the database. There is no separate migrate step on deploy.
Pre-Build Checklist#
-
.env.prodcontains every value your code reads withString.fromEnvironment— or the signing secrets will be injected at runtime instead -
db_config.prod.dartreads secrets withString.fromEnvironment— never hard-coded -
host/portinzonai.yamlare what the server should use (usually0.0.0.0in a container), andbaseUrlis the public URL — see Server Binding - Pending migration files are committed — they are bundled as-is
Deploying the Bundle#
Copy build/ to the server:
rsync -avz build/ user@server:/opt/myapp/
Start the server from that directory:
cd /opt/myapp && ./zonai serve --release
The server applies pending migrations and begins accepting requests. To ship changed code, config or env values, run
zonai build --flavor prod --release again and redeploy the whole directory.
See Running the Server for process manager setup.