feat(seo): pre-render the landing answer block (What is Semantic Anchors?)#593
Conversation
…ability The home page rendered its hero client-side, so crawlers and LLM fetchers saw only the empty skeleton — the worst case for the query "What is Semantic Anchors?". prerender-routes.js now fills the home #page-content with the hero copy (title + definition + emphasis), single-sourced from the EN translations so it never drifts from the live hero. The SPA overwrites #page-content with the full interactive hero + card grid on boot, so users are unaffected; the home is written separately so other routes keep their empty-skeleton assumption. Implements the landing-block half of LLM-Coding#580; the per-anchor answer-block sweep is intentionally skipped — anchor definitions already ship crawlable via /all-anchors. Verified with a full build: the home #page-content carries the definition plus the DefinedTermSet/Organization, and a control route (/about) neither leaks the home block nor loses its own doc content. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
WalkthroughDer PR erweitert das Build-Skript, um einen „Landing Answer Block" mit Hero-Titel und Intro-Text server-seitig auf der Startseite vor-zu-rendern und direkt in ÄnderungenHomepage-Landingblock-Pre-Rendering
Geschätzter Code-Review-Aufwand🎯 2 (Einfach) | ⏱️ ~10 Minuten Möglicherweise zugehörige Issues
Möglicherweise zugehörige Pull Requests
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/prerender-routes.js`:
- Line 321: Die Abschlussmeldung in scripts/prerender-routes.js verwendet eine
ungenaue Formulierung; passe die console.log-Ausgabe (die Zeile mit ROUTES) so
an, dass sie korrekt widerspiegelt, dass Routen nach dist/<route>/index.html
geschrieben werden, während die Startseite nach dist/index.html geschrieben wird
(z.B. durch Nennung beider Ziele oder eine differenzierte Formulierung), damit
die Variable ROUTES und der separate Home-Block korrekt beschrieben sind.
- Around line 284-286: Die aktuelle stille Fallback-Logik mit "const title =
en['hero.title'] || ''" (und ähnlich für intro, emphasis) erzeugt leere
Hero-Blöcke bei fehlenden Übersetzungs-Keys; stattdessen prüfe in
prerender-routes.js nach dem Laden von en, ob die Keys en['hero.title'],
en['hero.intro'] und en['hero.introEmphasis'] vorhanden und nicht leer sind, und
wirf bei fehlenden/leeren Werten eine aussagekräftige Error-Exception (oder rufe
process.exit(1) auf), sodass der Build hart fehlschlägt; referenziere die
Variablen title, intro und emphasis in der Validierungslogik und liefere im
Fehlertext welche Key(s) fehlen.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 815b904c-2be7-4574-8c8e-ad421a3ab090
📒 Files selected for processing (2)
docs/changelog.adocscripts/prerender-routes.js
| const title = en['hero.title'] || '' | ||
| const intro = en['hero.intro'] || '' | ||
| const emphasis = en['hero.introEmphasis'] || '' |
There was a problem hiding this comment.
Fehlende Pflicht-Validierung der Hero-Übersetzungsschlüssel
Mit || '' wird ein stiller Fehlerpfad erzeugt: Bei fehlenden/umbenannten Keys wird ein leerer Home-Answer-Block geschrieben, der Build bleibt aber erfolgreich. Für das SEO-Ziel sollte der Build hier hart fehlschlagen.
Vorschlag (fail-fast statt silent fallback)
function prerenderHome() {
const enPath = path.join(__dirname, '..', 'website', 'src', 'translations', 'en.json')
const en = JSON.parse(fs.readFileSync(enPath, 'utf-8'))
- const title = en['hero.title'] || ''
- const intro = en['hero.intro'] || ''
- const emphasis = en['hero.introEmphasis'] || ''
+ const requiredKeys = ['hero.title', 'hero.intro', 'hero.introEmphasis']
+ for (const key of requiredKeys) {
+ if (typeof en[key] !== 'string' || en[key].trim() === '') {
+ throw new Error(`Missing required translation key for home prerender: ${key}`)
+ }
+ }
+ const title = en['hero.title']
+ const intro = en['hero.intro']
+ const emphasis = en['hero.introEmphasis']📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const title = en['hero.title'] || '' | |
| const intro = en['hero.intro'] || '' | |
| const emphasis = en['hero.introEmphasis'] || '' | |
| function prerenderHome() { | |
| const enPath = path.join(__dirname, '..', 'website', 'src', 'translations', 'en.json') | |
| const en = JSON.parse(fs.readFileSync(enPath, 'utf-8')) | |
| const requiredKeys = ['hero.title', 'hero.intro', 'hero.introEmphasis'] | |
| for (const key of requiredKeys) { | |
| if (typeof en[key] !== 'string' || en[key].trim() === '') { | |
| throw new Error(`Missing required translation key for home prerender: ${key}`) | |
| } | |
| } | |
| const title = en['hero.title'] | |
| const intro = en['hero.intro'] | |
| const emphasis = en['hero.introEmphasis'] |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/prerender-routes.js` around lines 284 - 286, Die aktuelle stille
Fallback-Logik mit "const title = en['hero.title'] || ''" (und ähnlich für
intro, emphasis) erzeugt leere Hero-Blöcke bei fehlenden Übersetzungs-Keys;
stattdessen prüfe in prerender-routes.js nach dem Laden von en, ob die Keys
en['hero.title'], en['hero.intro'] und en['hero.introEmphasis'] vorhanden und
nicht leer sind, und wirf bei fehlenden/leeren Werten eine aussagekräftige
Error-Exception (oder rufe process.exit(1) auf), sodass der Build hart
fehlschlägt; referenziere die Variablen title, intro und emphasis in der
Validierungslogik und liefere im Fehlertext welche Key(s) fehlen.
| } | ||
| console.log(`\n✓ Pre-rendered ${ROUTES.length} routes to dist/<route>/index.html`) | ||
| prerenderHome() | ||
| console.log(`\n✓ Pre-rendered ${ROUTES.length} routes + home to dist/<route>/index.html`) |
There was a problem hiding this comment.
Abschluss-Log ist fachlich ungenau
Die Meldung sagt dist/<route>/index.html, obwohl der Home-Block in dist/index.html geschrieben wird. Das erschwert Build-Diagnosen unnötig.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/prerender-routes.js` at line 321, Die Abschlussmeldung in
scripts/prerender-routes.js verwendet eine ungenaue Formulierung; passe die
console.log-Ausgabe (die Zeile mit ROUTES) so an, dass sie korrekt
widerspiegelt, dass Routen nach dist/<route>/index.html geschrieben werden,
während die Startseite nach dist/index.html geschrieben wird (z.B. durch Nennung
beider Ziele oder eine differenzierte Formulierung), damit die Variable ROUTES
und der separate Home-Block korrekt beschrieben sind.
Implements the landing-block half of #580: a crawlable "What is Semantic Anchors?" answer on the home page.
The gap
The home page (
/) rendered its hero client-side, so search engines and LLM fetchers saw only the empty SPA skeleton — the single worst case for the query "What is Semantic Anchors?", the exact query the GEO audit flagged as getting zero AI mentions. #579 gave the home machine-readable identity (DefinedTermSet); this gives it a human-readable answer.Change
scripts/prerender-routes.jsnow fills the home#page-contentwith the hero copy — title, the definition ("Semantic Anchors are words … that activate rich, well-defined concepts inside any modern LLM"), and emphasis — single-sourced fromwebsite/src/translations/en.jsonso it can never drift from the live hero. No new content was written.dist/index.html, so the other routes (built from the cached shell) keep their empty-skeleton assumption.#page-contentwith the full interactive hero + card grid, so users are unaffected — standard progressive enhancement.The per-anchor "direct answer" sweep from #580 is intentionally skipped: anchor definitions already ship crawlable via the pre-rendered
/all-anchorspage, so the marginal value is low.Scope note
This also aligns with the rule that every page must be pre-rendered — the home was the last route serving an empty shell.
Verification
Full
vite buildrun locally:#page-contentcarries the definition +<h1>, and still carries theOrganization+DefinedTermSetJSON-LD from feat: Extend JSON-LD — standalone Organization + DefinedTerm/DefinedTermSet markup for anchors #579;/about) does not leak the home block and keeps its own doc content;#page-contentis no longer the empty skeleton div.🤖 Generated with Claude Code
Summary by CodeRabbit
Neue Funktionen
Dokumentation