Skip to main content
The Content Collections adapter allows you to use Content Collections as your content source for Fumadocs. This is useful if you prefer Content Collections’ approach to content management.

Installation

npm install @fumadocs/content-collections @content-collections/core @content-collections/mdx fumadocs-core

Setup

1. Configure Content Collections

Create a content-collections.ts file:
content-collections.ts
import { defineCollection, defineConfig } from '@content-collections/core';
import {
  frontmatterSchema,
  metaSchema,
  transformMDX,
} from '@fumadocs/content-collections/configuration';

const docs = defineCollection({
  name: 'docs',
  directory: 'content/docs',
  include: '**/*.mdx',
  schema: frontmatterSchema,
  transform: transformMDX,
});

const metas = defineCollection({
  name: 'meta',
  directory: 'content/docs',
  include: '**/meta.json',
  parser: 'json',
  schema: metaSchema,
});

export default defineConfig({
  collections: [docs, metas],
});

2. Create Your Source

Create a source file that uses the Content Collections adapter:
lib/source.ts
import { allDocs, allMetas } from 'content-collections';
import { loader } from 'fumadocs-core/source';
import { createMDXSource } from '@fumadocs/content-collections';

export const source = loader({
  baseUrl: '/docs',
  source: createMDXSource(allDocs, allMetas),
});

3. Build Integration

Add Content Collections to your build process:
import { withContentCollections } from '@content-collections/next';

/** @type {import('next').NextConfig} */
const config = {
  reactStrictMode: true,
};

export default withContentCollections(config);

Schema Configuration

Document Schema

Customize the frontmatter schema for your documents:
content-collections.ts
import { defineCollection } from '@content-collections/core';
import {
  frontmatterSchema,
  transformMDX,
} from '@fumadocs/content-collections/configuration';
import { z } from 'zod';

const docs = defineCollection({
  name: 'docs',
  directory: 'content/docs',
  include: '**/*.mdx',
  schema: frontmatterSchema.extend({
    author: z.string(),
    date: z.date(),
    tags: z.array(z.string()).optional(),
  }),
  transform: transformMDX,
});
The frontmatterSchema includes:
z.object({
  title: z.string(),
  description: z.string().optional(),
  icon: z.string().optional(),
  full: z.boolean().optional(),
  _openapi: z.record(z.string(), z.any()).optional(),
})

Meta Schema

Customize the meta.json schema:
content-collections.ts
import { metaSchema } from '@fumadocs/content-collections/configuration';
import { z } from 'zod';

const metas = defineCollection({
  name: 'meta',
  directory: 'content/docs',
  include: '**/meta.json',
  parser: 'json',
  schema: metaSchema.extend({
    badge: z.string().optional(),
  }),
});
The metaSchema includes:
z.object({
  title: z.string().optional(),
  description: z.string().optional(),
  pages: z.array(z.string()).optional(),
  icon: z.string().optional(),
  root: z.boolean().optional(),
  defaultOpen: z.boolean().optional(),
})

Transform Options

The transformMDX function accepts options to customize MDX processing:
content-collections.ts
import { transformMDX } from '@fumadocs/content-collections/configuration';

const docs = defineCollection({
  name: 'docs',
  directory: 'content/docs',
  include: '**/*.mdx',
  schema: frontmatterSchema,
  transform: async (document, context) => {
    return transformMDX(document, context, {
      // Remark plugins
      remarkPlugins: [
        // Add custom plugins
      ],
      
      // Rehype plugins
      rehypePlugins: [
        // Add custom plugins
      ],
      
      // Code highlighting options
      rehypeCodeOptions: {
        themes: {
          light: 'github-light',
          dark: 'github-dark',
        },
      },
      
      // Heading options
      remarkHeadingOptions: {
        generateToc: true,
      },
      
      // Image options
      remarkImageOptions: {
        useImport: false,
      },
      
      // Code tab options
      remarkCodeTabOptions: {
        parseMdx: true,
      },
      
      // Generate structured data for search
      remarkStructureOptions: true,
    });
  },
});

Plugin Customization

You can customize individual plugins:
transformMDX(document, context, {
  rehypeCodeOptions: {
    themes: {
      light: 'catppuccin-latte',
      dark: 'catppuccin-mocha',
    },
    inline: 'tailing-curly-colon',
    transformers: [
      // Add Shiki transformers
    ],
  },
});

