Vibekit

How Fumadocs is wired

Routes, source loader, search, and LLM endpoints in this template

Fumadocs is three layers: Core (source, search, page tree), UI (docs layout and MDX components), and MDX (the content compiler). VibeKit uses all three inside apps/web. See the Fumadocs introduction for the framework view.

Packages

apps/web/package.json pins:

  • fumadocs-core and fumadocs-ui (runtime)
  • fumadocs-mdx (compiler, via createMDX() in apps/web/next.config.mjs)

The Next config wraps the app cleanly as withNextIntl(withMdx(nextConfig)). Fumadocs MDX compiles content/docs (documentation), content/blog (blog articles), and content/legal (terms and privacy policy), unifying all Markdown under one engine.

Source loader

apps/web/modules/docs/source.ts exposes loaders for all content:

  1. defineDocs({ dir: "content/docs" }) reads product documentation.
  2. defineDocs({ dir: "content/blog" }) reads blog posts with frontmatter validation.
  3. defineDocs({ dir: "content/legal" }) reads terms and legal policies.
  4. defineI18n uses config.i18n locales, hides the default locale in URLs, and parses locale files with a dot suffix (page.de.md).
  5. docsSource, blogSource, and legalSource expose getPage, getPageTree, and generateParams.

The public route is a catch-all in its own route group (not under marketing chrome): apps/web/app/(docs)/docs/[[...path]]/.

  • layout.tsx renders DocsLayout with docsSource.getPageTree(locale) and the product logo.
  • page.tsx calls docsSource.getPage(path, locale), then page.data.load() for the MDX body and table of contents.

Locale is not in the URL. getLocale() reads the NEXT_LOCALE cookie. That matches the rest of the app (localePrefix: "never").

MDX components

apps/web/modules/docs/mdx-components.tsx spreads fumadocs-ui/mdx defaults (headings, code blocks, Callout, tabs, and the rest). Add product-specific components there. See Fumadocs UI components.

The docs catch-all layout wraps documentation in Fumadocs RootProvider for search. Its theme handling is disabled because the app already owns the theme provider.

GET /api/search uses createFromSource(docsSource). Each index record includes locale, title, subtitle, URL, and structured data from the compiled page. Details: Fumadocs search.

LLM endpoints

VibeKit follows the Fumadocs LLM integration:

URLWhat it returns
/llms.txtIndex of docs pages
/llms-full.txtFull Markdown of every page
/docs.md or /docs/getting-started/quickstart.mdOne page as Markdown (rewritten to /llms.mdx/docs/...)

Rewrites live in apps/web/next.config.mjs. Helpers live in apps/web/modules/docs/get-llm-text.ts.

Static params

generateStaticParams on the docs page uses docsSource.generateParams("path") to enumerate known slugs. Rendering still reads the locale cookie and resolved module state per request; this does not make every docs route static. Missing slugs call notFound().

On this page