Admin

Base module reference

What the base admin layer ships out of the box.

Base module reference

The base layer (redelay/js-admin-nuxt4) ships these modules. Every project admin inherits all of them automatically — remove entries from the sidebar by overriding navigation, or disable a module by omitting its source (fork-and-trim).

ModuleSidebarPagesBacked by
auth(hidden — layout handles)/login, /logout, /forgot-passwordgo-framework/modules/auth — POST /auth/login, /auth/refresh, /auth/revoke
usersUsers → All Users/users, /users/:id, /users/groups, /users/groups/:idgo-framework/modules/users/admin — /admin/users/*
notifications(top-bar bell)/system/statusgo-modules/notifications — /notifications/* (SSE)
settingsSystem → Settings/settings/:group/:subgroup?go-framework/modules/settings/admin — /admin/settings/*
flowsFlows → All Flows / Templates / Deployments/flows, /flows/new, /flows/:id, /flows/:id/versions/:vid, /flows/templates, /flows/deployments, /flows/deployments/:idgo-flowdsl/flowexec/module/admin — /flows, /runs, /deployments
aiSystem → AI/ai/usage, /ai/breakdowns, /ai/pricinggo-ai/ledger/admin — /admin/llm/*
profilesSystem → Profiles/profiles, /profiles/:module/:kind/:idgo-framework/modules/settings/admin — /admin/profiles/*
searchSystem → Search/search, /search/:indexgo-modules/search/admin — /admin/search/*
dashboard(home)/ (redirects to /dashboard), /dashboard/health + aggregates from the above
modulesSystem → Modules/modules (module browser)go-framework/modules/modspec — /modules.json
mediaMedia → Library / Storage/media, /media/dashboard(adapter — wires into your storage module)

AI modules

Three related framework modules surface in the admin:

  • ai-llm — the provider registry. Reads every supported provider's credentials from env + admin settings and builds every provider that has credentials on Startup. Admin groups under /admin/settings/ai-llm: openai, anthropic, gemini, ovh, ollama, defaults. Each provider group has an api-key / base-url / default-model input that pre-populates with the current env value so operators can see what's wired up without digging through shell configs.
  • ai-guard — builds a guard.Guard backend (Qwen3Guard-Gen on OVH is free) from GUARD_PROVIDER env + admin settings. The redelay/llm-guard FlowDSL router node consumes it.
  • ledger — mounts /admin/llm/usage, /admin/llm/breakdowns, /admin/llm/pricing. The admin UI's System → AI section renders charts + an editable pricing table over this. Pricing updates take effect on the next LLM call — no restart.

Settings resolution — DB > ENV > YAML default

Every module ships a settings: block in its module.yaml. Each SettingField can declare an env_var: that names the environment variable used as a fallback when no admin-edited DB row exists. The settings.Service (in go-framework/modules/settings) resolves every read through three layers:

  1. DB — explicit admin-edited value in the _settings MongoDB collection.
  2. ENV — value of SettingField.EnvVar when set in the process environment.
  3. Default — the YAML default: on the field.

The admin API's POST /admin/settings/get delegates to the service, so GET /admin/settings/schemas + POST /admin/settings/get together tell the admin UI both the schema AND the current effective value for every key — no blank fields for env-backed configuration on first boot. Writing a value goes through the same service, which also publishes a settings.updated event on the EventBus so peer workers invalidate their local resolver cache — no container restart needed for a cluster-wide refresh.

By default, the ENV fallback uses the convention {MODULE_ID}_{KEY} — both uppercased, with hyphens in the module id replaced by underscores. Only declare env_var: when you need a non-conventional name (legacy vars, third-party conventions):

yaml
settings:
  id: mymodule
  groups:
    - id: mymodule.defaults
      settings:
        - key: api_key
          label: API key
          type: string
          # No env_var — service reads MYMODULE_API_KEY automatically.
          default: ""
        - key: license_key
          label: Legacy license key
          type: string
          # Non-conventional name — declare explicitly.
          env_var: LEGACY_LICENSE_KEY
          default: ""

Worked examples from the tree:

ModuleKeyImplicit envenv_var declared?
flowstudioembed_urlFLOWSTUDIO_EMBED_URLno
flowstudioui_pathFLOWSTUDIO_UI_PATHno
flowstudiolicense_keyFLOWSTUDIO_LICENSE_KEYyes → FLOWDSL_LICENSE_KEY
searchindex_prefixSEARCH_INDEX_PREFIXno
searchqdrant_urlSEARCH_QDRANT_URLyes → QDRANT_URL
ai-llmopenai_api_keyAI_LLM_OPENAI_API_KEYyes → OPENAI_API_KEY
ai-guardblock_flaggedAI_GUARD_BLOCK_FLAGGEDyes → GUARD_BLOCK_FLAGGED

No Go code is ever needed for the fallback — the settings.Service handles both the convention and the explicit override.

Vector search module

search — pluggable backend (Qdrant today, OpenSearch planned), index CRUD under /admin/search/*, semantic query under /search/*, FlowDSL nodes redelay/search-upsert + redelay/search-query. Embedding provider/model are runtime-switchable via admin settings, so the same deployment can move between OVH bge-m3 (€0.01/M) and local Ollama without redeploying.

FlowDSL Studio settings (admin-editable)

The flowstudio module (served on admin-api at /flowdsl) reads three settings at request time — edits take effect on the next page load without a restart:

SettingPurpose
flowstudio.license_keyRunner-tier license key. When set, the Studio enables live flow execution and run-event tailing. Empty means viewer-only.
flowstudio.embed_urlCDN or self-hosted base URL for the FlowDSL Studio JS/CSS bundle. Point at a local dev build for offline work.
flowstudio.ui_pathMount path (default /flowdsl). Change only if you reverse-proxy the admin on a non-standard prefix — the admin UI reads this to build deep-link URLs.

Empty settings fall back to env defaults (FLOWDSL_LICENSE_KEY, FLOWSTUDIO_EMBED_URL, FLOWSTUDIO_UI_PATH).

Studio deep-linking

Any admin UI button can open the Flow Studio pre-selected on a specific flow, version, template, or deployment by appending query params:

text
http://admin.yourapp.com/flowdsl?flowID=flow.xxxx&versionID=ver.yyyy
http://admin.yourapp.com/flowdsl?templateID=default
http://admin.yourapp.com/flowdsl?deploymentID=dep.zzzz

The Go shell parses these into a window.__FLOWSTUDIO__.initial block; the hosted Studio app also reads window.location.search directly. Use the useFlowStudioLink() composable from the base layer's flows module to generate links from project admin pages:

ts
const { linkTo, openFlow, openTemplate, openDeployment } = useFlowStudioLink()

// In a template:
<UButton :to="linkTo({ flowID, versionID })" target="_blank" external>
  Open in Studio
</UButton>

// Or programmatically:
openFlow(flowID, versionID)

linkTo reads the admin-api URL from runtimeConfig.public.apiBaseUrl and the mount path from runtimeConfig.public.flowdslUiPath (default /flowdsl, overridable via NUXT_PUBLIC_FLOWDSL_UI_PATH).

Shared components

ComponentPurpose
<EmptyState>Consistent "nothing here yet" card. Props: icon, title, description, bare, compact; slot actions.
<ResourceTable>Generic list wrapper with pagination, row actions, empty/loading states.
<ResourceDetailPage>Generic detail+edit page driven by ResourceConfig<T>.
<ResourceForm>Auto-renders a form from a FormSection[] config. Used inside ResourceDetailPage.
<ResourcePageHeader>Back button + title + description + actions slot.
<FlowStudioEmbed>Reusable Flow Studio widget wrapper with SSE run-event feed.
<SystemHealthWidget>Compact /health summary tile — used on the dashboard home.

Shared composables

ComposablePurpose
useApiFetch / $apiFetchAuth'd fetch wrappers. Auto-imported.
useResourceList, useResourceForm, useResourceApiGeneric list/form state + CRUD operations.
useModuleNavigationMerged navigation tree from all loaded modules.
useModulesModule registry + defineRedelayModule() runtime helpers.
useLoadingBarGlobal top-of-page progress bar.
useRelationMany-to-many relation helpers (user ↔ group, etc.).

Dashboard layout

layouts/dashboard.vue owns the sidebar + mobile topbar + session-expired modal. All pages with layout: 'dashboard' (the default for authenticated routes) sit inside it. Don't reach into it directly — extend via module navigation.

Runtime config keys

KeyDefaultPurpose
NUXT_API_URLhttp://localhost:8888Admin-api host seen by the browser
NUXT_API_INTERNAL_URL—Admin-api host seen by Nuxt server (SSR proxy)
NUXT_STANDALONEunsetSet to 1 when running the base layer alone; loads its own CSS
NUXT_PUBLIC_FLOWDSL_EMBED_URLhttps://studio.flowdsl.com/embed/v1Flow Studio embed bundle location
NUXT_PUBLIC_FLOWDSL_LICENSE_KEYunsetLicense key — unlocks runner tier in the embed