Overview
The @cwa/nuxt module ships as a Nuxt layer. A layer is a self-contained Nuxt application whose pages, layouts, components, and plugins are merged into your project automatically. You add the layer with extends: ['@cwa/nuxt/layer'] in nuxt.config.ts (see Module Setup for why the package name beats a node_modules path), and the layer registers the module for you — not the other way round. Registering the module directly under modules leaves out the layer's auth pages, admin panel, root layout and middleware.
What the Layer Provides
Pages (auto-registered)
CWA registers several pages automatically. These work out-of-the-box and require no configuration:
Auth pages (public):
| Route | Purpose |
|---|---|
/login | Email + password login |
/forgot-password | Request a password reset email |
/reset-password/[username]/[token] | Set a new password |
/verify-email/[username]/[token] | Verify email on registration |
/confirm-new-email/[username]/[newEmail]/[token] | Confirm email address change |
Content pages (dynamic, SSR):
| Route | Purpose |
|---|---|
/ and /* | Catch-all CWA content route — resolves routes from the API manifest and renders your layout + page template |
Admin panel (client-only, admin users only):
| Route | Purpose |
|---|---|
/_cwa | Redirects to /_cwa/pages |
/_cwa/pages | Manage page records |
/_cwa/layouts | Manage layout records |
/_cwa/routes | Manage routes |
/_cwa/data | Browse and edit any resource by type |
/_cwa/settings | Site config, SEO, maintenance mode |
/_cwa/orphaned | Review and delete orphaned resources |
/_cwa/users | User management |
Layout
cwa-root-layout is registered by the layer. It is the Nuxt layout used on all CWA content pages. It mounts the admin header and resource manager panel when auth.isAdmin is true, then renders the <slot /> — which is where your CWA-resolved layout component appears.
cwa-root-layout is applied automatically to every page that doesn't set its own layout (change the name it registers under with the cwa.layoutName option).
If you add a page of your own that isn't CWA-managed content, disable CWA route resolution for it:
definePageMeta({ cwa: { disabled: true } })
Otherwise the global CWA route middleware tries to fetch a Route resource for that path.
Route Middleware
Besides the global route resolver, the layer ships two named middleware for guarding your own pages. They only run on pages that ask for them:
| Middleware | Requires |
|---|---|
cwa-auth | A signed-in user |
cwa-admin | A user with ROLE_ADMIN |
definePageMeta({ middleware: 'cwa-admin' })
Signed-out visitors are sent to /login with a redirect parameter, and the login page returns them after sign-in. See Protecting Pages.
Reusable UI Components
The layer registers a set of <CwaUi...> components that the admin panel uses internally. These are also available in your own templates:
| Component | Description |
|---|---|
<CwaUiFormInput> | Styled text input |
<CwaUiFormLabelWrapper> | Label + control layout — wrap CwaUiFormInput/Select/Toggle in it; the controls themselves take no label prop |
<CwaUiFormSelect> | Styled select with popover option list |
<CwaUiFormToggle> | Boolean toggle switch |
<CwaUiFormFile> | File upload control (used in upload admin tabs) |
<CwaUiFormButton> | Styled button |
<CwaUiAlertInfo> | Info notice block |
<CwaUiAlertWarning> | Warning notice block |
<CwaUiProgressBar> | Animated progress bar |
<CwaUiHamburger> | Mobile hamburger icon |
<CwaUiDatePicker> | Date and time field with a calendar popover, in UTC ISO strings. See Date and Time Pickers |
<CwaUiCalendar> | Calendar for a date, a range or several dates |
<CwaUiInputDate> | Segmented date and time field without the calendar |
These components are styled with CWA's bundled CSS (cwa.css). They are primarily intended for admin and auth pages, but you can use them anywhere.
Overriding Layer Pages
Any page the layer provides can be overridden by creating the same path in your project's app/pages/ directory. Nuxt's layer merging means your file wins:
app/pages/login.vue ← your override, takes precedence
← layer's /login is ignored
See Auth Pages for override examples.