Frontend
apps/dashboard is a Nuxt 4 app and the single deployable artifact: it serves the UI, the control plane, and authentication from one origin.
Module-per-feature layout
Application code lives under modules/<feature>/ rather than Nuxt's default flat directories. Each feature is a real Nuxt module: its index.ts registers its own components/, composables/, and utils/ directories, and Nuxt discovers it by scanning modules/, so nothing has to be listed in nuxt.config.ts. apps/marketing uses the same layout.
apps/dashboard/
├── app/
│ ├── app.vue
│ ├── pages/
│ │ ├── (auth)/login.vue
│ │ ├── (dashboard)/index.vue
│ │ └── (organizations)/…
│ ├── layouts/
│ ├── plugins/
│ ├── types/
│ └── assets/css/
└── modules/
├── shared/ # cross-feature components, composables, and utils
├── auth/ # login and session UI
├── dashboard/ # task history, queue, approvals
├── organizations/ # organization management
├── i18n-strip-empty/ # drops untranslated placeholder keys from the bundle
└── vitehub.ts # ViteHub KV inside Nuxt's Nitro build
Route groups — (auth), (dashboard), (organizations) — organize pages without affecting URLs. Pages are gated through routeRules with auth: { only: 'user' | 'guest' } and a layout assignment.
Styling and icons
- UnoCSS with
preset-wind4— utility classes, not Tailwind. The CSS entry isapp/assets/css/main.css. - @nuxt/icon with the Lucide collection, fully client-bundled (
provider: 'none') so no icon request leaves the app. - @nuxtjs/color-mode drives theming (
dataValue: 'theme').
Server composition
The server/ directory hosts the API transports, webhook ingress, and the Better Auth mount — see API overview and Authentication.
nuxt.config.ts registers vite-hub/nuxt as a module entry, composing the ViteHub KV Runtime Helper into Nuxt's own Nitro build and giving the server a KeyValueStorage backed by fs-lite on the filesystem (.data/kv) when self-hosted, with Cloudflare KV, Deno KV, or Upstash as drop-in driver configuration. Its deployment preset comes from config/env.ts (node unless NITRO_PRESET or VITEHUB_HOSTING names a host), and that preset fixes both the Nitro preset the build emits and the KV driver — see Deployment.
Internationalization
The interface ships English and Italian through @nuxtjs/i18n (strategy: 'no_prefix'), with dictionaries split by scope. See Internationalization.
Auth capability flags
The login page's capabilities (signup enabled, GitHub button) are published via appConfig — captured at build time, deliberately not runtime-overridable. Rebuild after changing auth policy variables. See Authentication overview.
Testing
- Unit and component tests live in
test/unit/andtest/nuxt/. aube run test:browserbuilds the dashboard, starts the production preview on port 5678, and runs the Playwright suite against the real/api/auth/**endpoints with an in-memory Better Auth adapter (AUTH_E2E_MEMORY=true, set only for that preview server) — the suite creates and signs in its own throwaway account instead of using a live database.- Use
aube --filter @agent-zero/dashboard run test:browser:uifor Playwright UI mode.
Organizations
The dashboard ships with optional multi-user organizations: teams that share visibility into task history and approvals.
Mails
packages/mail owns transactional email: Maizzle-based templates plus a small provider layer. The dashboard uses it for organization invitations and other auth-driven messages.