Fumadocs
SkillSearchGuides your agent to set up and customize Fumadocs documentation sites, covering installs, MDX config, layouts, search, and i18n.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Fumadocs skill
About this capability
Set up, customize, or troubleshoot Fumadocs Core/MDX/UI: adapters, loaders, navigation/layouts, search, MDX components, OpenAPI, OG images, exports, and i18n. Excludes generic Markdown, unrelated framework setup, and non-Fumadocs projects.
What this skill tells your AI
The instructions your AI receives, as published by compozy/compozy in .agents/skills/fumadocs/SKILL.md and read by ahel’s review.
Fumadocs is a docs framework for React: it sits inside Next.js / React Router / TanStack Start / Waku and combines three independently usable packages.
| Package | Role | Skip when |
|---|---|---|
fumadocs-core | Headless engine: loader(), page tree, MDX plugins, search adapters, i18n primitives | never (always required) |
fumadocs-mdx | Content source: compiles content/**/*.mdx + meta.json into typed .source/ collections | replaced by @fumadocs/local-md, @fumadocs/mdx-remote, or a custom source |
fumadocs-ui | Opinionated theme: RootProvider, layouts, MDX defaults, search dialog (Tailwind v4) | building a fully bespoke UI on top of fumadocs-core |
Server-first via React Server Components. Static export is opt-in. Edge runtime is unsupported.
Procedures
Step 1: Identify the task class
Map the user's request to one of these classes, then load the matching reference:
| Class | Trigger phrases | Reference |
|---|---|---|
| Bootstrap a project | "scaffold", "set up Fumadocs", "install in ", "create-fumadocs-app" | references/01-install-and-setup.md |
| Routing / file conventions | meta.json, pages directives, slug rules, root folders, page tree | references/02-source-and-page-tree.md |
| MDX configuration | source.config.ts, defineDocs, defineCollections, async / dynamic mode, plugin order, typegen | references/03-mdx-pipeline.md |
| UI layouts / components / MDX wiring | DocsLayout/Notebook/Flux/Home, RootProvider, mdx-components.tsx, theming, MDX overrides | references/04-ui-layouts-and-components.md |
| Search / i18n | adapter selection, search dialog, locale routing, middleware | references/05-search-and-i18n.md |
| OpenAPI / OG / AI / content sources / guides | <APIPage>, generateFiles, OG image route, llms.txt, Ask AI, local-md, mdx-remote, PDF/EPUB/RSS | references/06-integrations.md |
| Debugging an existing setup | "broken", "blank sidebar", "404", "build fails", "weird hydration" | references/07-pitfalls.md |
If the task spans multiple classes, load the references in the order shown above (setup → tree → MDX → UI → search/i18n → integrations).
Step 2: Confirm the package surface in use
Before recommending code, check which Fumadocs surface the project actually uses. Read these files (paths are conventional, not absolute):
package.json— confirmfumadocs-core,fumadocs-mdx,fumadocs-uiversions and which adapter is installed (next,@react-router/...,@tanstack/react-start,waku).source.config.ts(Fumadocs MDX) orlib/source.ts(low-levelloader()) — determines whether the project uses the bundler-backed MDX path or a runtime source (local-md,mdx-remote, custom).- The catch-all docs route — Next:
app/<segment>/[[...slug]]/page.tsx; React Router:routes/docs/$.tsxorroute('docs/*', ...); TanStack Start:routes/docs/$.tsx; Waku:pages/docs/[...slugs].tsx. - The root layout / provider import path —
fumadocs-ui/provider/{next,react-router,tanstack,waku}MUST match the framework. - Tailwind entry — confirm Tailwind 4, the colour preset (
fumadocs-ui/css/<theme>.css) andfumadocs-ui/css/preset.cssimports.
If any of these contradicts the user's request, surface the conflict before editing.
Step 3: Choose adapters and modes deterministically
Use these decision tables instead of guessing:
MDX entry mode (Fumadocs MDX → collections/{server,browser,dynamic})
| Choose | When |
|---|---|
server | RSC / SSR / SSG (default, fastest first paint) |
browser | Client-routed apps (TanStack Start, React Router SPA mode) — only doc / docs collections |
dynamic | Very large libraries (>500 MDX) where build time / memory dominates |
direct import | One-off MDX as a page or React component (no loader() indirection) |
Content source
| Choose | When |
|---|---|
| Fumadocs MDX (default) | Bundler-backed, typegen, image optimization, full MDX import/export |
@fumadocs/local-md | Runtime-only, Cloudflare Workers compat, no eval, no bundler step |
@fumadocs/mdx-remote | Runtime compile from CMS / remote content (trusted input only) |
custom (StaticSource / DynamicSource) | Hardcoded trees, generated content, multi-tenant per-permission sources |
Search adapter
| Choose | When |
|---|---|
orama (default) | Self-hosted, free, typed schema, vector capable |
flexsearch | Tiny / medium docs, zero infra, smaller bundle than Orama |
algolia | Enterprise scale, polished relevance (free tier requires logo) |
orama-cloud | Hosted Orama, scale without ops |
mixedbread | Semantic / vector / natural-language queries |
typesense | OSS scale + faceting (community adapter) |
trieve | RAG / hybrid retrieval (community-maintained) |
| custom | Hand-roll a /static.json route from source.getPages().structuredData |
Layout
| Choose | When |
|---|---|
fumadocs-ui/layouts/docs | Classic docs site with persistent sidebar |
fumadocs-ui/layouts/notebook | Denser, app-shell feel; supports top-tab navigation |
fumadocs-ui/layouts/flux | Aggressively minimal (client-only — no unserialisable RSC props) |
fumadocs-ui/layouts/home | Marketing / landing pages that share docs chrome |
When the layout changes, the per-doc page import must follow (fumadocs-ui/layouts/<layout>/page → DocsPage, DocsTitle, DocsBody).
Step 4: Wire source.config.ts, loader(), and mdx-components.tsx
These three files form the spine of any Fumadocs setup. Use the canonical templates (read first, then adapt):
- Read
assets/source-config-template.tsfor thedefineDocs+defineCollections+defineConfigshape, schema extension viapageSchema/metaSchema, and the recommendedtsconfigaliascollections/* → .source/*. - Read
assets/source-template.tsfor theloader({ source, baseUrl, url, slugs, icon, i18n, plugins })shape and the typicallib/source.tsexports. - Read
assets/mdx-components-template.tsxfor thegetMDXComponentspattern, thepreref-strip workaround, andcreateRelativeLink(source, page)wiring.
If the project already has these files, prefer surgical edits over rewrites — collection-level mdxOptions wipes globals, so use applyMdxPreset(...) to keep the docs preset.
Step 5: Validate before claiming done
For any change that touches MDX content, source config, page conventions, or layouts:
- Trigger source generation via the project's existing dev script (Fumadocs MDX writes
.source/ondev/build; otherwise runnpx fumadocs-mdx). - Run the framework's typecheck —
.source/index.d.tsmust compile cleanly. A.source/not regenerated is the most common cause of "module not found" or "property does not exist" errors. - Render the affected route(s) — sidebar items match
meta.json.pages, breadcrumbs/TOC populate, search dialog opens with⌘K. Layout-level breakage is silent until rendered. - If i18n is configured, check the locale variants:
defaultLanguageand at least one non-default.hideLocale: 'always'cookies break static caches — surface this if applicable.
Step 6: Use the pitfall catalog before debugging
When the user reports a bug, read references/07-pitfalls.md first — most failures are catalogued. The five most common:
- Tailwind v3 silently breaks the theme — only Tailwind v4 +
fumadocs-ui/css/preset.cssis supported. next.config.js(CJS) won't loadfumadocs-mdx— the loader is ESM only; rename tonext.config.mjsor enable Native Node TS resolver.- Layout/page import mismatch — Notebook/Flux require
DocsPagefromlayouts/<layout>/page; defaulting tolayouts/docs/pageproduces broken TOC/footer. - Duplicated URLs in the page tree — Fumadocs locates the active node by
pathnameonly; any duplicate corrupts active-link detection. - Provider subpath mismatch —
fumadocs-ui/provider/<framework>must match the adapter orRootProvidersilently no-ops (search, theme switch, i18n all stop working).
Error Handling
- The user mentions a feature that isn't visible in
package.json. Ask which adapter they're on before generating code; never assume Next.js because the docs default to it. - The framework adapter is older than Fumadocs 16. Earlier majors used different provider paths and Tailwind 3 — verify the version and read
references/07-pitfalls.mdfor migration notes before editing. source.config.tsand a runtime source (local-md/mdx-remote) coexist. Two competing loaders is not a supported state — readreferences/06-integrations.md#content-sourcesand pick one before changing code.- Static export is required. Confirm whether search needs to be
static(Orama static, FlexSearch static, or hosted/cloud) — server-fetch search will not work statically. Seereferences/05-search-and-i18n.md#static-export. .source/does not exist or is stale. Trigger source generation before any typecheck; missing entries cause cryptic "module not found" / "is not exported" errors.- OpenAPI is requested.
openapiSource()mutatespage.typeto'openapi'— every consumer (getLLMText, page renderer, search index, OG image, RSS) must branch on it. Readreferences/06-integrations.md#openapibefore wiring.
Signals
- GitHub stars
- 3k
- Forks
- 177
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
fumadocs- Source
- github.com/compozy/compozy