Commit Graph

12 Commits

Author SHA1 Message Date
Jakub Zych
3abc986f42 feat: route report and drift check at server start
- the module writes #seo-routes (static paths and route patterns) from the
  resolved pages; options seo.routeReport, seo.pagination and
  seo.htmlSitemap reach the public runtime config
- seo-route-report: POST /registry/routes once per process with the
  route-report token, one retry after 60 s on failure, nothing without a
  token, with the layer off or with routeReport false
- seo-drift: one "[vue-seo-layer] drift:" warning per mismatch between
  the CMS's site answer (URL patterns, pagination, HTML sitemap paths)
  and the build
- GET /api/__seo__/site and useSeoSite()
- smoke grammar routereport and log, fixture registry route, drift run
2026-11-04 11:49:21 +01:00
Jakub Zych
9cc2cda924 feat: noindex for declared and signed-in routes
- app plugin seo-route-robots: a page whose meta sets requiresAuth: true
  gets robots noindex, nofollow, a page with seo.robots gets its value,
  a path under seo.noindexRoutes gets noindex, nofollow; meta tag above
  the CMS head entry and X-Robots-Tag during SSR, never on staging
- requiresAuth and seo added to Nuxt's page meta extraction keys
- playground /konto, /szkic and /prywatne with their smoke lines
2026-11-04 11:49:14 +01:00
Jakub Zych
b4680af0e3 feat: the build fails when an indexable route renders only in the browser (tracer)
- lib/guard.ts: pure checks (isNoindex with Nitro route-rule patterns,
  findOffenders over the app's ssr flag, every merged route rule,
  .client.vue pages and experimental.inlineRouteRules)
- module options seo.noindexRoutes and seo.indexable; declared noindex
  routes get X-Robots-Tag: noindex, nofollow through their route rule
- a production build fails with the D-70 message; nuxt dev and
  nuxt prepare only warn
- testing/guard-check.mjs builds four fixture apps (guard:check)
2026-11-04 11:42:08 +01:00
Jakub Zych
6636cde70a fix: root files fall through until the backend has given a site answer
With the SEO backend unreachable since start, /robots.txt and /sitemap.xml
answered 503 where v0.1.1 left them to the app (a consumer's smoke expects
the app's 404). The root proxies now need a site answer; the last one seen
is kept while the backend is down, so a failure after it is still 503.
2026-11-04 09:31:39 +01:00
Jakub Zych
c2357cd7f9 docs: README
- options (cms alias of public.seo.enabled, breadcrumbs, links.newTabHint,
  rootFiles, resolveFiles), the new runtime keys and the moved purge keys
- the resolve and site answer contract, one JSON-LD graph, root files,
  the purge route, 404 report, labels and tokens, the smoke runs
2026-11-04 09:29:02 +01:00
Jakub Zych
aa7480e003 feat: SEO labels, tokens and base styles
- useSeoLabels(): the L8 dictionary (en, pl) of the page's content locale
  (resolve locale, then html_lang, then en), overridable and extendable in
  app.config.ts under seo.labels; no i18n dependency
- seo-tokens.css (spacing, colour, small type, breadcrumb separator) and
  seo-base.css (.seo-visually-hidden, the focus ring of layer links), loaded
  before the app's CSS and styling only .seo-* classes
2026-11-04 09:27:57 +01:00
Jakub Zych
d1629439c7 feat: root files from the CMS and the 404 report
- server/middleware/seo-root.ts proxies /robots.txt, /sitemap.xml,
  /sitemap-<name>.xml, /llms.txt and the verification and IndexNow key
  files the site answer lists in root_files, with the backend's status,
  content type and X-Robots-Tag; a backend failure is 503 Retry-After 60
- server/lib/site.ts caches GET /_seo/api/v1/site (300 s, cleared by the
  purge); a backend without it (404) keeps the v0.1.1 behaviour: no root
  proxies, the verification lookup by name
- the 404 report and the verification lookup honour seo.cms and rootFiles
- smoke runs for the layer off (seo.cms and the v0.1.1 enabled switch), the
  CMS down (fail open) and no 404 token; npm run purge:check
2026-11-04 09:26:00 +01:00
Jakub Zych
691fa09b0f feat: shared site cache purge route clears the SEO caches
- POST /api/__site__/cache/purge, its library and the site config plugin
  moved from vue-journal-layer with the same contract (token rules, 404 for
  proxied requests unless allowProxied, deprecated siteCache names); the
  route also clears the resolve cache
- server/plugins/seo-cache-purge.ts clears the SEO caches after any 200
  purge, so an app whose journal, menu or FAQ layer copy of the route wins
  keeps fresh SEO answers until those copies are removed
- cachePurge and siteCache runtime keys; /api/__site__/** never cached
- testing/purge-check.mjs (CMS answer change, plus a redirect added for a
  route-cached page applying at once) and purge-token-check.mjs
2026-11-04 09:23:15 +01:00
Jakub Zych
e3baa7028c feat: redirect and 410 enforcement, X-Robots-Tag and the resolve cache
- the Nitro middleware answers redirect (301/302, Location from the answer
  only, same-site targets as paths as in v0.1.1) and gone (410) before the
  render and the route cache, sets X-Robots-Tag, and answers 404 for a
  pagination.invalid answer; other not_found answers stay with Nuxt
- resolve answers cached in an LRU (seo.resolveCacheTtl, default 60 s,
  1000 entries) with in-flight de-duplication; a clear detaches loads in
  flight so no answer fetched before a purge is stored after it
- the playground route-caches /blog/** (swr 300)
2026-11-04 09:20:20 +01:00
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
Jakub Zych
7d52c5d2e5 fix: canonical and social URLs answered as paths become absolute on the request origin v0.1.1 2026-10-31 13:53:30 +01:00
Jakub Zych
ac59f3c80d feat: vue-seo-layer, the Nuxt half of the SummerCMS SEO plugin v0.1.0 2026-10-31 13:45:37 +01:00