Skip to main content
doc0blade47/fumadocsdocumentation home
Sign in

Content Collections Adapter

Last updated Oct 12, 2026100% grounded
Relevant source files

The following files were used as context for generating this wiki page:

Overview

The Content Collections Adapter (@fumadocs/content-collections) bridges Content Collections data layers with Fumadocs by supplying factory functions and transformation pipelines that translate content entries into compatible virtual files and sources.

Sources: packages/content-collections/package.json:2-4, packages/content-collections/src/index.ts:4-10

By normalizing schemas, unifying metadata extensions, and configuring remark/rehype pipelines such as heading generation and code block formatting, the package enables type-safe content management and rendering across Fumadocs applications.

Sources: packages/content-collections/src/types.ts:4-9, packages/content-collections/src/configuration.ts:58-71

Package architecture and integration entry

Public Exports and Bundle Configuration

The @fumadocs/content-collections package (@fumadocs/content-collections) is structured as an ESM-only module targeting Node 22, configured via tsdown with TypeScript declaration generation enabled (dts: true) and fixed file extensions disabled. The package exposes two public entry points mapped in package exports: the root entry . resolving to ./dist/index.js (with type definitions at ./dist/index.d.ts) and ./configuration resolving to ./dist/configuration.js (with type definitions at ./dist/configuration.d.ts).

import { defineConfig } from 'tsdown';
 
export default defineConfig({
  dts: true,
  fixedExtension: false,
  target: 'node22',
  format: 'esm',
  entry: ['src/{index,configuration}.ts'],
  deps: {
    onlyBundle: [],
  },
});

Sources: packages/content-collections/tsdown.config.ts:1-12

"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
  ".": {
    "types": "./dist/index.d.ts",
    "import": "./dist/index.js"
  },
  "./configuration": {
    "types": "./dist/configuration.d.ts",
    "import": "./dist/configuration.js"
  }
},

Sources: packages/content-collections/package.json:17-29

Package Dependencies and Peer Requirements

Package execution relies on runtime dependencies for unified document processing and schema validation, alongside peer dependencies that couple the adapter directly with Content Collections core packages and Fumadocs core.

Dependency NameTypeVersion / RangePurpose
unifieddependencies^11.0.5AST processing and plugin pipeline integration
zoddependencies^4.4.3Schema definition and type validation
@content-collections/coredevDependencies / peerDependencies0.15.1 / 0.x.xCore collection management and document building
@content-collections/mdxdevDependencies / peerDependencies^0.2.2 / 0.x.xMDX compilation bindings for Content Collections
fumadocs-coredevDependencies / peerDependenciesworkspace:* / 15.x.x || 16.x.xVirtual file types and source abstractions
@types/nodedevDependencies25.9.2Node.js type definitions
tsconfigdevDependenciesworkspace:*Shared TypeScript configuration
tsdowndevDependencies0.22.2Bundle compilation and build tool

Note

The peer dependency range for fumadocs-core explicitly requires major version 15.x.x or 16.x.x, ensuring interface compatibility with Fumadocs source loader definitions.

Sources: packages/content-collections/package.json:40-56

Data contract and schema inheritance

Interface Definitions

The data contract between Content Collections and Fumadocs relies on two core TypeScript interfaces: BaseMetaData and BaseDocsData. These interfaces extend Fumadocs core metadata and page data types by injecting the _meta property defined by @content-collections/core.

export interface BaseMetaData extends MetaData {
  _meta: Meta;
}
 
export interface BaseDocsData extends PageData {
  _meta: Meta;
}

Sources: packages/content-collections/src/types.ts:4-10

Interface NameExtending TypeAdditional PropertyTarget Source Mapping
BaseMetaDataMetaData_meta: MetaVirtualFile<{ metaData: Meta; pageData: Docs }>
BaseDocsDataPageData_meta: MetaVirtualFile<{ metaData: Meta; pageData: Docs }>

Important

Both BaseMetaData and BaseDocsData require the presence of _meta containing Content Collections core metadata (Meta), which supplies file path tracking (_meta.filePath) utilized when generating virtual file entries.

Sources: packages/content-collections/src/index.ts:23-31, packages/content-collections/src/types.ts:4-10

Type Parameter Constraints

The createMDXSource factory function enforces schema inheritance through generic type constraints bounded by BaseDocsData and BaseMetaData. Documents (allDocs) and metadata files (allMetas) must conform to these extended data models to produce a typed Source containing metaData and pageData.

