Files
vue-seo-layer/app/plugins/seo-head.ts
Jakub Zych 160b53b2f5 feat: CMS head and one JSON-LD graph on every server-rendered page (tracer)
- Nitro middleware resolves page requests once and hands the answer to the
  render (event.context.seo); the route middleware reuses it
- useCmsSeo: html lang, hreflang links, og:locale and exactly one JSON-LD
  script with one @graph (CMS nodes plus useSchemaNode nodes, merged by @id)
- local module (configKey seo): cms (alias of public.seo.enabled),
  breadcrumbs, links.newTabHint, rootFiles, resolveFiles
- GET /api/__seo__/resolve for client navigation through the Nuxt server
- smoke harness: count=, exact header=, noheader=, reqheader=, repeated
  options, resolves/apicalls/noreport lines, --no-site; v0.1.1 suite runs
  unchanged against a backend without /site
2026-11-04 09:15:26 +01:00

19 lines
811 B
TypeScript

// One head entry for the whole app, following the resolve answer of the
// current page (useCmsSeo). tagPriority 'critical' makes its tags win over
// the same tags a page or another module sets (unhead keeps the lower
// weight), so editor values from the SEO plugin override the content
// defaults; a value the answer lacks leaves the page's own tag in place.
//
// The answer comes from the route middleware (seo.global.ts): during SSR it
// is the one the Nitro middleware already resolved (event.context.seo), kept
// in useState so hydration fetches nothing; on client navigation it is
// fetched again.
import { seoEnabled } from '../utils/seo.ts'
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig()
if (!seoEnabled(config.public.seo)) return
useCmsSeo(useSeoAnswer())
})