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
sitemapEnabledtrueGenerate /sitemap.xml from routes
maintenanceModeEnabledfalseRedirect all non-admin visitors to maintenance page
robotsText''Custom robots.txt content
robotsAllowNonSeoCrawlerstrueAllow non-SEO bots
robotsAllowAiBotstrueAllow AI crawlers

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 route resolution middleware automatically applies SEO meta tags 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

These are wired into @nuxtjs/seo via useSeoMeta(). You can add your own after the middleware runs and your call will win:

// 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 redirects all non-admin visitors to /_cwa/maintenance. Admins are not redirected and can still access the site to turn maintenance mode off.

Override the maintenance page by creating app/pages/_cwa/maintenance.vue.

Sitemap

/sitemap.xml is auto-generated from all Route resources in the API. Only published, public routes are included. Customise priority and changefreq per-route in the admin under /_cwa/routes.

Disable sitemap generation if you manage it externally:

// 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.