Aller au contenu

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

shell
bunx shadcn@latest add @krak-stack/docs

The 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.

plaintext
src/content/docs/
├── en/
│   ├── introduction.mdx
│   └── operations.mdx
└── fr/
    ├── introduction.mdx
    └── operations.mdx

Every MDX file requires matching frontmatter and body titles. Localized versions share routing metadata while translating title, description, headings, and body content.

plaintext
---
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.

tsx
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.

tsx
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.

Dependencies
Packages and shadcn components required by this registry item.