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.

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 files:

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

Fumadocs MDX will build collections into arrays of type-safe data, accessible in your Next.js app.

You can define and configure collections by creating a config file: source.config.ts.

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

Only files in the directory specified in dir will be included in the collection.

For Fumadocs to work, you can use defineDocs:

source.config.ts
import { defineDocs } from 'fumadocs-mdx/config';
 
// define `docs` and `meta` collections
export const { docs, meta } = defineDocs({
  dir: 'content/docs',
});

defineDocs defines the required collections for Fumadocs. It is same as the config below:

source.config.ts
import {
  defineCollections,
  frontmatterSchema,
  metaSchema,
} from 'fumadocs-mdx/config';
 
export const docs = defineCollections({
  type: 'doc',
  dir: 'content/docs',
  schema: frontmatterSchema, // zod schema to validate frontmatter
});
 
export const meta = defineCollections({
  type: 'meta',
  dir: 'content/docs',
  schema: metaSchema, // zod schema to validate JSON data
});

The two collections together will include all Markdown/MDX and JSON files under your content/docs directory.

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.

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

Accessing Collections

Collection Entry is an entry in the output array of a collection, it can have a different type/shape depending on the collection type and schema.

You can access the entries of collection from .source folder, with its original name:

import { docs, meta } from '@/.source';

To integrate with Fumadocs, create:

lib/source.ts
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),
});

We imported the .source folder with @/.source, you can also change it to your own import alias.

createMDXSource takes an array of doc and meta entry, and convert them into Fumadocs compatible format.

Good to Know

meta entries are only taken for building page trees.

You can leave the second parameter an empty array if meta.json isn't used:

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

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';
import defaultMdxComponents from 'fumadocs-ui/mdx';
 
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 other collections, see Collections for available options.

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

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

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

FAQ

Built-in Properties

These properties are exported from MDX files by default.

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

MDX Plugins

See MDX Options.

Edit on GitHub

Last updated on

On this page