Fumadocs

Introduction

Learn how to use Fumadocs MDX in your documentation

Introduction

Fumadocs MDX is the official content source of Fumadocs.

It provides the tool for Next.js to transform content into type-safe data, similar to Contentlayer and Content Collections. This library isn't Fumadocs-only, you can use it to handle blog and other contents.

Getting Started

Setup Fumadocs MDX for your Fumadocs application.

npm install fumadocs-mdx @types/mdx

This package requires Fumadocs core.

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);

ESM Only

The Next.js config must be a .mjs file since Fumadocs is ESM-only.

Defining Collections

Collection refers to a collection containing a certain type of files, there's two types of collections:

  • doc: Markdown/MDX documents
  • meta: JSON files

For example, a doc collection will include only the .md and .mdx files:

ui.md
hello.md
index.mdx
meta.json

Fumadocs MDX will transform collections into arrays of type-safe data, accessible in your Next.js app. Notably, Markdown/MDX content will be compiled into a React Server Component, with other useful properties like Table of Contents.

You can define and configure collections by creating a source.config.ts file. For example, this is how you define a doc collection:

source.config.ts
import { defineCollections } from 'fumadocs-mdx/config';
 
export const test = defineCollections({
  type: 'doc',
  dir: 'content/docs',
});

The above collection will include all Markdown/MDX files under the content/docs directory.

For Fumadocs to work, you can define a docs collection:

source.config.ts
import { defineDocs } from 'fumadocs-mdx/config';
 
export const docs = defineDocs({
  dir: 'content/docs',
  docs: {
    // options for `doc` collection
  },
  meta: {
    // options for `meta` collection
  },
});

The docs collection combines a meta and doc collection, which scans through all Markdown, MDX and JSON files under your content/docs directory. They are needed for Fumadocs to work.

Output Folder

Once you run next dev or next build, it generates a .source folder in root directory.

The folder contains all output data and its types, you should add it to .gitignore.

The fumadocs-mdx command generates types for .source folder without running Next.js, you can add it as a post install script to ensure types are always generated when initializing the project.

package.json
{
  "scripts": {
    "postinstall": "fumadocs-mdx"
  }
}

Accessing Collections

Collection Output is the generated data of a collection, it can have a different type/shape depending on the collection type and schema.

You can access the collection output from .source folder with its original name:

// source.config.ts
import { defineDocs } from 'fumadocs-mdx/config';
 
export const docs = defineDocs({
  dir: 'content/docs',
  docs: {
    // options for `doc` collection
  },
  meta: {
    // options for `meta` collection
  },
});
 
// lib/source.ts
import { docs } from '@/.source';
 
console.log(docs);

In this guide, We will import the .source folder with @/.source, you can also change it to your own import alias. Make sure you are importing from .source rather than source.config.ts.

To integrate with Fumadocs, you can use the toFumadocsSource() function of docs collection output.

lib/source.ts
import { docs } from '@/.source';
import { loader } from 'fumadocs-core/source';
 
export const source = loader({
  baseUrl: '/docs',
  source: docs.toFumadocsSource(),
});

And for other types of collections, the output may different, you can also log them to see the differences.

Start Server

next dev

A .source folder should be created. You can log and see if it is loaded correctly.

See Organizing Pages to learn how to organize your pages.

Usage

Generally, you'll interact with Fumadocs MDX through the Source object (output of loader).

import { source } from '@/lib/source';
 
const page = source.getPage(['slugs']);
 
if (page) {
  // access page data
  console.log(page.data);
 
  // frontmatter properties are also inside
  console.log(page.data.title);
}

To render the page, use page.data.body as a component.

import defaultMdxComponents from 'fumadocs-ui/mdx';
 
const MDX = page.data.body;
 
// set your MDX components with `components` prop
return <MDX components={{ ...defaultMdxComponents }} />;

Multiple Collections

You can define more collections, see Collections for available options.

source.config.ts
import { defineDocs } from 'fumadocs-mdx/config';
 
export const docs = defineDocs({
  dir: 'content/docs',
});
 
export const blogPosts = defineDocs({
  dir: 'content/blog',
});

And use loader for a simple way to interact with collection output.

lib/source.ts
import { docs, blogPosts } from '@/.source';
import { loader } from 'fumadocs-core/source';
 
export const source = loader({
  baseUrl: '/docs',
  source: docs.toFumadocsSource(),
});
 
export const blog = loader({
  baseUrl: '/blog',
  source: blogPosts.toFumadocsSource(),
});

FAQ

Built-in Properties

These properties are exported from MDX files by default.

PropertyDescription
frontmatterFrontmatter
tocTable of Contents
structuredDataStructured Data, useful for implementing search

Customise Frontmatter

Use the schema option to pass a validation schema to validate frontmatter and define its output properties.

MDX Plugins

See MDX Options.

How is this guide?

On this page