export function createMDXSource<Docs extends BaseDocsData, Meta extends BaseMetaData>(
  allDocs: Docs[],
  allMetas: Meta[],
): Source<{
  metaData: Meta;
  pageData: Docs;
}> {

Sources: packages/content-collections/src/index.ts:4-10

Plugin configuration and remark pipelines

Transform Options and Default Processors

The transformMDX function processes documents by invoking baseCompileMDX from @content-collections/mdx while applying a customized pipeline of remark and rehype plugins [packages/content-collections/src/configuration.ts:58-97]. The transformation accepts TransformOptions, which inherit from core MDX options while omitting raw plugin arrays in favor of customizable ResolvePlugins inputs for both remarkPlugins and rehypePlugins packages/content-collections/src/configuration.ts:13-15.

export interface TransformOptions extends Omit<MDXOptions, 'remarkPlugins' | 'rehypePlugins'> {
  remarkPlugins?: ResolvePlugins;
  rehypePlugins?: ResolvePlugins;
 
  /**
   * Generate `structuredData`
   *
   * @defaultValue true
   * @deprecated use `remarkStructureOptions` instead
   */
  generateStructuredData?: boolean;
 
  remarkStructureOptions?: Plugins.StructureOptions | boolean;
  remarkHeadingOptions?: Plugins.RemarkHeadingOptions | boolean;
  rehypeCodeOptions?: Plugins.RehypeCodeOptions | boolean;
  remarkImageOptions?: Plugins.RemarkImageOptions | boolean;
  remarkCodeTabOptions?: Plugins.RemarkCodeTabOptions | boolean;
}

Sources: packages/content-collections/src/configuration.ts:13-30

Option NameTypeDefault ValuePurpose
remarkStructureOptionsPlugins.StructureOptions | booleangenerateStructuredData ?? trueConfigures document structure extraction for search indexes
rehypeCodeOptionsPlugins.RehypeCodeOptions | booleantrueEnables code block syntax highlighting and processing
remarkHeadingOptionsPlugins.RemarkHeadingOptions | booleantrueExtracts headings to construct table of contents data
remarkImageOptionsPlugins.RemarkImageOptions | booleantrueProcesses Markdown images (configured with useImport: false)
remarkCodeTabOptionsPlugins.RemarkCodeTabOptions | booleantrueParses code tab syntax extensions if present in plugins
generateStructuredDatabooleanundefinedLegacy flag for structuredData; maps to remarkStructureOptions

Note

The remarkImageOptions plugin is hardcoded to set useImport: false, ensuring images are parsed inline rather than transformed into ES module imports during compilation.

Sources: packages/content-collections/src/configuration.ts:72-80, packages/content-collections/src/configuration.ts:108-110

Resolution Pipeline and File Data Extraction

Plugins are resolved using resolvePlugins and resolvePlugin, merging user-provided options with Fumadocs defaults packages/content-collections/src/configuration.ts:100-122. A final custom visitor function is appended to the remark pipeline to capture runtime file.data properties generated by plugins like table of contents extraction and structured data processing packages/content-collections/src/configuration.ts:114-120.

    rehypePlugins: resolvePlugins(
      (plugins) => [resolvePlugin(Plugins.rehypeCode, rehypeCodeOptions), ...plugins],
      rest.rehypePlugins,
    ),
    remarkPlugins: resolvePlugins(
      (plugins) => [
        Plugins.remarkGfm,
        resolvePlugin(Plugins.remarkHeading, remarkHeadingOptions),
        resolvePlugin(Plugins.remarkImage, remarkImageOptions, {
          useImport: false,
        }),
        'remarkCodeTab' in Plugins &&
          resolvePlugin(Plugins.remarkCodeTab, remarkCodeTabOptions),
        ...plugins,
        resolvePlugin(Plugins.remarkStructure, remarkStructureOptions),
        () => {
          return (_, file) => {
            data = file.data;
          };
        },
      ],
      rest.remarkPlugins,
    ),
  },
);

Sources: packages/content-collections/src/configuration.ts:100-124

Caution

The nested caching mechanism inside baseCompileMDX is explicitly overridden (cache: async (input, fn) => fn(input)) to prevent recursive caching conflicts between Content Collections and the MDX compiler packages/content-collections/src/configuration.ts:90-95.

Sources: packages/content-collections/src/configuration.ts:90-95

Virtual file mapping and sources

Creating MDX Sources

The createMDXSource function bridges raw Content Collections arrays into a structured Fumadocs source object packages/content-collections/src/index.ts:4-10. It accepts allDocs and allMetas collections conforming to BaseDocsData and BaseMetaData respectively, returning a unified Source object containing typed metaData and pageData generics packages/content-collections/src/index.ts:4-10.