Output Types

The transformMDX function returns:
type TransformOutput = {
  // MDX component
  body: string;
  
  // Table of contents
  toc: {
    title: string;
    url: string;
    depth: number;
  }[];
  
  // Structured data for search
  structuredData: {
    headings: Array<{
      id: string;
      content: string;
    }>;
    contents: Array<{
      heading: string;
      content: string;
    }>;
  };
};

Using Helper Functions

The adapter provides helper functions for creating schemas:
content-collections.ts
import {
  createDocSchema,
  createMetaSchema,
} from '@fumadocs/content-collections/configuration';
import { defineCollection } from '@content-collections/core';
import { z } from 'zod';

const docs = defineCollection({
  name: 'docs',
  directory: 'content/docs',
  include: '**/*.mdx',
  schema: (z) => ({
    ...createDocSchema(z),
    // Add your custom fields
    author: z.string(),
  }),
});

const metas = defineCollection({
  name: 'meta',
  directory: 'content/docs',
  include: '**/meta.json',
  parser: 'json',
  schema: (z) => ({
    ...createMetaSchema(z),
    // Add your custom fields
    badge: z.string().optional(),
  }),
});

Creating the Source

Use createMDXSource to convert Content Collections to a Fumadocs source:
lib/source.ts
import { allDocs, allMetas } from 'content-collections';
import { createMDXSource } from '@fumadocs/content-collections';
import { loader } from 'fumadocs-core/source';

export const source = loader({
  baseUrl: '/docs',
  source: createMDXSource(allDocs, allMetas),
});
The createMDXSource function expects:
  • First parameter: Array of document entries with _meta.filePath
  • Second parameter: Array of meta entries with _meta.filePath

Usage in Your App

Once configured, use the source in your application:
app/docs/[[...slug]]/page.tsx
import { source } from '@/lib/source';
import { notFound } from 'next/navigation';

export default async function Page({ params }) {
  const page = source.getPage(params.slug);
  if (!page) notFound();
  
  const { body, toc, structuredData } = page.data;
  
  return (
    <div>
      <h1>{page.data.title}</h1>
      {body}
    </div>
  );
}

export function generateStaticParams() {
  return source.generateParams();
}

Multiple Collections

You can define multiple documentation collections:
content-collections.ts
import { defineCollection, defineConfig } from '@content-collections/core';
import { transformMDX, frontmatterSchema } from '@fumadocs/content-collections/configuration';

const docs = defineCollection({
  name: 'docs',
  directory: 'content/docs',
  include: '**/*.mdx',
  schema: frontmatterSchema,
  transform: transformMDX,
});

const blog = defineCollection({
  name: 'blog',
  directory: 'content/blog',
  include: '**/*.mdx',
  schema: frontmatterSchema.extend({
    date: z.date(),
    author: z.string(),
  }),
  transform: transformMDX,
});

export default defineConfig({
  collections: [docs, blog],
});
lib/source.ts
import { allDocs, allBlog } from 'content-collections';
import { createMDXSource } from '@fumadocs/content-collections';
import { loader } from 'fumadocs-core/source';

export const docsSource = loader({
  baseUrl: '/docs',
  source: createMDXSource(allDocs, []),
});

export const blogSource = loader({
  baseUrl: '/blog',
  source: createMDXSource(allBlog, []),
});

Comparison with Fumadocs MDX

FeatureFumadocs MDXContent Collections
Configurationsource.config.tscontent-collections.ts
Type GenerationAutomaticVia Content Collections
Build PerformanceOptimized for FumadocsContent Collections engine
Plugin SystemFumadocs pluginsContent Collections transforms
Hot ReloadYesYes
Async LoadingBuilt-inVia transforms
WorkspacesNative supportManual setup

Migration to Fumadocs MDX

If you want to migrate to the native Fumadocs MDX:
  1. Create a source.config.ts file
  2. Convert your collections to defineDocs or defineCollections
  3. Update imports from content-collections to fumadocs-mdx:collections/server
  4. Replace createMDXSource with docs.toFumadocsSource()
  5. Update your build integration
See the Fumadocs MDX page for details.

Build docs developers (and LLMs) love