The CWA is in heavy development
The CWA is still in alpha and not ready for production - some code and implementations are likely to change. If you would like to try out the CWA, please enjoy what we have provided and feel free to provide feedback, or get involved on GitHub.
DraftConfiguration

Site Config & SEO

Admin settings panel, siteConfig API, per-page SEO from page data, sitemap, maintenance mode, and robots configuration.

CWA's SEO layer is built on top of @nuxtjs/seo — the full Nuxt SEO bundle is available to you out of the box, including useSeoMeta, useSchemaOrg, robots meta, sitemap generation, and OG image support. CWA layers on top of it with API-driven site config and automatic per-page meta from your Page and PageData records.

Site-wide settings are stored in the API and cached in Pinia. Admins change them at /_cwa/settings — no deploy required.

Default Settings

The module ships with sensible defaults:

KeyDefaultDescription
siteName'CWA Web App'Used in <title> concatenation
fallbackTitletrueShow siteName when a page has no title
concatTitletrueAppend | siteName to page titles
indexabletrueWhether search engines should index the site
canonicalUrl''Base URL for canonical tags
sitemapEnabledtrueInclude CWA routes in the generated sitemap
sitemapXml''Custom sitemap XML served at /__sitemap__/cwa-custom.xml and added to the sitemap index when non-empty. Validated on save — an invalid document aborts saveConfig() and returns totalConfigsChanged: 0
maintenanceModeEnabledfalseServe a 503 to all non-admin visitors
robotsText''Custom robots.txt content
robotsAllowNonSeoCrawlerstrueAllow non-SEO bots
robotsAllowAiBotstrueAllow AI crawlers
robotsRemoveSitemapfalseOmit the sitemap directive from robots.txt

Accessing Site Config

Use cwa.siteConfig.config — it's a reactive store getter:

const cwa = useCwa()

const siteName = computed(() => cwa.siteConfig.config.value?.siteName)
const isMaintenanceMode = computed(() => cwa.siteConfig.config.value?.maintenanceModeEnabled)
const sitemapEnabled = computed(() => cwa.siteConfig.config.value?.sitemapEnabled)

Or use useCwaSiteConfig directly for utility functions:

import { useCwaSiteConfig } from '#imports'
const { defaultSiteConfig } = useCwaSiteConfig()

Saving Config Changes (Admin)

const result = cwa.siteConfig.saveConfig({
    siteName: 'My Rebranded Site',
    maintenanceModeEnabled: false,
    robotsAllowAiBots: false
})

// result.totalConfigsChanged — number of keys that actually changed
// Only changed keys are PATCHed to the API

Per-Page SEO

The module's CWA page component automatically applies SEO meta from the current page or page data:

SourceApplied as
Page.title<title>
Page.metaDescription<meta name="description">
PageData.titleOverrides Page.title
PageData.metaDescriptionOverrides Page.metaDescription

They're set with useHead() at tagPriority: 101 — one step below the default priority — so any useHead() or useSeoMeta() call of your own overrides them. Titles are composed across nesting depth (deepest page first, joined with |), falling back to a title-cased last URL segment when fallbackTitle is enabled.

// In a page template component
useHead({
    title: computed(() => `${articleHeadline.value} - In-depth Guide`)
})

Default OG Image

The module ships a default Open Graph image template via nuxt-og-image. Every CWA page automatically gets a dark-background social card containing the CWA logo, the page title, and the meta description — no setup required.

The template is CwaDefault.satori.vue (a Satori/SVG renderer). It receives:

PropSource
titleCurrent page or pageData title
descriptionCurrent page or pageData meta description

Previewing locally — visit /__og-image__/image/your-path/og.png to preview the generated image for any route.

Overriding the OG image

Per-page override — call defineOgImage() in your page template component. Your call replaces the module default for that route:

// In your page template <script setup>
defineOgImage('MyCustomTemplate', {
    title: pageData.value?.data?.headline,
    imageUrl: pageData.value?.data?.heroImage?.contentUrl
})

Project-wide override — create app/components/og-image/CwaDefault.satori.vue in your application. Nuxt resolves component names from the app layer first, so this shadows the module's default template for all pages that haven't overridden per-page.

Open Graph and Twitter Cards

Social card meta tags (og:title, og:description, og:image, twitter:card) are too content-specific for the module to set automatically — add them in your page templates alongside your own content fields:

useSeoMeta({
    ogTitle: computed(() => pageData.value?.data?.headline),
    ogDescription: computed(() => pageData.value?.data?.summary),
    ogImage: computed(() => pageData.value?.data?.heroImage?.contentUrl),
    twitterCard: 'summary_large_image'
})

Maintenance Mode

When maintenanceModeEnabled: true, the module's server middleware throws a 503 Service Unavailable (statusMessage: 'Website under maintenance', message "We will be back up and running as soon as possible"), which Nuxt renders through your app/error.vue. There is no redirect and no dedicated maintenance page — customise the screen by handling error.statusCode === 503 in your error page.

Exempt from the check: /login, /__nuxt_error, anything under /_cwa, plus /sitemap.xml, /sitemap_index.xml, /robots.txt and /__sitemap__/*. Signed-in users whose api_component JWT carries ROLE_ADMIN or ROLE_SUPER_ADMIN (and hasn't expired) bypass it entirely, so admins can still reach the site to turn maintenance mode off.

Sitemap

The sitemap is generated by @nuxtjs/sitemap. The module registers a CWA source endpoint (/__sitemap__/cwa-urls) that returns every Route in the API as a loc entry — there is no publish or visibility filtering, and no per-route priority or changefreq. Set defaults through @nuxtjs/sitemap's own sitemap config in nuxt.config, or add a second source, if you need more than URLs.

To publish a hand-written sitemap instead, put the XML in sitemapXml (admin → Settings) — it's served at /__sitemap__/cwa-custom.xml and added to the sitemap index.

Stop CWA contributing routes at all if you manage the sitemap externally — the source then returns an empty list:

// Admin settings panel → Sitemap → Disabled
// Or programmatically:
cwa.siteConfig.saveConfig({ sitemapEnabled: false })

Nuxt Config Overrides (Static Defaults)

You can set site config defaults in nuxt.config — these are merged with the API's stored values, with the API winning for any key it defines:

// nuxt.config.ts
cwa: {
    siteConfig: {
        siteName: 'My App',
        canonicalUrl: 'https://www.example.com'
    }
}

This lets you ship a sensible default without requiring a database record on first boot.