Fumadocs MDX is the official content source of Fumadocs. It parses frontmatter and is bundled with many MDX
plugins for building a good documentation site.
This package must be used with Fumadocs
npm pnpm yarn bun
npm install fumadocs-mdx @types/mdx
Add the plugin to your next.config.mjs
file.
import { createMDX } from 'fumadocs-mdx/next' ;
const withMDX = createMDX () ;
/** @ type { import('next').NextConfig } */
const config = {
reactStrictMode : true ,
};
export default withMDX ( config ) ;
It generates a .source
folder once you start the dev server or start building the app.
The folder contains all parsed files, you should add it to .gitignore
.
ESM Only
The Next.js config must be a .mjs
file since Fumadocs is ESM-only.
Configure Fumadocs MDX by creating a source.config.ts
file.
import { defineDocs } from 'fumadocs-mdx/config' ;
export const { docs , meta } = defineDocs ( {
dir : '/content/docs' ,
} ) ;
You can add a post install script to generate types before executing CLI tools (e.g. ESLint).
{
" scripts " : {
" postinstall " : "fumadocs-mdx"
}
}
To integrate with Fumadocs, create:
import { docs , meta } from '@/.source' ;
import { createMDXSource } from 'fumadocs-mdx' ;
import { loader } from 'fumadocs-core/source' ;
export const source = loader ( {
baseUrl : '/docs' ,
source : createMDXSource (docs , meta) ,
} ) ;
A .source
folder should be created. You can log and see if it is loaded correctly.
See Pages Conventions
to learn how to organize your pages.
Generally, you'll interact with Fumadocs MDX through the Source loader
API.
You can see the type definitions to find available properties.
To render the page, obtain the page from source
and render the MDX component (page.data.body
).
import { notFound } from 'next/navigation' ;
import { source } from '@/lib/source' ;
import defaultMdxComponents from 'fumadocs-ui/mdx' ;
const page = source . getPage ([ 'slugs' ]) ;
if ( ! page) notFound () ;
const MDX = page . data . body ;
// set your MDX components with `components` prop
< MDX components = {{ ... defaultMdxComponents }} /> ;
Eventually, it will look like:
import { source } from '@/lib/source' ;
import {
DocsPage ,
DocsBody ,
DocsTitle ,
DocsDescription ,
} from 'fumadocs-ui/page' ;
import { notFound } from 'next/navigation' ;
import defaultMdxComponents from 'fumadocs-ui/mdx' ;
import { metadataImage } from '@/lib/metadata' ;
export default async function Page ( props : {
params : Promise < { slug ?: string [] } > ;
}) {
const params = await props . params ;
const page = source . getPage (params . slug) ;
if ( ! page) notFound () ;
const MDX = page . data . body ;
return (
< DocsPage toc = { page . data . toc } full = { page . data . full } >
< DocsTitle > { page . data . title } </ DocsTitle >
< DocsDescription > { page . data . description } </ DocsDescription >
< DocsBody >
< MDX components = {{ ... defaultMdxComponents }} />
</ DocsBody >
</ DocsPage >
) ;
}
export async function generateStaticParams () {
return source . generateParams () ;
}
export async function generateMetadata ( props : {
params : Promise < { slug ?: string [] } > ;
}) {
const params = await props . params ;
const page = source . getPage (params . slug) ;
if ( ! page) notFound () ;
return metadataImage . withImage (page . slugs , {
title : page . data . title ,
description : page . data . description ,
} ) ;
}
These properties are exported from MDX files by default.
Property Description frontmatter
Frontmatter toc
Table of Contents structuredData
Structured Data, useful for implementing search
See MDX Options .