export function createMDXSource<Docs extends BaseDocsData, Meta extends BaseMetaData>(
  allDocs: Docs[],
  allMetas: Meta[],
): Source<{
  metaData: Meta;
  pageData: Docs;
}> {

Sources: packages/content-collections/src/index.ts:4-10]

type File = VirtualFile<{
  metaData: Meta;
  pageData: Docs;
}>;
 

Sources: packages/content-collections/src/index.ts:11-15]

File Mapping Structure

The returned source maps each document and metadata record into a typed VirtualFile array packages/content-collections/src/index.ts:16-35. Document entries are mapped with a 'page' type, retaining their original data and path derived from v._meta.filePath packages/content-collections/src/index.ts:18-25. Metadata entries are mapped with a 'meta' type using the same path extraction strategy packages/content-collections/src/index.ts:26-33.

return {
  files: [
    ...allDocs.map(
      (v) =>
        ({
          type: 'page',
          data: v,
          path: v._meta.filePath,
        }) satisfies File,
    ),
    ...allMetas.map(
      (v) =>
        ({
          type: 'meta',
          data: v,
          path: v._meta.filePath,
        }) satisfies File,
    ),
  ],
};

Sources: packages/content-collections/src/index.ts:16-35]

Virtual File PropertyMapping SourceType DefinitionPurpose
typeLiteral string 'page' / 'meta''page' | 'meta'Discriminates document content from folder metadata files
datav (from allDocs or allMetas)Docs | MetaHolds the validated collection record payload
pathv._meta.filePathstringDefines the virtual file path used for routing and tree building

Sources: packages/content-collections/src/index.ts:18-33, packages/content-collections/src/types.ts:4-10

Note

The TypeScript satisfies operator is used during array mapping to ensure every virtual file strictly adheres to the local File type without widening inferred literal types packages/content-collections/src/index.ts:24, packages/content-collections/src/index.ts:32.

Sources: packages/content-collections/src/index.ts:24, packages/content-collections/src/index.ts:32

Collection definition and schema spec

Collection Definition Primitives

Fumadocs provides content definition helpers such as defineDocs, defineCollections, and docsCollection to structure documentation workspaces. The defineDocs helper accepts a target directory and configuration overrides for documentation and metadata collections, defaulting to content/docs when no directory is specified packages/mdx/src/config/define.ts:112-144.

export function defineDocs<
  DocSchema extends StandardSchemaV1 = typeof pageSchema,
  MetaSchema extends StandardSchemaV1 = typeof metaSchema,
>(options: {
  dir?: string;
  docs?: Omit<DocCollection<DocSchema>, 'dir' | 'type'>;
  meta?: Omit<MetaCollection<MetaSchema>, 'dir' | 'type'>;
}): DocsCollection<DocSchema, MetaSchema> {
  const dir = options.dir ?? 'content/docs';
 
  return {
    type: 'docs',
    dir,
    docs: defineCollections({
      type: 'doc',
      dir,
      schema: pageSchema as any,
      ...options?.docs,
    }),
    meta: defineCollections({
      type: 'meta',
      dir,
      schema: metaSchema as any,
      ...options?.meta,
    }),
  };
}

Sources: packages/mdx/src/config/define.ts:112-144]

Standard Schema Validation Specifications

Collections enforce runtime data integrity using the Standard Schema specification (StandardSchemaV1), supporting static schemas or context-aware schema generator functions packages/content/src/index.ts:1-14, packages/mdx/src/config/define.ts:9-12. The docsCollection factory constructs combined MDX document collections and JSON/YAML metadata collections backed by pageSchema and metaSchema defaults packages/content/src/index.ts:35-53.

Collection PropertyType / SignatureDefault ValuePurpose
dirstring'content/docs'Root filesystem directory scanned for collection files
docsDocsMDXCollectionConfigpageSchemaConfiguration and validation schema for MDX page frontmatter
metaDataCollectionConfigmetaSchemaConfiguration and validation schema for folder metadata files
schemaSchema | ((ctx) => Schema)pageSchema / metaSchemaStandard Schema validator or dynamic factory function

Sources: packages/content/src/index.ts:35-53, packages/mdx/src/config/define.ts:9-12, packages/mdx/src/config/define.ts:112-144]

Important

When defining a collection schema using a function, the context parameter provides file-specific metadata { path: string; source: string }, allowing validation rules to adapt dynamically based on file location or content structure.

Sources: packages/mdx/src/config/define.ts:9-12]

Was this page helpful?