Content Collections is a library that transforms your content into type-safe data collections.
Install the required packages.
npm pnpm yarn bun
npm install @fumadocs/content-collections @content-collections/core @content-collections/mdx @content-collections/next
After the installation, add a path alias for the generated collections to the tsconfig.json
.
{
" compilerOptions " : {
" paths " : {
" @/* " : [ "./*" ],
" content-collections " : [ "./.content-collections/generated" ]
}
}
}
In the Next.js configuration file, apply the plugin.
import { withContentCollections } from '@content-collections/next' ;
/** @ type { import('next').NextConfig } */
const config = {
reactStrictMode : true ,
};
export default withContentCollections ( config ) ;
To integrate with Fumadocs, add the following to your content-collections.ts
.
import { defineCollection , defineConfig } from '@content-collections/core' ;
import {
createMetaSchema ,
createDocSchema ,
transformMDX ,
} from '@fumadocs/content-collections/configuration' ;
const docs = defineCollection ( {
name : 'docs' ,
directory : 'content/docs' ,
include : '**/*.mdx' ,
schema : createDocSchema ,
transform : transformMDX ,
} ) ;
const metas = defineCollection ( {
name : 'meta' ,
directory : 'content/docs' ,
include : '**/meta.json' ,
parser : 'json' ,
schema : createMetaSchema ,
} ) ;
export default defineConfig ( {
collections : [docs , metas] ,
} ) ;
And pass it to Source API.
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) ,
} ) ;
Done! You can access the pages and generated page tree from Source API.
import { getPage } from '@/lib/source' ;
const page = getPage (slugs) ;
// MDX output
page ?. data . body ;
// Table of contents
page ?. data . toc ;
// Structured Data, for Search API
page ?. data . structuredData ;
You can customise MDX options in the transformMDX
function.
import { defineCollection } from '@content-collections/core' ;
import { transformMDX } from '@fumadocs/content-collections/configuration' ;
const docs = defineCollection ( {
transform : ( document , context ) =>
transformMDX (document , context , {
// options here
} ) ,
} ) ;
To use components from other packages like Fumadocs UI, pass them to your <MDXContent />
component.
import defaultMdxComponents from 'fumadocs-ui/mdx' ;
import { Callout } from 'fumadocs-ui/components/callout' ;
import { MDXContent } from '@content-collections/mdx/react' ;
< MDXContent code = "..." components = {{ ... defaultMdxComponents , Callout }} /> ;
You can also import them in MDX Files, but it is not recommended.
Deep Dive: Why?
Content Collections uses mdx-bundler
to bundle MDX files.
To support importing a package from node modules, Fumadocs added a default value to the cwd
option of MDX Bundler.
It works good, but we still do not recommend to import components in MDX files.
Reasons:
It requires esbuild to bundle these components, while it should be done by the Next.js bundler (for features of Server Components)
You can refactor the import path of components without changing your MDX files.
With Remote Sources, it doesn't make sense to add an import in MDX files.