Files
deepstock/vite-plugin-seo-snapshot.js
Dorian 425e56c0ca feat: SEO crawlability + on-brand copy
Make every served byte crawlable without executing JS, remove off-brand
copy, and cut third-party requests.

- Copy: replace off-brand terms (survival/crisis/collapse) in title, meta,
  OG/Twitter, JSON-LD and webmanifest with on-brand preparedness copy.
  Update App.vue i18n page_title/meta_description (EN+DE) too, since the app
  overwrites the head at runtime. Reconcile area count to the real 6.
- Prerender: vite-plugin-seo-snapshot injects a static <noscript> snapshot
  (real <h1>, content, <a href>) after #app. JS users ignore <noscript>, so
  the live app/UX is unchanged; curl/no-JS crawlers get real content.
- 404: nginx now returns true 404s on unknown paths (no soft-200 SPA
  fallback) with a branded 404 page.
- Sitemap: drop no-op hreflang alternates, add <lastmod>.
- Fonts: self-host Space Mono / DM Serif Display / Barlow (woff2, latin +
  latin-ext, font-display: swap); preload above-the-fold faces. No more
  fonts.googleapis/gstatic requests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 08:20:19 +01:00

26 lines
1006 B
JavaScript

import { readFileSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
// Injects a static, crawlable SEO snapshot into a <noscript> block in the
// served index.html. Browsers with JS enabled ignore <noscript>, so the live
// app and its UX are completely unaffected. Non-rendering crawlers and `curl`
// receive a real <h1>, descriptive content and <a href> links instead of an
// empty SPA shell.
export default function seoSnapshot() {
const snapshotPath = fileURLToPath(new URL('./src/seo-snapshot.html', import.meta.url))
return {
name: 'seo-snapshot',
transformIndexHtml(html) {
const snapshot = readFileSync(snapshotPath, 'utf8')
.replace(/<!--[\s\S]*?-->/g, '') // strip authoring comments from served HTML
.trim()
const block = `<noscript>\n${snapshot}\n</noscript>`
// Place it immediately after the app mount point.
return html.replace(
'<div id="app"></div>',
`<div id="app"></div>\n${block}`,
)
},
}
}