Admin Panel
The CWA admin panel is shipped as part of the layer and requires no setup. It becomes accessible at /_cwa for any user with ROLE_ADMIN.
Admin Routes
| Route | Purpose |
|---|---|
/_cwa | Dashboard |
/_cwa/pages | Browse, create, and edit page records |
/_cwa/layouts | Browse and edit layout records |
/_cwa/routes | Manage routes — path, name, publish state |
/_cwa/data | Browse any resource by type; drill into individual records |
/_cwa/data/[type] | List view for a specific resource type |
/_cwa/data/[type]/[iri] | Edit view for a single resource |
/_cwa/settings | Site config, SEO settings, maintenance mode, robots |
/_cwa/users | List and manage user accounts |
/_cwa/users/[iri] | Edit an individual user |
All /_cwa routes are client-only (SSR disabled). Access is guarded inside the admin index page itself: non-admins are redirected to / on mount, and signing out while on an admin route sends you back to /. There is no admin route middleware to reuse — see Protecting Your Own Pages.
Edit Mode
When an admin visits a content page, an edit bar appears at the top of the page (rendered by <CwaAdminHeader>). Clicking "Edit" toggles edit mode:
const cwa = useCwa()
cwa.admin.isEditing // whether edit mode is active (a reactive boolean, not a ref)
cwa.admin.toggleEdit() // open/close edit mode
In edit mode, every rendered component gains a selection overlay. Clicking a component opens its resource manager panel (<CwaAdminResourceManager>).
The Resource Manager
The resource manager is a panel that slides in when a component is selected. It shows tabs for editing the component's data fields. The standard tabs (resource info, UI styles, publish, ordering) ship with the Nuxt module. Custom tabs are added using useCwaResourceManagerTab.
Custom Manager Tab
Create a Vue component in app/cwa/components/[ComponentName]/admin/[TabName].vue. Use useCwaResourceManagerTab to register it:
<!-- app/cwa/components/Title/admin/SEO.vue -->
<template>
<div class="p-4 space-y-4">
<CwaUiFormLabelWrapper label="Meta Title">
<CwaUiFormInput
v-model="metaTitleModel"
placeholder="Override page title for search engines"
/>
</CwaUiFormLabelWrapper>
</div>
</template>
<script setup lang="ts">
import { useCwaResourceManagerTab, useCwaResourceModel } from '#imports'
const { exposeMeta, iri } = useCwaResourceManagerTab({ name: 'SEO', order: 10 })
const { model: metaTitleModel } = useCwaResourceModel<string>(iri, 'metaTitle')
defineExpose(exposeMeta) </script>
defineExpose(exposeMeta) is required — without it the tab has no name and won't be ordered. The composable also returns the currently-selected iri, so the tab needs no iri prop of its own.The tab appears in the resource manager whenever a Title component is selected.
cwa.admin API
| Member | Type | Description |
|---|---|---|
isEditing | boolean | Whether edit mode is active. Reactive — reads inside a computed or template track correctly — but not a ref, so no .value |
toggleEdit(state?) | (boolean?) => void | Toggle or set edit mode |
emptyStack() | () => void | Deselect the current component |
emitRedraw() | () => void | Force re-render of all component overlays |
setNavigationGuardDisabled(disabled) | (boolean) => void | Turn the edit-mode navigation block on/off |
navigationGuardDisabled | boolean | Whether the block has been manually disabled |
The guard's effective state is cwa.navigationDisabled — on the root cwa object, not cwa.admin.
Navigation Guard
While edit mode is active, the admin navigation guard blocks programmatic route changes (router.push, back, and friends) so an in-progress edit isn't lost. It aborts the navigation silently — there is no confirmation dialog. Add ?cwa_force=true to the target route to bypass it.
To disable the guard programmatically (e.g. after a save):
cwa.admin.setNavigationGuardDisabled(true)
Separately, navigating away while a component is mid-add triggers a discard-confirmation dialog.