Skip to main content
The loader API provides file transformation for MDX and metadata files across different bundler environments.

createMdxLoader

Creates a loader for transforming MDX files into executable JavaScript.
import { createMdxLoader } from 'fumadocs-mdx/loaders/mdx';
import type { ConfigLoader } from 'fumadocs-mdx/loaders/config';

const mdxLoader = createMdxLoader(configLoader);
configLoader
ConfigLoader
required
Configuration loader instance that provides access to the core system

Returns

test
RegExp
Matches .md and .mdx files with optional query strings
load
(input: LoaderInput) => Promise<LoaderOutput>
Transforms MDX content into JavaScript modules

Query Parameters

The loader accepts query parameters to customize behavior:
collection
string
Name of the collection to use for this file
workspace
string
Workspace name for multi-workspace configurations
only
'frontmatter' | 'all'
default:"'all'"
Load only frontmatter or the complete compiled MDX

Example

import page from './content/docs/introduction.mdx?collection=docs';
// Returns compiled MDX component

import { frontmatter } from './content/docs/introduction.mdx?collection=docs&only=frontmatter';
// Returns only frontmatter data

createMetaLoader

Creates a loader for JSON and YAML metadata files.
import { createMetaLoader } from 'fumadocs-mdx/loaders/meta';

const metaLoader = createMetaLoader(configLoader, {
  json: 'js',
  yaml: 'js'
});
configLoader
ConfigLoader
required
Configuration loader instance
resolve.json
'json' | 'js'
default:"'js'"
Output format for JSON files. Use 'json' for JSON modules or 'js' for ES modules
resolve.yaml
'js'
default:"'js'"
Output format for YAML files (always ES modules)

Returns

A Loader that parses and validates metadata files.

Loader Interface

The universal loader interface for different bundler environments.
interface Loader {
  test?: RegExp;
  load: (input: LoaderInput) => Awaitable<LoaderOutput | null>;
  bun?: {
    load?: (source: string, input: LoaderInput) => Awaitable<Bun.OnLoadResult>;
  };
}
test
RegExp
Regular expression to filter file paths and URLs
load
(input: LoaderInput) => Promise<LoaderOutput | null>
Transform function. Returns null to skip transformation
bun.load
(source: string, input: LoaderInput) => Promise<Bun.OnLoadResult>
Bun-specific loader for synchronous dynamic imports

LoaderInput

interface LoaderInput {
  development: boolean;
  compiler: CompilerOptions;
  filePath: string;
  query: Record<string, string | string[] | undefined>;
  getSource: () => string | Promise<string>;
}
development
boolean
Whether running in development mode
compiler
CompilerOptions
Compiler context for tracking dependencies
filePath
string
Absolute path to the file being loaded
query
Record<string, string | string[]>
Parsed query parameters from the import URL
getSource
() => string | Promise<string>
Function to retrieve the file contents

LoaderOutput

interface LoaderOutput {
  code: string;
  map?: unknown;
  moduleType?: 'js' | 'json';
}
code
string
required
The transformed JavaScript or JSON code
map
unknown
Source map for the transformation
moduleType
'js' | 'json'
Module type hint (supported in Vite 8+)

Adapter Functions

Convert loaders to bundler-specific formats.

toNode

Convert to Node.js module.register() loader.
import { toNode } from 'fumadocs-mdx/loaders/adapter';
import type { LoadHook } from 'node:module';

const nodeLoader: LoadHook = toNode(mdxLoader);

toVite

Convert to Vite plugin transform hook.
import { toVite } from 'fumadocs-mdx/loaders/adapter';

const viteLoader = toVite(mdxLoader);

export default {
  plugins: [
    {
      name: 'fumadocs-mdx',
      transform: viteLoader.transform,
    }
  ]
};

toWebpack

Convert to Webpack loader.
import { toWebpack } from 'fumadocs-mdx/loaders/adapter';

const webpackLoader = toWebpack(mdxLoader);

module.exports = {
  module: {
    rules: [
      {
        test: /\.mdx?$/,
        use: [webpackLoader]
      }
    ]
  }
};

toBun

Convert to Bun plugin.
import { toBun } from 'fumadocs-mdx/loaders/adapter';
import type { BunPlugin } from 'bun';

const bunPlugin: BunPlugin = {
  name: 'fumadocs-mdx',
  setup(build) {
    toBun(mdxLoader)(build);
  }
};

ConfigLoader

Provides access to the configuration system.
interface ConfigLoader {
  getCore(): Promise<Core>;
}

createStandaloneConfigLoader

Creates a config loader that manages its own lifecycle.
import { createStandaloneConfigLoader } from 'fumadocs-mdx/loaders/config';

const configLoader = createStandaloneConfigLoader({
  core,
  buildConfig: true,
  mode: 'production'
});
core
Core
required
Uninitialized core instance
buildConfig
boolean
required
Whether to build the configuration from source
mode
'dev' | 'production'
required
Development mode enables config hot-reloading

createIntegratedConfigLoader

Creates a config loader from an already initialized core.
import { createIntegratedConfigLoader } from 'fumadocs-mdx/loaders/config';

const configLoader = createIntegratedConfigLoader(core);
core
Core
required
Initialized core instance

Bundler Integrations

Next.js

import { createMDX } from 'fumadocs-mdx/next';

const withMDX = createMDX({
  configPath: 'source.config.ts',
  outDir: '.source',
  index: { target: 'default' }
});

export default withMDX({
  // Next.js config
});
configPath
string
default:"'source.config.ts'"
Path to configuration file
outDir
string
default:"'.source'"
Output directory for generated files
index
IndexFilePluginOptions | false
default:"{}"
Index file generation options, or false to disable

Bun

import { createMdxPlugin } from 'fumadocs-mdx/bun';

Bun.plugin(createMdxPlugin({
  environment: 'bun',
  configPath: 'source.config.ts',
  disableMetaFile: false
}));
environment
string
default:"'bun'"
Environment identifier
configPath
string
default:"'source.config.ts'"
Path to configuration file
disableMetaFile
boolean
default:"false"
Skip transformation of JSON/YAML metadata files

Node.js

import { register } from 'node:module';

register('fumadocs-mdx/node/loader', import.meta.url);
The Node.js loader automatically handles .mdx and metadata files using module.register().

Build Cache

Enable experimental build caching for production builds:
export default defineConfig({
  experimentalBuildCache: '.cache'
});
The cache stores compiled MDX output keyed by content hash. Delete the cache directory to invalidate.

Build docs developers (and LLMs) love