LogoZonai
zonai.dev

zonai.yaml Reference

Every configuration key available in zonai.yaml.

zonai.yaml is the project configuration file, placed at the project root next to pubspec.yaml. It controls source directory paths, server binding, and build targets.

All paths are relative to the directory containing zonai.yaml. CLI flags override any value set in this file (e.g. --port overrides port:).

Required Fields#

KeyDescription
version Semantic version string (e.g. 0.1.0 ). Zonai uses this to verify CLI/project compatibility.

Path Fields#

All paths are optional. Zonai uses sensible defaults so you only need to set a path if you deviate from the standard layout.

KeyDefaultPoints To
schemasPathlib/src/schemasTable definitions
configPathlib/src/configAppConfig files
operationsPath lib/src/operations Custom operations
rulesPathlib/src/rulesAuthorization rules
extensionsPathlib/src/extensionsLifecycle hooks
rateLimitPath lib/src/rate_limit Rate limit policies
cronsPathlib/src/cronsCron job definitions
emailTemplatesPath lib/src/email_templates HTML email templates
migrationsPath .zonai/migrations Generated SQL migration files
dataPath.zonai/dataSQLite database directory
imagesPath <dataPath>/images Uploaded photo files, plus the dashboard's favicon.ico and logo.png

Storage Fields#

KeyDefaultDescription
logDatabaseMaxSize (no limit) Hard ceiling on the log database file. A positive byte count, optionally suffixed b , kb , mb , gb or tb (powers of 1024) — e.g. 512mb .

logDatabaseMaxSize#

_log lives in its own database file, which is what makes a ceiling on it expressible at all: SQLite's cap bounds a file, so on a shared database it would be hit by whichever write arrived first — your application's inserts just as easily as a log line.

It is off by default, and that is deliberate. Once the ceiling is reached, log writes fail and keep failing until retention frees space. That costs you observability at exactly the moment something is going wrong, so it is not imposed on a project that did not ask for it. Retention, the nightly reclaim, and the disk-full error already handle the ordinary case.

Set it when you want a guarantee that this one table can never be what fills a volume:

logDatabaseMaxSize: 512mb

Pick a size that is generous relative to your retention window — the cap is a backstop for a runaway, not a substitute for retention. When it is reached, the server keeps serving requests and keeps printing to the console; it prints one line to stderr saying log records are no longer reaching the database, and the dashboard's log view stops gaining entries.

Removing the key lifts the cap on the next server start. Nothing is stored in the database file, so there is no reset step. An unparseable value is rejected at startup rather than ignored — a ceiling you believe you have but do not is worse than none.

There is no equivalent for _rate_limit: it is bounded by its own retention window rather than by growth, and capping it would start failing the writes that enforce your rate limits.

Server Fields#

KeyDefaultDescription
host localhost Bind address. localhost binds the IPv4 loopback 127.0.0.1 — reachable from this machine only. Any other value is bound as written: 0.0.0.0 for every IPv4 interface (containers, direct external access), ::1 for IPv6 loopback.
port8080HTTP port.

CLI --host and --port flags take precedence over these values. zonai build copies this file into build/, so the bundle inherits them. See Server Binding for examples.

Build Settings#

The optional buildSettings block enables cross-compilation:

KeyDefaultValues
targetOs Current OS linux, macos, windows
targetArchCurrent archarm64, x64

Use this when building on macOS to deploy to a Linux server. Only linux targets can be cross-compiled; a macos or windows target must match the build machine. See Cross-Compilation.

Client Settings#

The optional client block configures zonai gen client, which generates a typed Dart client from your schema. It is read only by that command — no other command and no server startup depends on it.

KeyDefaultDescription
output (none — required) Directory to write the generated client into, relative to zonai.yaml
package false Also emit a pubspec.yaml, making the output a standalone package
packageName (none) Name for that pubspec. Only read when package: true
tables.exclude(none)Project tables to leave out
tables.include (none) Zonai system tables (_-prefixed) to generate anyway
names.<table>.row (derived) Override the generated row-class name for one table

output is required and has no default#

The server project cannot be an app dependency — zonai_schema pulls in native SQLite — so the generator writes into a directory the app owns. There is no default because the destination belongs to an app this project knows nothing about. Running zonai gen client without it prints the block to add and exits non-zero.

client:
  output: ../app/lib/gen/zonai

Pass --output <dir> to override it for a single run.

Choosing tables#

By default every table your project declared is generated, and every table zonai owns is not. System tables are the _-prefixed ones — _jwt, _log, _photos, _push_jobs, _rate_limit — and they are skipped because a generated, autocompleting JwtApi would read as a supported API over tables a consumer must never touch.

client:
  output: ../app/lib/gen/zonai
  tables:
    exclude: [audit_log]    # a project table you don't want in the client
    include: [_log]         # a system table you genuinely read

exclude always wins over include. The command reports every table it skipped, so nothing disappears silently.

Renaming generated types#

Every generated name for a table derives from one stem, so names.<table>.row moves all of them together — row: BlogPostsRow also yields BlogPostsId, BlogPostsApi and client.blogPosts. This is the escape hatch for a table name that is not a usable Dart identifier.

client:
  output: ../app/lib/gen/zonai
  names:
    posts:
      row: BlogPostsRow

Complete Example#

version: 0.1.0

# Server binding
host: localhost
port: 8080

# Source paths (all have defaults — only set if you deviate)
schemasPath: lib/src/schemas
configPath: lib/src/config
operationsPath: lib/src/operations
rulesPath: lib/src/rules
extensionsPath: lib/src/extensions
rateLimitPath: lib/src/rate_limit
cronsPath: lib/src/crons
emailTemplatesPath: lib/src/email_templates

# Generated paths
migrationsPath: .zonai/migrations
dataPath: .zonai/data
imagesPath: .zonai/data/images

# Optional hard ceiling on the log database (omit for no limit)
logDatabaseMaxSize: 512mb

# Cross-compilation (omit to build for current platform)
buildSettings:
  targetOs: linux
  targetArch: x64

# Typed client generation (omit unless you run `zonai gen client`)
client:
  output: ../app/lib/gen/zonai
  package: false
  tables:
    include: [_log]

Minimal zonai.yaml (most projects only need this):

version: 0.1.0