Admin

Overview

What the Redelay admin UI is, why it's split into two layers, and when to reach for each.

Admin UI Overview

Redelay ships a Nuxt 4 admin surface built from two repositories:

RepositoryRoleRuns on
redelay/js-admin-nuxt4Base layer — generic modules every Redelay deployment gets (auth, users, groups, settings, notifications, flows, AI usage, system status).admin-core :3002 standalone
redelay/adminProject 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:

ts
// 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 ai module, backed by go-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 by backend/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:

shell
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.

ProcessWhat it isBlank-importsPort (example)
cmd/apiPublic APIimports/common only:8083
cmd/admin-apiAdmin API + FlowDSL Studiocommon + cmd/admin-api/admin_imports.go (the */admin submodules):8084
cmd/redelayctlCLIimports/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:

  1. 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/common and runs on both binaries; its /admin submodule (admin-gated writes, id: <module>-admin, RequirePermission("admin:access")) goes in admin_imports.go and runs on admin-api only. A CI leak test greps cmd/api's dependency tree for any /admin path, so an admin route physically cannot reach the public binary.
  2. 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's routeRules, so the browser sees a single origin, there is no CORS, and admin-api's port need not be exposed publicly. Point it with NUXT_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