The Admin Panel
The CWA has no separate CMS URL. Editing happens on the live page — the admin bar overlays the front end, and the manager panel slides up from the bottom when you click a component.
Access
Log in at /login with ROLE_ADMIN credentials. Once logged in, the admin bar appears at the top of every page.
The Admin Bar
The bar shows:
- Edit / Done toggle — activates inline editing mode
- A menu linking to the admin pages: Layouts, Pages, Data, Routes, Users and Settings
- The current page's name with a cog — click it to open that page's settings
- A loading indicator for API activity
- A warning icon with a count beside Edit / Done when the page has component groups that your code no longer shows (see Stranded Component Groups)
Edit Mode
When edit mode is active:
- An empty ComponentGroup shows a dashed placeholder with a single + hotspot — click it to open the "Add Component" dialog
- Click any component to select it and open the manager panel
- The manager panel slides up from the bottom and shows your component's admin tabs
- Right-click a component in the live page layout (not in the
/_cwa/admin pages) to open a context menu listing the nested resources under the cursor — use it to select the parent component position or group instead of the innermost component
The Admin Pages (/_cwa/)
| URL | Purpose |
|---|---|
/_cwa/layouts | List layouts; create new; assign uiComponent |
/_cwa/pages | List pages; assign layout and page template |
/_cwa/pages/[iri] | Page settings: title, SEO, layout |
/_cwa/data | Browse PageData categories (blog, products, events…) |
/_cwa/data/[type] | List and create records for a data type |
/_cwa/data/[type]/[iri] | Edit an individual data record |
/_cwa/routes | Manage URL paths; create redirects; view the route tree |
/_cwa/users | List users; create/edit accounts and roles |
/_cwa/settings | Site config: name, SEO defaults, robots, sitemap, maintenance mode |
/_cwa/orphaned | Review and delete orphaned component groups, positions and components, and stored files nothing uses (see Orphaned Resources) |
Managing Routes
The /_cwa/routes admin page manages URL paths for pages and redirects.
Editing a path
The path editor uses a prefix + suffix layout. For top-level routes the prefix is / (root) and you type the full slug. For child routes (e.g. a blog article nested under /blog) the Prefix select also offers the parent path — pick it and you only type the suffix. This makes it clear what the final URL will be without having to remember the parent path.
An SEO recommendation appears below the input showing a full path preview built from the parent prefix and a slugified version of the page title. Click it to apply.
When you save a changed path, a dialog asks Update child routes? Confirming it renames all child paths to keep them under the new parent prefix and creates redirects from every old path automatically. Without it only the parent route is renamed (with a redirect from its old path); children keep their old paths.
Visibility
The route editor (a page's Routes tab, also reached from /_cwa/routes) has a Visibility setting that decides whether the public can see the page:
- Live — public now
- Scheduled — public from the date and time you pick in the Goes live field. Times are in your computer's time zone: hover the calendar button to see the zone and its offset at that date, for example "Times are in Europe/London, UTC+01:00"
- Not live — hidden, with the path still reserved. Use it to take a page offline without deleting its route
The change is saved with Save Route.
Choosing Live on a route that is already live keeps its go-live date, which is shown beside the control. Only a route that was scheduled or not live gets the current time. Module builds before 003ab4a9 (cwa-nuxt-module#341) overwrote the date with the current time. Because a route can't go live before its parent, that also moved its child routes' effective dates forward.
Visibility is inherited: a page can't go live before its parent route does, so if the parent is scheduled or not live, the route editor tells you what is holding the page back. The routes list and each route's summary show the state that actually applies, with the go-live date for scheduled routes.
As an admin you can still open, preview and edit a scheduled or hidden page. Visitors get a 404, and it stays out of the sitemap until it goes live. For the full rules see Scheduling and Taking Routes Offline.
Redirects
Each route entry shows two sections:
Forward visitors to — the outbound redirect field. Set this to send visitors arriving at this URL to a different destination. When a redirect target is set and edit mode is active, the admin panel suppresses the redirect so the page remains navigable for editing.
Incoming redirects — the redirectedFrom list. Shows all other routes that currently forward visitors to this route. Useful for auditing redirect chains and identifying stale paths.
Redirects can be chained. The API walks the chain when it serialises a route and returns the final destination as redirectPath — the Nuxt module's route middleware then issues a 308 to it. A chain that loops back on itself is rejected with a circular reference error rather than being followed.
To seed redirects in fixtures, see Data Fixtures → Seeding Redirects.
Adding a Component
- Enter edit mode
- In an empty group, click its + hotspot. In a group that already has content, click a component to select it, then use the manager panel's CTA button — Add Before / Add After (or Add to Start / Add to End when the ComponentGroup itself is selected)
- The "Add Component" dialog lists available component types
- Select one — if
instantAdd: trueis set innuxt.config, it's added immediately; otherwise a config panel appears first - The new component is added to the group
Reordering
Select a component and open the manager panel's Order tab. Turn on Enable reordering, then use Move Up / Move Down or type a position number. The module patches sortValue on each ComponentPosition automatically.
The Manager Panel
When you click a component, the manager panel shows all admin/*.vue files for that component type as tabs. Each tab is defined by a call to useCwaResourceManagerTab({ name: 'Tab Name' }) in the Vue file.
Changes in the admin tabs apply to the draft version of the component. Click Publish in the panel to make changes live.
Scheduling a Publish
A component with a draft can be published now or at a later time. Select it and open the manager panel's Publish tab. It says whether the component is Draft, Scheduled or Live, and for a draft it has a Schedule toggle:
- Schedule off: click Publish now to publish the draft straight away.
- Schedule on: pick a date and time, then click Schedule. The state changes to Scheduled. Type into the day, month, year, hour and minute, or use the calendar button. Minutes go in steps of 5, and times before you opened the tab can't be chosen.
A scheduled draft opens with the toggle on. To keep it unpublished, click Cancel schedule, which clears the date.
Scheduling needs @cwa/nuxt 2.0.0-alpha.2 or later.
Visitors see the new version from the scheduled time: the API holds the draft back until then and caps cached responses at that time, see Scheduled Publication and Cache Lifetime. Nothing is pushed to open browsers at that moment, so a page that is already open shows the change the next time it loads.
Deleting is on the panel's Info tab. There is no duplicate/clone action.
Stranded Component Groups
A page can have component groups attached that nothing in your code shows any more. The usual cause is renaming a group's reference: <CwaComponentGroup reference="hero"> becomes reference="banner", the page gets a new, empty banner group, and the old hero group stays attached with all its content. Visitors no longer see that content, and nothing else tells you.
When this happens, a warning icon with a count appears beside Edit / Done in the admin bar. It counts the stranded groups: groups attached to the layout, to the page at any depth, or to a component on the page, whose reference no <CwaComponentGroup> in your templates declares for that owner. It appears once the page has loaded, whether or not edit mode is on.
The check reads your code, not the rendered page. At build time the module scans your layout, page and component templates in app/cwa/, including each component's ui/ variants, for <CwaComponentGroup> declarations. In dev the scan runs again whenever a .vue file changes. A group behind a v-if, in a closed tab or in a lazy component counts as declared, even though it isn't mounted yet.
It finds:
- a renamed
reference - a group on a page or component whose template, or the UI variant it has selected, no longer declares it
- a group on the layout that no template in the app declares
- an older group keyed to a component's draft IRI, left behind after the component was published
<CwaComponentGroup> directly in a template, or in an ordinary component that the template uses by its tag. The scan follows auto-imported tags, default imports, #components imports and defineAsyncComponent(() => import('…')). It can't follow a component rendered through <component :is>, h() or resolveComponent(), so a group declared only inside one of those is reported as stranded, even though visitors see it. A wrapper component that receives location as a prop and passes it to <CwaComponentGroup> is fine.The reference is read from the declaration, so give it as a plain string: reference="hero" or :reference="'hero'". The location is recognised when it's :location="iri" or publishedIri in the template itself, $cwa.resources.layoutIri.value, or a fixed location-reference. Any other location, such as a prop in a wrapper, matches that reference on any owner.
Reporting switches off for the whole site, rather than guessing, when a template or a component it uses can't be read:
- the template isn't HTML, such as
lang="pug" - the file or its script doesn't parse
- a
<CwaComponentGroup>takes its props from an object withv-bind="…" - a
<CwaComponentGroup>has a computedreferenceand a location the scan doesn't recognise, such as a wrapper that passesreferencedown as a prop
The build warns once for each file and reason that switches reporting off, so you can fix it:
stranded component group warnings are off for the whole site, because <file> binds reference at a location that cannot be classified, so it could declare any group. Pass a literal reference, or a location the module recognises (the template's iri or publishedIri, the layout IRI, or a literal location-reference).
The reason is one of could not be read, could not be parsed, has a template that is not HTML, binds its props with a v-bind object, or binds reference at a location that cannot be classified. Only files reachable from a CWA template are scanned, so a wrapper nothing uses never warns. This warning arrives in the release after 2.0.0-alpha.4 (#367); on 2.0.0-alpha.4 reporting switches off silently.
A layout, page or component whose template the scan didn't see is skipped, and none of its groups are reported.
Click the icon to open Stranded component groups. Each group is listed by its reference, with its IRI and the components in it, and has two actions:
- Merge: pick a group the page shows from Merge into…, then click Merge and confirm. The components move to the end of that group, in their order, and the emptied group is deleted. An empty group can't be merged; delete it instead.
- Delete: deletes the group after the usual confirmation. Like any group delete, it takes its positions with it, and any component in them that isn't used anywhere else.
allowedComponents doesn't include its type, the original group is kept and the modal lists the components that didn't move. The others have already moved to the target group.This needs @cwa/nuxt 2.0.0-alpha.4 or later (cwa-nuxt-module#360).
Orphaned Resources
Content you remove from a page can leave records behind: a component nothing displays any more, an empty position, or a group nothing owns. Uploads can leave stored files behind too. The API can report these, and the admin lets you review and delete them. What counts as orphaned is set by the API, see Orphaned resource report.
This needs @cwa/nuxt 2.0.0-alpha.3 or later. The files report is newer, see Orphaned files.
Scanning from site settings
Site settings (/_cwa/settings) has an Orphaned resources section. It shows when each report was last scanned, as Components: and Files: lines, or Never scanned, with three buttons:
- Scan now asks the API for a new component report.
- Scan files asks the API for a new file report. It is separate because listing storage can be slow.
- Review orphaned resources opens
/_cwa/orphaned.
When the last scans found anything, a notice at the top of settings reads "Orphaned resources discovered" with a Review now button. It counts orphaned resources and orphaned files, and missing files separately, for example "2 resources and 1 file are no longer used anywhere on the site. 1 file is missing from storage." Unknown files aren't counted.
Opening settings only reads the stored reports. It never starts a scan, so each report is only as fresh as its last scan. The component report is refreshed by Scan now, a delete on /_cwa/orphaned, or the API's scan-orphaned command, which can run on a schedule and email you when the orphans change. The template's production deploy runs it every day at 03:00 London time (see Daily Orphan Scan), so there the component report is at most a day old. The file report is refreshed by Scan files, a file delete on /_cwa/orphaned, or the API's scan-orphaned-files command.
After a scan is requested, the page reads the report again every 2 seconds, for about 10 seconds, until its scan time changes. If the API queues the scan for a Messenger worker, the report only changes once a worker runs it, so with no worker running the page shows "The scan has been requested but has not finished yet" and the report stays as it was. The worker setup is in Orphaned resource report.
Reviewing and deleting
/_cwa/orphaned shows the last component report in three sections: Components, Component positions and Component groups, each with its count. Before the first scan it has a Scan button instead. The page doesn't link from the admin menu; open it from site settings.
Each row shows the resource's IRI (and, for a component, its collection) with two buttons:
- View shows the resource's data as JSON. For a component this is the published version, or the draft if the component was never published. Up to
@cwa/nuxt2.0.0-alpha.3, View showed a 404 for a component that was never published. - Delete deletes that resource.
Each section with rows has Delete all, which deletes that section's rows. Delete everything asks the API to delete every orphan it finds when it checks again, including anything that has become unused since the last scan. Every delete asks you to confirm first.
- A component group takes its positions with it, and any component in those positions that isn't used anywhere else.
- A component takes its own component groups, unless something else uses them, along with their positions and the components used only there.
Delete, Delete all and Delete everything each send one request to POST /_/orphaned_resources/delete. The API checks each resource again first and deletes only what is still orphaned, along with what it contains, and an orphaned component takes its unused draft with it. It then refreshes the stored report, and the page reads it again.
Above the buttons, the page then says what was deleted, counting everything the delete took with it, such as "Deleted 2 components and 1 component group, including anything they contained." If nothing went, it says "Nothing was deleted." Each resource you asked for that wasn't deleted is listed with its IRI and the reason:
| Reason | Meaning |
|---|---|
| Kept: it is in use again, or it is a draft. | The API's fresh check didn't find it orphaned: something uses it now, or it is a draft copy. |
| Already gone. | It no longer exists. |
A report can be minutes old, so something may have been reused since. The rest of your selection is still deleted.
The page shows the report the API stored after the delete. Anything else that has changed since appears when you click Scan again.
@cwa/nuxt2.0.0-alpha.3 or later. It also needs api-components-bundle 2.0.0-alpha.6 or later, which added the delete endpoint (#353). Development builds before it sent one DELETE per row, which left the draft of an orphaned component behind as a component of its own.Orphaned files
Below the component report, /_cwa/orphaned has a Files report with its own Scan files button. A file scan looks at the storage your uploadable fields use and finds stored files that nothing references, and resources whose file is missing. Before the first file scan the section has only the Scan files button. The scan request and the 2-second re-reads work as for components.
The report has three sections. Each row shows the file's path and its storage adapter.
| Section | What it lists | What you can do |
|---|---|---|
| Orphaned files | Files nothing references that the API can show it uploaded | Delete one, Delete all listed, or Delete everything |
| Unknown files | Files nothing references but that don't look like CWA uploads, so something else may own them | Nothing. Remove them from storage yourself if you are sure, or exclude their location with the API's orphaned_files.excluded_paths |
| Missing files | Resources whose file doesn't exist in storage, with the resource's IRI | View shows the resource. Fix it by uploading the file again or editing the resource. Nothing here deletes it |
Every delete asks you to confirm, then goes to the API, which checks each file again and deletes only what is still orphaned. Delete removes the path from every adapter where it is orphaned. Delete everything also deletes files that have become unused since the last scan, and never touches unknown or missing files. The page then reads the report again and says what happened, such as "Deleted 3 files.", with each path that was kept and why:
| Reason | Meaning |
|---|---|
| Kept: something references it again. | A resource uses the file now. |
| Already gone. | The file no longer exists. |
| Could not be deleted from storage. | The storage adapter refused or failed the delete. |
| Kept: it does not look like a file the CWA uploaded, so it is never deleted from here. | It is an unknown file. |
From bundle 2.0.0-alpha.8 (#372), deleting a resource also deletes its stored files, however it is deleted, so new orphaned files should be rare. The report is mainly for files that cascading deletes left behind on earlier versions. What the API scans and which files it will delete are described in Orphaned files report.
@cwa/nuxt2.0.0-alpha.4 (cwa-nuxt-module#362) and api-components-bundle 2.0.0-alpha.8 (#373), or later.