Runtime & Deployment
Node Runtime
Section titled “Node Runtime”The primary way to run Zebric in development:
zebric dev --blueprint blueprint.toml --port 3000 --seedThis starts a Hono HTTP server with:
- Hot reload via WebSocket (blueprint changes apply instantly)
- SQLite database (auto-created from entity definitions)
- Server-side HTML rendering with Tailwind CSS
- CSRF protection, security headers, and session management
Engine Configuration
Section titled “Engine Configuration”When using the engine programmatically:
import { ZebricEngine } from '@zebric/runtime-node'
const engine = new ZebricEngine({ blueprintPath: './blueprint.toml', port: 3000, host: 'localhost', database: { type: 'sqlite', // or 'postgres' filename: './data.db', // SQLite path }, dev: { hotReload: true, seed: true, logLevel: 'info', // debug | info | warn | error logQueries: false, },})
await engine.start()Database Options
Section titled “Database Options”SQLite (default):
database: { type: 'sqlite', filename: './data.db'}PostgreSQL:
database: { type: 'postgres', url: 'postgres://user:pass@localhost:5432/mydb'}Workers Runtime
Section titled “Workers Runtime”Deploy to Cloudflare Workers using @zebric/runtime-worker — same blueprint format, running on Cloudflare’s edge network. The fastest way to start is copying starters/cloudflare-workers, which is a single-file entry point:
import { ZebricWorkersEngine } from '@zebric/runtime-worker'import type { WorkersEnv } from '@zebric/runtime-worker'import blueprintToml from './blueprint.toml'
export default { async fetch(request: Request, env: WorkersEnv, ctx: ExecutionContext): Promise<Response> { const engine = new ZebricWorkersEngine({ env, blueprintContent: blueprintToml, blueprintFormat: 'toml', }) return engine.fetch(request) },}WorkersEnv bindings: DB (D1, required), CACHE_KV, FILES_R2, SESSION_KV (all optional — enabling SESSION_KV turns on session-backed forms with CSRF protection).
name = "my-zebric-app"main = "worker.ts"compatibility_date = "2025-01-10"compatibility_flags = ["nodejs_compat"]
[[d1_databases]]binding = "DB"database_name = "my-zebric-db"database_id = "your-database-id" # from: wrangler d1 create my-zebric-db
# Optional[[kv_namespaces]]binding = "SESSION_KV"id = "your-session-kv-id" # from: wrangler kv:namespace create SESSION_KV
[[r2_buckets]]binding = "FILES_R2"bucket_name = "my-zebric-files"Create the D1 database (tables are created automatically from your entities on first request), then run locally or deploy:
wrangler d1 create my-zebric-db # copy the database_id into wrangler.toml
wrangler dev # local dev at http://localhost:8787, with D1/KV/R2 emulationwrangler deploy # deploy to your-app.your-subdomain.workers.devFor a working reference with all three bindings wired up, see examples/workers-blog.
Deployment
Section titled “Deployment”Docker
Section titled “Docker”FROM node:22-slimWORKDIR /appCOPY package.json pnpm-lock.yaml ./RUN npm install -g pnpm && pnpm install --prodCOPY blueprint.toml ./EXPOSE 3000CMD ["npx", "zebric", "dev", "--blueprint", "blueprint.toml"]Cloudflare Workers
Section titled “Cloudflare Workers”wrangler deployObservability
Section titled “Observability”Audit Logging
Section titled “Audit Logging”Security events are written as JSON to ./data/audit.log (configurable). Events include authentication attempts, access control denials, CSRF violations, data access, and suspicious activity. Each entry includes timestamp, event type, severity, user context, and sanitized metadata.
Sensitive fields (passwords, tokens, API keys) are automatically redacted.
Metrics
Section titled “Metrics”The engine exposes Prometheus-format metrics with zbl_* prefixed counters and histograms, registered on both the main app port and the admin port:
GET http://localhost:3000/metrics # main app portGET http://localhost:3030/metrics # admin port (127.0.0.1 only)Available metrics:
zbl_requests_total— total HTTP requestszbl_request_duration_ms— request duration histogram (buckets: 25, 50, 100, 250, 500, 1000, 2000ms)zbl_requests_by_route_total— requests per routezbl_requests_by_status_total— requests by status code family (2xx, 4xx, etc.)zbl_query_duration_ms— database query duration histogram per entityzbl_route_cache_hits/zbl_route_cache_misses— route cache performance
Health Check
Section titled “Health Check”GET http://localhost:3000/health # main app portGET http://localhost:3030/health # admin portReturns health status with a 200 (healthy) or 503 (unhealthy) status code.
Local Prometheus + Grafana Stack
Section titled “Local Prometheus + Grafana Stack”docker-compose.dev.yml includes Prometheus and Grafana services pre-configured to scrape your local Zebric instance.
# Prometheus onlydocker compose -f docker-compose.dev.yml up zebric-dev prometheus-dev
# Prometheus + Grafanadocker compose -f docker-compose.dev.yml up zebric-dev prometheus-dev grafana-dev- Prometheus UI: http://localhost:9091 — check Status → Targets to confirm
zebric-engineshowsUP, or query directly at/graph?g0.expr=zbl_requests_total - Grafana: http://localhost:3001 (default credentials
admin/admin). It has no Prometheus data source pre-configured — add one manually under Connections → Data sources, type Prometheus, URLhttp://prometheus-dev:9090(the Docker service name, notlocalhost)
The scrape config lives at monitoring/prometheus-dev.yml (10s interval, targets zebric-dev:3000). Update the targets field there if you change the app port or container name.
Prometheus data persists in the prometheus_dev_data volume between runs; docker compose -f docker-compose.dev.yml down -v resets it.
Admin Server
Section titled “Admin Server”The admin server runs on a separate port (default: 3030, bound to 127.0.0.1 only) and exposes:
| Endpoint | Description |
|---|---|
/health | Engine health status |
/metrics | Prometheus-format metrics |
/blueprint | Current parsed blueprint |
/state | Engine state |
/entities | Entity summary |
/pages | Page routes and layouts |
/workflows | Workflow definitions, job counts, and stats |
/workflows/visualization | HTML workflow graph visualization |
/traces | Request traces (with ?limit=N) |
/traces/errors | Error traces |
/traces/slow | Slow traces (with ?threshold=1000) |
/traces/stats | Trace statistics |
/schema-diff | Pending database schema changes |
/plugins | Loaded plugin list |