diff --git a/docs-site/app/docs/[[...slug]]/page.tsx b/docs-site/app/docs/[[...slug]]/page.tsx index 0b59743d..869454ec 100644 --- a/docs-site/app/docs/[[...slug]]/page.tsx +++ b/docs-site/app/docs/[[...slug]]/page.tsx @@ -5,15 +5,26 @@ import { DocsTitle, DocsDescription, } from "fumadocs-ui/page"; -import { notFound } from "next/navigation"; +import { notFound, redirect } from "next/navigation"; import defaultMdxComponents from "fumadocs-ui/mdx"; import { CodeBlock } from "@/components/code-block"; import { DocsPageActions } from "@/components/docs-page-actions"; +const docsIndexPath = "/docs/getting-started/introduction"; +const docsIndexSlug = ["getting-started", "introduction"] as const; + +function isDocsIndex(slug: string[] | undefined) { + return slug === undefined || slug.length === 0 || slug.join("/") === ""; +} + export default async function Page(props: { params: Promise<{ slug?: string[] }>; }) { const params = await props.params; + if (isDocsIndex(params.slug)) { + redirect(docsIndexPath); + } + const page = source.getPage(params.slug); if (!page) notFound(); @@ -35,14 +46,16 @@ export default async function Page(props: { } export function generateStaticParams() { - return source.generateParams(); + return [{ slug: [""] }, ...source.generateParams()]; } export async function generateMetadata(props: { params: Promise<{ slug?: string[] }>; }) { const params = await props.params; - const page = source.getPage(params.slug); + const page = source.getPage( + isDocsIndex(params.slug) ? [...docsIndexSlug] : params.slug, + ); if (!page) notFound(); return { diff --git a/docs-site/middleware.ts b/docs-site/middleware.ts index 4e06ea8b..670ebd33 100644 --- a/docs-site/middleware.ts +++ b/docs-site/middleware.ts @@ -38,7 +38,7 @@ function isMarkdownPreferred(acceptHeader: string | null) { .find((parameter) => parameter.startsWith("q=")); return { - type: type.toLowerCase(), + type: type.trim().toLowerCase(), quality: quality ? Number.parseFloat(quality.slice(2)) : 1, index, }; diff --git a/docs-site/package.json b/docs-site/package.json index 8ab53b93..d4a88999 100644 --- a/docs-site/package.json +++ b/docs-site/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "next dev", "build": "next build", - "start": "next start" + "start": "next start", + "test": "node --test tests/*.test.mjs" }, "dependencies": { "fumadocs-core": "15.7.13", diff --git a/docs-site/tests/docs-index-route.test.mjs b/docs-site/tests/docs-index-route.test.mjs new file mode 100644 index 00000000..859ae54e --- /dev/null +++ b/docs-site/tests/docs-index-route.test.mjs @@ -0,0 +1,14 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +const docsSiteUrl = process.env.DOCS_SITE_URL ?? "http://localhost:3000"; + +test("/docs redirects to the docs introduction", async () => { + const response = await fetch(`${docsSiteUrl}/docs`, { redirect: "manual" }); + + assert.equal(response.status, 307); + assert.equal( + response.headers.get("location"), + "/docs/getting-started/introduction", + ); +});