Skip to content

Commit b2e4901

Browse files
committed
fix(seo): add nav links to pre-rendered HTML for Google crawlability
Google only indexed the homepage because inner pages had no crawlable links — the sidebar navigation was rendered client-side by React. Inject a <nav> with links to all doc pages into every pre-rendered page.
1 parent 85e1333 commit b2e4901

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

apps/web/scripts/prerender.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,44 @@ function docPageToHtml(page: DocPage): string {
7272
parts.push(contentBlockToHtml(block));
7373
}
7474
parts.push(`</article>`);
75+
parts.push(navHtml());
7576
return parts.join("\n");
7677
}
7778

79+
// --- Site navigation (crawlable links for search engines) ---
80+
81+
const NAV_SECTIONS = [
82+
{
83+
title: "Getting Started",
84+
items: [{ to: "/docs", label: "Introduction" }],
85+
},
86+
{
87+
title: "WordprocessingML",
88+
items: [
89+
{ to: "/docs/paragraphs", label: "Paragraphs" },
90+
{ to: "/docs/paragraph-borders", label: "Paragraph Borders" },
91+
{ to: "/docs/tables", label: "Tables" },
92+
],
93+
},
94+
{
95+
title: "Guides",
96+
items: [
97+
{ to: "/docs/creating-documents", label: "Creating Documents" },
98+
{ to: "/docs/common-gotchas", label: "Common Gotchas" },
99+
],
100+
},
101+
];
102+
103+
function navHtml(): string {
104+
const sections = NAV_SECTIONS.map(
105+
(section) =>
106+
`<div><strong>${escapeHtml(section.title)}</strong><ul>${section.items
107+
.map((item) => `<li><a href="${item.to}">${escapeHtml(item.label)}</a></li>`)
108+
.join("")}</ul></div>`,
109+
);
110+
return `<nav>${sections.join("")}</nav>`;
111+
}
112+
78113
// --- Static HTML for non-doc pages ---
79114

80115
function homePageHtml(): string {
@@ -83,6 +118,7 @@ function homePageHtml(): string {
83118
<p>The OOXML spec, explained by people who actually implemented it.</p>
84119
<p>Interactive examples, real-world gotchas, live previews, and AI-powered search.</p>
85120
<a href="/docs">Browse Reference</a>
121+
${navHtml()}
86122
</main>`;
87123
}
88124

@@ -98,13 +134,15 @@ function mcpPageHtml(): string {
98134
</ul>
99135
<h2>What is MCP?</h2>
100136
<p>The Model Context Protocol (MCP) is an open standard that lets AI assistants connect to external data sources and tools.</p>
137+
${navHtml()}
101138
</main>`;
102139
}
103140

104141
function specPageHtml(): string {
105142
return `<main>
106143
<h1>ECMA-376 Spec Explorer</h1>
107144
<p>Search and browse the ECMA-376 Office Open XML specification with semantic search and PDF viewer.</p>
145+
${navHtml()}
108146
</main>`;
109147
}
110148

0 commit comments

Comments
 (0)