Bibliothèques · Référence
Documentation
A provider-neutral localized documentation source, catalog, search index, and complete responsive documentation UI.
Dernière mise à jour le 26 octobre 2026
Overview
docs provides a Fumadocs-style source and catalog API for localized technical documentation. It validates page records with Effect Schema, parses raw MDX, builds navigation and a shared search index, renders the documentation layout and pages, and leaves route ownership with the application.
Install
bunx shadcn@latest add @krak-stack/docsThe item creates src/lib/docs.tsx. It includes built-in English and French UI messages and accepts message overrides through makeDocs.
Content Sources
Use createMdxDocsSource with any raw-file provider. The included docsSource uses an eager Vite glob for src/content/docs/**/*.mdx with English and French locales. A CMS or generated manifest can bypass MDX parsing with createDocsSource({ pages, locales }) and records matching DocsPageSchema.
src/content/docs/
├── en/
│ ├── introduction.mdx
│ └── operations.mdx
└── fr/
├── introduction.mdx
└── operations.mdxEvery MDX file requires matching frontmatter and body titles. Localized versions share routing metadata while translating title, description, headings, and body content.
---
slug: introduction
path: /docs
title: Introduction
description: Learn how to use the application.
icon: lucide:book-open
order: 1
locale: en
section: start
type: concept
legacySlugs: [overview]
---
# Introduction
Welcome to the documentation.
## First steps
Start here.section is an arbitrary stable navigation group. type is one of concept, tutorial, how-to, reference, or runbook. legacySlugs is optional and redirects old public URLs to the canonical page.
Configure The Catalog
makeDocs applies project-level routing, metadata, navigation, branding, resources, messages, and repository settings to a source.
const docs = makeDocs({
source: docsSource,
basePath: "/docs",
defaultSlug: "introduction",
origin: "https://example.com",
siteName: "Example Docs",
sectionOrder: ["start", "guides", "operations", "reference"],
brand: {
label: "Example",
subtitle: () => "Documentation",
icon: "lucide:book-open",
href: "/",
},
github: {
url: "https://github.com/example/project",
branch: "main",
},
});The returned catalog exposes pages, sections, resolve, search, getMessages, getHead, url, and editUrl.
Set Up The Optional Slug Route
Create src/routes/docs.{-$slug}.tsx. The application owns this route because locale resolution, canonical origin, redirects, not-found behavior, and header actions are project decisions.
import { createFileRoute, notFound, redirect } from "@tanstack/react-router";
import { LocaleSwitcher } from "@/components/ui/locale-switcher";
import { ThemeToggle } from "@/components/theme-toggle";
import {
DocsLayout,
DocsNotFound,
DocsPage,
docsSource,
makeDocs,
type DocsLocale,
} from "@/lib/docs";
import { appI18n } from "@/lib/i18n";
const docsLocale = (): DocsLocale => appI18n.locale;
const docs = makeDocs({
source: docsSource,
basePath: "/docs",
defaultSlug: "introduction",
origin: "https://example.com",
siteName: "Example Docs",
sectionOrder: ["start", "guides", "operations", "reference"],
github: { url: "https://github.com/example/project" },
});
export const Route = createFileRoute("/docs/{-$slug}")({
loader: ({ params }) => {
const resolution = docs.resolve(params.slug, docsLocale());
if (!resolution) throw notFound();
if (!resolution.canonical) {
throw redirect({
to: resolution.page.path,
statusCode: 301,
});
}
return resolution;
},
head: ({ loaderData }) => {
const locale = loaderData?.page.locale ?? docsLocale();
return docs.getHead({
locale,
...(loaderData?.page ? { page: loaderData.page } : {}),
});
},
component: DocsRoutePage,
notFoundComponent: () => (
<DocsNotFound docs={docs} locale={docsLocale()} />
),
});
function DocsRoutePage() {
const resolution = Route.useLoaderData();
return (
<DocsLayout
docs={docs}
locale={resolution.page.locale}
headerActions={
<>
<ThemeToggle />
<LocaleSwitcher
locale={appI18n.locale}
locales={appI18n.locales}
onLocaleChange={appI18n.setLocale}
/>
</>
}
>
<DocsPage docs={docs} resolution={resolution} />
</DocsLayout>
);
}The optional segment makes /docs resolve defaultSlug and /docs/operations resolve the matching page. docs.resolve also identifies legacy aliases; redirect every non-canonical resolution permanently so only one URL is indexed.
Search And Rendering
DocsLayout renders ordered navigation, GitHub, documentation search, branding, and app-provided header actions. DocsPage renders Streamdown content, heading anchors, desktop and mobile tables of contents, edit links, and previous/next navigation. Browser search and documentation-toolkit share docs.search, so page text is indexed once and result ranking stays consistent.
For additional locales, provide message overrides through makeDocs({ messages }). Keep public application-specific labels in the receiving project's localization system.