@vigilkids/cms-nuxt
v0.5.4
Published
Nuxt 3 module for OnEx CMS — composables, server routes, middleware, sitemap
Downloads
212
Readme
@vigilkids/cms-nuxt
Nuxt module for product-agnostic OneX CMS integration. It registers the CMS runtime configuration, auto-imported composables, Nuxt server endpoints, preview support, cache revalidation, route-policy URL generation, and optional @nuxtjs/sitemap integration.
The package owns the CMS client boundary and resource route policy. Consuming products own Nuxt page shells and choose the public URL shape through module options.
Install
pnpm add @vigilkids/cms-nuxt @vigilkids/cms-clientPeer Dependencies
nuxt >=3.15.0@vigilkids/cms-client ^0.3.1@nuxtjs/sitemapis optional and only required whencms.sitemap.enabledistrue
Module Setup
Configure the module with the cms key in nuxt.config.ts. Do not create CMS runtimeConfig values by hand; the module derives the server and public runtime config from these options.
export default defineNuxtConfig({
modules: ['@vigilkids/cms-nuxt'],
cms: {
apiUrl: process.env.NUXT_CMS_API_URL ?? '',
productCode: process.env.NUXT_CMS_PRODUCT_CODE ?? '',
defaultLocale: 'en',
webhookSecret: process.env.NUXT_CMS_WEBHOOK_SECRET ?? '',
routes: {
resources: {
index: '/resources',
category: '/resources/{category_slug}',
article: '/resources/{category_slug}/{slug}',
author: '/resources/authors/{slug}',
},
sourceResources: {
index: '/',
category: '/{category_slug}',
article: '/{category_slug}/{slug}',
author: '/authors/{slug}',
},
locale: {
defaultLocale: 'en',
prefixes: {
'zh-CN': 'zh',
},
includeDefaultLocale: false,
},
},
localeMap: {
'zh-CN': 'zh',
},
content: {
articleCollectionPath: '/api/cms/articles',
cmsProxyPath: '/cms-proxy',
},
categories: {
preload: true,
},
preview: {
enabled: true,
path: '/api/preview',
cookieName: '__preview_token',
cookieMaxAge: 1800,
},
revalidate: {
enabled: true,
path: '/api/_revalidate',
},
sitemap: {
enabled: true,
locales: ['en', 'zh-CN'],
sourcePath: '/api/cms/sitemap-urls',
},
},
})Module Options
| Option | Default | Purpose |
| --- | --- | --- |
| apiUrl | '' | CMS API base URL used by CmsClient, server routes, and SSR fetches. |
| productCode | '' | Sent as X-Product-Code when present. |
| defaultLocale | 'en' | Public default locale used by composables and route policy. |
| webhookSecret | '' | Server-only HMAC secret for the revalidate endpoint. |
| routes.resources | built-in defaults | Public resource URL patterns generated by useCmsRoutes, preview, revalidate, and sitemap. |
| routes.sourceResources | built-in defaults | CMS API resource URL patterns used to parse preview and sitemap input before rebuilding public URLs. |
| routes.locale | default locale policy | Locale prefix policy for generated public URLs. |
| content.articleCollectionPath | '/api/cms/articles' | Nuxt server endpoint for normalized article collection queries. |
| content.cmsProxyPath | '/cms-proxy' | Nuxt server proxy prefix used by client-side CMS fetches. |
| categories.preload | false | Fetches /categories during module setup and exposes the result in public runtime config. |
| preview | enabled by default | Preview route and preview cookie behavior. |
| revalidate | enabled by default | Signed ISR cache invalidation endpoint. |
| redirects | enabled by default | CMS redirect middleware with priority-aware matching and configurable in-memory cache TTL. |
| sitemap | disabled by default | @nuxtjs/sitemap provider integration and sitemap source endpoint path. |
| localeMap | {} | Maps public locale codes to CMS API locale codes. |
| localePrefixes | {} | Additional prefix input merged into routes.locale.prefixes. |
Resource Route Policy
Resource Route Policy is the package's public URL extension point. It keeps the CMS integration product-neutral: the package knows how to build and parse resource routes, while each product chooses its page structure.
Default resource patterns are:
const defaultResourcePatterns = {
index: '/',
category: '/{category_slug}',
article: '/{category_slug}/{slug}',
author: '/authors/{slug}',
} as constroutes.resources defines public site paths. routes.sourceResources defines the path shape returned by CMS preview and sitemap payloads when that source path differs from the public site path. routes.locale controls locale prefixes:
export default defineNuxtConfig({
cms: {
routes: {
resources: {
article: '/learn/{category_slug}/{slug}',
},
sourceResources: {
article: '/{category_slug}/{slug}',
},
locale: {
defaultLocale: 'en',
prefixes: { fr: 'fr' },
includeDefaultLocale: false,
},
},
},
})useCmsRoutes() exposes the resolved policy and route builder:
<script setup lang="ts">
const cmsRoutes = useCmsRoutes()
const articlePath = cmsRoutes.build('article', {
category_slug: 'guides',
slug: 'getting-started',
locale: 'fr',
}, true)
</script>A new product should change only:
cms.routes.resources,cms.routes.sourceResources, andcms.routes.locale- Nuxt page shells that map those URL patterns to UI components
The CMS client, preview endpoint, revalidation endpoint, category preload, fetch proxy, and sitemap source stay inside the package.
Content Endpoints
The module registers no-cache Nuxt server endpoints from the configured paths.
| Endpoint | Method | Behavior |
| --- | --- | --- |
| content.articleCollectionPath | GET | Returns Paginated<ArticleListItem> with locale, category_slug, q, page, and page_size query support. Search results are normalized into article cards. |
| ${content.cmsProxyPath}/** | any | Proxies client-side CMS requests to apiUrl, forwarding X-Product-Code and preview token headers when present. |
| sitemap.sourcePath | GET | Returns Nuxt sitemap entries for ?locale=... using route policy and CMS sitemap data. |
| preview.path | GET | Reads preview input, sets the preview cookie, and redirects to the route-policy-generated resource path. |
| revalidate.path | POST | Verifies x-webhook-signature and clears matching Nitro route cache entries. |
Categories
Set categories.preload to true when category navigation or route guards need category data at render time. The module fetches ${apiUrl}/categories during setup and exposes the data to useCmsCategories().
<script setup lang="ts">
const { currentCategories, getCategoryPath, categoryExists } = useCmsCategories()
</script>Use useCategories() when the page should fetch categories through @vigilkids/cms-client with useAsyncData.
Preview
Preview mode is enabled unless preview.enabled is false.
GET /api/preview?token=preview-token&resource=article&slug=guides/getting-started&locale=enThe preview endpoint:
- reads
token,resourceorresource_type,slug,locale, and additional route params from the query string - parses
slugwithroutes.sourceResourceswhen possible - fetches article detail when the public article pattern requires
category_slug - sets the configured preview cookie
- redirects to the generated public route with
_preview=1
useCmsPreview() returns { isPreview, previewToken, exitPreview }. useCmsPreviewToken() is available for lower-level integrations.
Revalidate
The revalidate endpoint is enabled unless revalidate.enabled is false. It expects a raw JSON CMS webhook payload signed with @vigilkids/cms-client/webhook HMAC verification.
POST /api/_revalidate
X-Webhook-Signature: sha256=...
Content-Type: application/json{
"event": "article.published",
"resource_type": "article",
"locale": "en",
"slug": "getting-started",
"category_slug": "guides",
"route_params": {
"category_slug": "guides",
"slug": "getting-started"
}
}The endpoint builds index, category, and resource paths with the configured route policy, then removes matching Nitro route cache entries.
Sitemap
There are two sitemap integration surfaces:
GET sitemap.sourcePath?locale=enreturns route-policy-generated sitemap entries for a single locale.sitemap.enabled: truehooks into@nuxtjs/sitemapand pushes CMS entries forsitemap.locales.
CMS sitemap entries can include resource types, route params, hreflang alternatives, images, last_mod, change_freq, and priority. The package converts them into Nuxt sitemap entries with public paths generated from the route policy.
Composables
All runtime composables are auto-imported.
| Composable | Purpose |
| --- | --- |
| useCmsClient() | Returns a CmsClient configured from public CMS runtime config and preview token state. |
| useCmsFetch<T>(path, options) | SSR fetches CMS directly and CSR fetches through content.cmsProxyPath. |
| useArticle(slug) | Fetches article detail, related articles, SEO meta, Open Graph meta, Twitter meta, and JSON-LD. |
| useArticleList(params) | Fetches article lists through CmsClient.getArticles. |
| useCmsArticleCollection(params) | Fetches the normalized article collection endpoint with category, search, and pagination support. |
| useCategories() | Fetches categories through CmsClient.getCategories. |
| useCmsCategories() | Reads preloaded category data and exposes category lookup/path helpers. |
| useAuthor(slug) | Fetches author detail and author articles. |
| useCmsPreviewToken() | Reads the preview token in SSR and CSR contexts. |
| useCmsPreview() | Exposes preview state and exit behavior. |
| useCmsRoutes() | Exposes the resolved route policy and route builder. |
| useBlogSeo(options) | Applies list-page SEO meta. |
| useHreflangLinks(resource, builder) | Injects alternate links from resource locales with caller-defined URL building. |
Compatibility
- Nuxt
>=3.15.0 @vigilkids/cms-client ^0.3.1- Vue runtime supplied by Nuxt
- Node.js version should satisfy the consuming Nuxt application's runtime requirements
