Deployment
The dashboard is the single deployable artifact: one Nuxt app serving the UI, the control plane, and authentication from one origin.
Build and run
aube run build
node apps/dashboard/.output/server/index.mjs
nuxt build emits a self-contained .output/ bundle — no node_modules needed at runtime. The server listens on port 3000 by default; override with PORT.
Production checklist
- Session secret — set
NUXT_BETTER_AUTH_SECRET(this exact name; the development fallback is ignored in production). Generate withopenssl rand -base64 32. - Postgres — point
DATABASE_URLat a managed database and apply the schema once withaube run db:migrate. See Database. - Auth policy — decide
AUTH_ENABLE_SIGNUP, GitHub OAuth credentials, and organization flags, then build with them set: the auth pages capture capabilities at build time. See Authentication. - Mail — configure Resend (
RESEND_API_KEY;MAIL_PROVIDER=resendis optional) or setMAIL_PROVIDER=smtpwith its SMTP variables. With neither,consoleonly logs. Required if invitations or organizations are enabled. See Mails. - Control plane — issue bearer tokens via
AGENT_ZERO_CONTROL_PLANE_TOKENS, allow-list repositories viaAGENT_ZERO_CONTROL_PLANE_REPOSITORIES, and grant modes viaAGENT_ZERO_CONTROL_PLANE_MODES. Without them, mutations are rejected. See Protect endpoints. - Webhooks — set
GITHUB_WEBHOOK_SECRETandAGENT_ZERO_CHECKOUT_PATH; the webhook route fails closed (503) until both are set. Configure the webhook on the source-control side per Source-control providers. - Isolated execution — production runs that write require
runner.isolation: containerin repository policy, with an image and resource limits. The includedLocalRunneris for trusted local development only. See the Safety model. - Model provider — select the provider in repository policy and set its credential environment variable. See Model providers.
Task history storage
Task history uses the ViteHub KV Runtime Helper: filesystem-backed fs-lite by default (.data/kv), with Cloudflare KV, Deno KV, or Upstash available as driver configuration without touching application code. Records are redacted before they are written.
Hosted sandboxes
For hosted execution, the provider-neutral RunnerPool supports vendor adapters (ViteHub, Cloudflare Sandbox, Vercel Sandbox were evaluated — see Sandbox providers). Quota checks run before provisioning, leases are bounded, and expired sandboxes are stopped.
Rebuild triggers
Rebuild the app whenever you change:
AUTH_ENABLE_SIGNUP,GITHUB_CLIENT_ID/GITHUB_CLIENT_SECRET, or organization flags (login-page capabilities are captured at build time);- anything in
packages/*(the server bundle inlines them).
Vercel
apps/dashboard ships its own vercel.json so it can be deployed as a Vercel project with Root
Directory set to apps/dashboard: the install and build commands cd back to the workspace root
so aube and Turborepo resolve the monorepo correctly.
The build command sets NITRO_PRESET=vercel. nuxt.config.ts registers vite-hub/nuxt with a
deployment preset, and that preset pins Nitro's own, so the build target is a deliberate choice
rather than something Nitro auto-detects: without that variable every build emits the self-hosted
node-server bundle in .output/, which Vercel cannot serve — it fails with No Output Directory
named "dist" found. With it, config/env.ts resolves the vercel preset and the build writes
.vercel/output (Vercel's Build Output API) instead. VITEHUB_HOSTING selects the same target and
takes precedence.
Because they select the target, NITRO_PRESET and VITEHUB_HOSTING are declared on the app build
tasks in turbo.jsonc: Turborepo's strict environment mode hides a variable a task does not
declare (NITRO_* is forwarded by its Nuxt framework inference, VITEHUB_HOSTING is not), and
declaring them keeps the target in the cache key so a self-hosted build is never restored into a
hosted one. Both .output/** and .vercel/output/** are listed as build outputs for the same
reason.
On a hosted preset the KV Runtime Helper resolves the host's own driver rather than the filesystem
one, because a serverless function has nowhere durable to write: on Vercel that is Upstash, so set
KV_REST_API_URL and KV_REST_API_TOKEN or task history fails at runtime. See
Database.
vite-hub@0.0.3's vercel plan checks for a server function at
.vercel/output/functions/__server.func/index.mjs, while the installed nitropack@2.13.4 emits —
and routes to — __fallback.func. The bundle is correct; only the name ViteHub looks for is not,
so nuxt.config.ts links that name to the emitted function for the length of the check and removes
the link afterwards. That bridge is registered as a Nitro module, not under nitro.hooks: a
handler placed there replaces the preset's own handler for the same hook, and the vercel preset
writes config.json and every .vc-config.json from its compiled hook — without them the
directory exists but Vercel cannot read it, and the build fails with the same missing-dist error.
Delete the module and viteHubVercelEntryName in config/env.ts once a ViteHub release
expects the preset's own layout.apps/marketing sets NITRO_PRESET the same way. It composes no ViteHub integration, so the
variable only picks its Nitro preset, and it has no KV store to configure.
Documentation site
apps/docs is not deployed with the dashboard. It ships its own vercel.json so it can be
deployed as a separate Vercel project with Root Directory set to apps/docs: the install and
build commands cd back to the workspace root so pnpm and Turborepo resolve the monorepo
correctly, and the build output is .output.
Internationalization
The dashboard ships English and Italian. Locale policy lives in packages/i18n; the dashboard wires it into @nuxtjs/i18n with strategy: 'no_prefix' (the locale is a user preference, not a URL segment).
Tech stack
Agent Zero is a TypeScript monorepo. Every tool below was chosen deliberately; the toolchain rules in AGENTS.md are binding for contributors and coding agents alike.