Overview
Admin UI Overview
Redelay ships a Nuxt 4 admin surface built from two repositories:
| Repository | Role | Runs on |
|---|---|---|
redelay/js-admin-nuxt4 | Base layer — generic modules every Redelay deployment gets (auth, users, groups, settings, notifications, flows, AI usage, system status). | admin-core :3002 standalone |
redelay/admin | Project admin — extends the base layer with project-specific modules. The redelay.com admin lives here; yours would sit alongside. | admin :3001 (or your own port) |
The layering model
The project admin extends the base layer as a Nuxt 4 layer:
// your-admin/nuxt.config.ts
export default defineNuxtConfig({
extends: [resolve(__dirname, '../js-admin-nuxt4')],
// project-specific overrides: theme, modules, runtime config…
})
Everything the base layer ships — layouts, composables, pages, components, plugins — is inherited automatically. Your project adds new pages and modules by dropping files into its own tree; the discovery module merges both trees at boot.
When to put work in the base vs. the project
Base layer — anything generic enough that every Redelay deployment benefits:
- Framework-level resources (users, groups, settings, flows, system status)
- LLM analytics (the
aimodule, backed bygo-ai/ledger) - Shared UI primitives (
EmptyState,ResourceTable,FlowStudioEmbed)
Project admin — anything specific to your product:
- Project-local CRUD modules (customers, products, invoices)
- Per-project branding (brand colours, logo, fonts)
- Integrations with your own backend services
- Example in this repo:
admin/modules/assistant/— chats + handoff inbox backed bybackend/modules/assistant/admin
How it's exposed
Both layers ship with a Dockerfile (infra/dockerfiles/Dockerfile.admin) and corresponding docker-compose services (admin-core, admin). The Makefile has convenience targets:
make admin-core # base layer standalone on :3002
make admin # project layer on :3001 (extends base)
The project admin proxies /api/v1/** to your Go admin-api (cmd/admin-api). Auth is JWT; the admin reads admin:access permission from the JWT claims.
Full project topology (backend + admin)
A Redelay project is three backend binaries plus one admin app, wired so the public surface can never reach admin routes and the browser only ever talks to the admin's own origin. This is the recommended structure for a new project.
| Process | What it is | Blank-imports | Port (example) |
|---|---|---|---|
cmd/api | Public API | imports/common only | :8083 |
cmd/admin-api | Admin API + FlowDSL Studio | common + cmd/admin-api/admin_imports.go (the */admin submodules) | :8084 |
cmd/redelayctl | CLI | imports/cli | — |
admin (Nuxt) | Thin app extending js-admin-nuxt4 | — | :3002 |
Ports are per-project examples (redelay uses 8001, goshop-pl 8080, gymtracer 8084) — pick a stack-local offset and keep it consistent.
The two halves and where each is documented:
- Backend split — which module lands on which binary, and the tests that
enforce it — is the Public / admin split convention
and Module inventory
in the go-framework reference. In short: a module's core package (public
self-service + safe reads) goes in
imports/commonand runs on both binaries; its/adminsubmodule (admin-gated writes,id: <module>-admin,RequirePermission("admin:access")) goes inadmin_imports.goand runs on admin-api only. A CI leak test grepscmd/api's dependency tree for any/adminpath, so an admin route physically cannot reach the public binary. - Admin UI — a thin Nuxt app extending the base layer (the rest of this
section). It proxies
/api/v1/**server-side to admin-api via the base layer'srouteRules, so the browser sees a single origin, there is no CORS, and admin-api's port need not be exposed publicly. Point it withNUXT_API_URL(host, browser-visible) /NUXT_API_INTERNAL_URL(in-cluster, SSR).
The rule that ties them together: the admin app targets cmd/admin-api,
never cmd/api. admin-api is the only binary that serves /admin/* (and,
behind the operator's VPN, the FlowDSL Studio). Pointing the admin at the public
api would 404 every admin CRUD call.
The auth-prefix contract
The admin posts login/refresh/revoke to /api/v1<authPrefix>/…. Redelay's
default is /auth, so out of the box the admin calls /api/v1/auth/login. If
your backend moved auth with AUTH_ROUTE_PREFIX — e.g. a stufio port that
serves /login — set NUXT_PUBLIC_AUTH_PREFIX to the same value so the
admin's calls line up. A mismatch shows up as a 404 on login. Everything else
(users, settings, flows) is unaffected because those paths are not relocated.
Next pages
- Getting started — stand up the base admin against a running backend in ~5 minutes.
- Layered architecture — how the two layers actually combine + the gotchas (
NUXT_STANDALONE, automatic_layerspage discovery, project-ownedtailwind.css). - Building a custom admin project — scaffold your own project admin from scratch.
- Building admin modules — the module structure, page discovery, navigation contract.
- Base module reference — what the base layer ships.
- Deployment — production builds, Docker images, env vars.