diff --git a/.changeset/route-root-docs-index.md b/.changeset/route-root-docs-index.md new file mode 100644 index 00000000..db776d95 --- /dev/null +++ b/.changeset/route-root-docs-index.md @@ -0,0 +1,5 @@ +--- +"@cloudflare/nimbus-docs": patch +--- + +Serve the root docs index entry at the catch-all root route. diff --git a/apps/www/src/pages/[...slug].astro b/apps/www/src/pages/[...slug].astro index fc82851c..ca3d7a05 100644 --- a/apps/www/src/pages/[...slug].astro +++ b/apps/www/src/pages/[...slug].astro @@ -1,5 +1,4 @@ --- -import type { GetStaticPaths } from "astro"; import DocsLayout from "../layouts/DocsLayout.astro"; import { getDocsStaticPaths, @@ -16,17 +15,7 @@ import { import { components } from "../components"; export const prerender = true; -// Serve the root index entry (`docs/index.mdx`) at `/` instead of `/index`, -// mirroring the `.md`/`.mdx` twin routes which already map `id === "index"` -// to the bare root segment. -export const getStaticPaths: GetStaticPaths = async (options) => { - const paths = await getDocsStaticPaths(options); - return paths.map((path) => - path.params.slug === "index" - ? { ...path, params: { ...path.params, slug: undefined } } - : path, - ); -}; +export const getStaticPaths = getDocsStaticPaths; const page = await getDocsPage(Astro); if (page instanceof Response) return page; diff --git a/packages/nimbus-docs/src/runtime.ts b/packages/nimbus-docs/src/runtime.ts index 08ac557e..aa44a091 100644 --- a/packages/nimbus-docs/src/runtime.ts +++ b/packages/nimbus-docs/src/runtime.ts @@ -1196,10 +1196,8 @@ async function resolveProseRoute( * export const prerender = true; * export const getStaticPaths = getDocsStaticPaths; * - * The entry's `id` is used verbatim as the slug. So `docs/index.mdx` → - * `/index`, `docs/guides/setup.mdx` → `/guides/setup`. If you want a docs - * entry at the root URL, name it appropriately and decide whether to use - * a static `pages/index.astro` or let the catch-all handle root. + * The root `index` entry maps to the catch-all root. So `docs/index.mdx` → + * `/`, `docs/guides/setup.mdx` → `/guides/setup`. */ export const getDocsStaticPaths: GetStaticPaths = async () => { // Docs-specific helper: always reads the `docs` collection. Other @@ -1207,7 +1205,7 @@ export const getDocsStaticPaths: GetStaticPaths = async () => { // a one-line `getCollection("")`-based getStaticPaths. const entries = await getVisibleEntries(["docs"]); return entries.map((entry) => ({ - params: { slug: entry.id }, + params: { slug: entry.id === "index" ? undefined : entry.id }, props: { entry }, cacheKey: String(entry.digest), })); diff --git a/packages/nimbus-docs/test/docs-root-route-contract.test.ts b/packages/nimbus-docs/test/docs-root-route-contract.test.ts new file mode 100644 index 00000000..ec84d2f3 --- /dev/null +++ b/packages/nimbus-docs/test/docs-root-route-contract.test.ts @@ -0,0 +1,33 @@ +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { test } from "node:test"; +import { fileURLToPath } from "node:url"; +import path from "node:path"; + +const repoRoot = path.resolve( + fileURLToPath(new URL("../../..", import.meta.url)), +); + +function source(relativePath: string): string { + return readFileSync(path.join(repoRoot, relativePath), "utf8"); +} + +test("the shared docs helper maps the root index entry to the catch-all root", () => { + const runtime = source("packages/nimbus-docs/src/runtime.ts"); + const getDocsStaticPaths = runtime.slice( + runtime.indexOf("export const getDocsStaticPaths"), + runtime.indexOf("export async function getDocsPageProps"), + ); + assert.match( + getDocsStaticPaths, + /params:\s*\{\s*slug:\s*entry\.id === "index" \? undefined : entry\.id\s*\}/, + ); + assert.match( + source("packages/nimbus-starter-source/src/pages/[...slug].astro"), + /export const getStaticPaths = getDocsStaticPaths;/, + ); + assert.match( + source("apps/www/src/pages/[...slug].astro"), + /export const getStaticPaths = getDocsStaticPaths;/, + ); +});