Skip to main content
doc0blade47/fumadocsdocumentation home
Sign in

MDX Loader Pipeline

Last updated Oct 12, 2026100% grounded
Relevant source files

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

Overview

The MDX loader pipeline handles content transformation and bundling within Bundler Plugins, Content Compiler Plugins, and Source Loader integrations. It processes documentation source files through unified processors, applying remark and rehype transformations to generate type-safe modules and structured outputs.

Sources: packages/mdx/src/loaders/mdx/index.ts:25-108, packages/mdx/src/loaders/mdx/build-mdx.ts:74-122

MDX Loader Factory and Entrypoints

Loader Factory and Query Validation

The createMdxLoader factory function receives a ConfigLoader and returns a standard Loader object that tests files against mdxLoaderGlob. During the load execution, query parameters are validated via querySchema, which parses loose objects with default options: only (frontmatter or all), collection, and workspace. If a workspace identifier is provided, the core instance is retrieved from core.getWorkspaces().

const querySchema = z.looseObject({
  only: z.literal(['frontmatter', 'all']).default('all'),
  collection: z.string().optional(),
  workspace: z.string().optional(),
});

Sources: packages/mdx/src/loaders/mdx/index.ts:11-15

Note

When only is set to frontmatter, the loader skips MDX compilation entirely and returns a serialized export of the parsed frontmatter data directly. Sources: packages/mdx/src/loaders/mdx/index.ts:81-86

Build caching can be enabled under production environments when experimentalBuildCache is set in global configuration. The loader checks disk cache entries using an MD5 hash of the file path and compares content hashes to avoid redundant compilations. Sources: packages/mdx/src/loaders/mdx/index.ts:39-60

Sources: packages/mdx/src/loaders/mdx/index.ts:25-60

Node Entrypoints and Execution Sequence

Node.js module loading integration is provided via initialize and load hooks in packages/mdx/src/node/_loader.ts, as well as a deprecated legacy loader export in packages/mdx/src/node/loader.ts. The modern module loader initializes a core instance with the node-loader environment and builds standalone configuration loaders before wrapping MDX and meta loaders for Node. Sources: packages/mdx/src/node/_loader.ts:11-29, packages/mdx/src/node/loader.ts:8-27

Sources: packages/mdx/src/loaders/mdx/index.ts:25-28, packages/mdx/src/node/_loader.ts:11-25, packages/mdx/src/loaders/mdx/build-mdx.ts:74-81

The pipeline execution sequence flows through specific functions during document loading:

  1. initialize — Sets up the core configuration and hooks in packages/mdx/src/node/_loader.ts. Sources: packages/mdx/src/node/_loader.ts:11-29
  2. createMdxLoader — Instantiates the loader object and parses query parameters and frontmatter in packages/mdx/src/loaders/mdx/index.ts. Sources: packages/mdx/src/loaders/mdx/index.ts:25-32
  3. buildMDX — Coordinates VFile preparation, custom transformations, and compiler invocation in packages/mdx/src/loaders/mdx/build-mdx.ts. Sources: packages/mdx/src/loaders/mdx/build-mdx.ts:74-121
  4. getProcessor — Retrieves or creates a cached Unified processor instance configured with remark and postprocess plugins in packages/mdx/src/loaders/mdx/build-mdx.ts. Sources: packages/mdx/src/loaders/mdx/build-mdx.ts:81-108

Sources: packages/mdx/src/loaders/mdx/index.ts:25-32, packages/mdx/src/node/_loader.ts:11-29, packages/mdx/src/loaders/mdx/build-mdx.ts:74-121

MDX Compilation with Unified Processors

Call-Chain Execution Walkthrough and Sequence

The execution trace for building and compiling MDX content flows through four primary stages, invoking specific functions in sequence: loader → createMdxLoader → buildMDX → getProcessor.

  1. loader — The Webpack or bundler adapter receives raw file content and calls the asynchronous loader callback function. Sources: packages/mdx/src/webpack/mdx.ts:9-28
  2. createMdxLoader — Parses query parameters, reads frontmatter, checks build caches, and calls buildMDX with the adjusted source string and compiler context. Sources: packages/mdx/src/loaders/mdx/index.ts:28-97
  3. buildMDX — Initializes a VFile instance with the source string, file path, and embedded custom properties like _getProcessor, applies collection-level transforms via transformVFile, and invokes the processor. Sources: packages/mdx/src/loaders/mdx/build-mdx.ts:74-121
  4. getProcessor — Retrieves or instantiates a cached Unified processor using @mdx-js/mdx configured with remarkInclude, user remark plugins, and remarkPostprocess. Sources: packages/mdx/src/loaders/mdx/build-mdx.ts:81-108

Sources: packages/mdx/src/webpack/mdx.ts:9-28, packages/mdx/src/loaders/mdx/index.ts:88-97, packages/mdx/src/loaders/mdx/build-mdx.ts:74-121

Compiler Options and Data Types

PropertyTypePurpose
filePathstringSpecifies the absolute or relative file path for the source document being compiled.
sourcestringRaw markdown or MDX content string, offset by frontmatter newline counts.
environment'bundler' | 'runtime'Defines the target execution environment for MDX configuration loading.
isDevelopmentbooleanFlags whether development mode is active, toggling debug features in @mdx-js/mdx.
_compilerCompilerOptionsOptional compiler reference supplying an addDependency method for file watchers.

Sources: packages/mdx/src/loaders/mdx/build-mdx.ts:14-29

Warning

When compiling documents, buildMDX prepends newline characters corresponding to the exact length of the stripped frontmatter block. This ensures that line numbers reported in parser or compilation errors match the original source file line numbers precisely. Sources: packages/mdx/src/loaders/mdx/index.ts:88-92

Preset Plugins and Processor Configuration

Preset Application and Options Architecture

The configuration pipeline provides two main preset options: fumadocs and minimal. The applyMdxPreset function accepts MDXPresetOptions and returns an asynchronous function resolving to @mdx-js/mdx ProcessorOptions. When set to minimal, options are returned directly without plugin injections. The mdxPreset function in the core package similarly builds processor options with a default outputFormat of 'function-body' for server or runtime evaluation.

Option KeyTypeDefault ValuePurpose
preset'fumadocs' | 'minimal''fumadocs'Selects the processor preset strategy.
valueToExportstring[][]Specifies property names to export from vfile.data.
remarkStructureOptionsPlugins.StructureOptions | false{ exportAs: 'structuredData' }Configures headings and structure extraction.
remarkHeadingOptionsPlugins.RemarkHeadingOptions{ generateToc: false }Configures heading parsing without TOC generation.
remarkImageOptionsPlugins.RemarkImageOptions | falseDynamic (useImport true for bundlers)Configures image processing behaviors.
remarkCodeTabOptionsPlugins.RemarkCodeTabOptions | falseundefinedEnables or configures code tab remark processing.
remarkNpmOptionsPlugins.RemarkNpmOptions | falseundefinedEnables or configures package manager code block transformations.
rehypeCodeOptionsPlugins.RehypeCodeOptions | falseundefinedConfigures syntax highlighting and code block enhancements.

Sources: packages/mdx/src/config/preset.ts:8-46, packages/core/src/content/mdx/preset-runtime.ts:5-18

Note

In bundler environments, remarkImage defaults useImport to true, ensuring image sources are correctly imported as module assets. In runtime environments, bundler-specific outputs shift to function bodies. Sources: packages/mdx/src/config/preset.ts:82-82, packages/mdx/src/config/preset.ts:127-127

Remark and Rehype Plugin Pipeline

The remark plugin pipeline integrates remarkGfm, remarkHeading, remarkImage, remarkCodeTab, remarkNpm, and remarkStructure. It also processes custom valueToExport arrays by reading matching keys from file.data and pushing them into file.data['mdx-export']. The rehype pipeline integrates rehypeCode and rehypeToc. Both pipelines support custom Pluggable arrays or modifier functions via pluginOption or resolvePlugins.

export * from './remark-gfm';
export * from './rehype-code';
export * from './remark-image';
export * from './remark-structure';
export * from './remark-heading';
export * from './remark-admonition';
export * from './remark-directive-admonition';
export * from './rehype-toc';
export * from './remark-code-tab';
export * from './remark-steps';
export * from './remark-npm';
export * from './codeblock-utils';
export { remarkMdxFiles, type RemarkMdxFilesOptions } from './remark-mdx-files';
export * from './remark-mdx-mermaid';
export * from './remark-feedback-block';
export type { LLMsOptions } from './remark-llms';

Sources: packages/core/src/mdx-plugins/index.ts:1-16

Warning

Setting individual remark or rehype option flags explicitly to false (such as remarkImageOptions: false or rehypeCodeOptions: false) completely disables the corresponding plugin from being appended to the unified pipeline array. Sources: packages/mdx/src/config/preset.ts:78-88, packages/mdx/src/config/preset.ts:116-123

Meta and Configuration Loaders

Metadata File Loader Parsing and Transformation

Metadata loaders intercept JSON and YAML source files matching collection patterns, applying Zod schema validation over query parameters to extract collection and workspace identifiers. The parse function handles file extensions by invoking JSON.parse for JSON files and js-yaml's load for YAML files, wrapping failures with detailed error context.

function parse(filePath: string, source: string) {
  try {
    if (filePath.endsWith('.json')) return JSON.parse(source);
    if (filePath.endsWith('.yaml')) return load(source);
  } catch (e) {
    throw new Error(`invalid data in ${filePath}`, { cause: e });
  }
 
  throw new Error('Unknown file type ' + filePath);
}

Sources: packages/mdx/src/loaders/meta.ts:25-34

Note

When the collection query parameter is omitted or fails validation, the metadata loader falls back to bundler built-in plugins by returning null, allowing default file resolution to take over. Sources: packages/mdx/src/loaders/meta.ts:37-38

Adapter Transformation and Output Generation

The loader produces output modules based on the resolved file type and configuration options. For JSON files, the moduleType can be configured as either 'json' or 'js', whereas YAML files always transpile to JavaScript default exports.

Resolve Option KeyTypeDefault ValuePurpose
json'json' | 'js''js'Specifies module output format for JSON meta files.
yaml'js''js'Specifies module output format for YAML meta files.

Sources: packages/mdx/src/loaders/meta.ts:18-23

if (input.filePath.endsWith('.json')) {
  return {
    moduleType: resolveJson,
    code:
      resolveJson === 'json'
        ? JSON.stringify(data)
        : `export default ${JSON.stringify(data)}`,
  };
} else {
  return {
    moduleType: 'js',
    code: `export default ${JSON.stringify(data)}`,
  };
}

Sources: packages/mdx/src/loaders/meta.ts:80-93

Warning

If a metadata collection item is defined in the source config, raw parsed data passes through core.transformMeta before export generation, altering the final structure returned to consumers. Sources: packages/mdx/src/loaders/meta.ts:61-69

Core Plugin Pipeline Lifecycle

Initialization and Execution Call Chain

The core plugin pipeline lifecycle manages core instance initialization, workspace discovery, and plugin hook execution. The process begins with createMDX, which invokes createNextCore and subsequently createCore to instantiate the core context and resolve plugins via getPlugins.

  1. createMDX — Initializes the core instance by wrapping configuration options. Sources: packages/mdx/src/next/index.ts:30-31

  2. createNextCore — Generates a core instance with specific environment defaults and the index plugin. Sources: packages/mdx/src/next/index.ts:200-206

  3. createCore — Instantiates the core object, setting up internal caches, workspaces, and transformation methods. Sources: packages/mdx/src/core.ts:148-152

  4. getPlugins — Flattens and aggregates plugin option arrays asynchronously into a unified array of plugins. Sources: packages/mdx/src/core.ts:136-146

Sources: packages/mdx/src/next/index.ts:30-31, packages/mdx/src/next/index.ts:200-206, packages/mdx/src/core.ts:136-152

Warning

During core initialization (core.init), caches and workspaces are cleared, and config plugins are executed sequentially, allowing each plugin to mutate the loaded configuration before workspace resolution occurs. Sources: packages/mdx/src/core.ts:176-185

Plugin Hook Dispatch and Transformation Methods

The core instance exposes explicit methods to invoke lifecycle hooks across registered plugins. When emitting files or transforming content, emit, transformMeta, transformFrontmatter, and transformVFile iterate through the plugins sequentially.

async emit(emitOptions: EmitOptions = {}): Promise<EmitOutput> {
  const { filterPlugin, filterWorkspace, write = false } = emitOptions;
  const start = performance.now();
  const ctx = this.getPluginContext();
  const added = new Set<string>();
  const out: EmitOutput = {
    entries: [],
    workspaces: {},
  };
 
  for (const li of await Promise.all(
    plugins.map((plugin) => {
      if ((filterPlugin && !filterPlugin(plugin)) || !plugin.emit) return;
      return plugin.emit.call(ctx);
    }),
  )) {
    if (!li) continue;
    for (const item of li) {
      if (added.has(item.path)) continue;
      out.entries.push(item);
      added.add(item.path);
    }
  }

Sources: packages/mdx/src/core.ts:244-266

Hook MethodContext PassedIteration BehaviorPurpose
configPluginContextSequential overrideModifies or replaces loaded configuration.
emitPluginContextParallel execution via Promise.allGenerates virtual or persistent output entries.
configureServerServerContextSequential executionSets up development server watchers or middleware.
meta.transformTransformOptions & PluginContextSequential pipeTransforms metadata collection items after validation.
doc.frontmatterTransformOptions & PluginContextSequential pipeTransforms document frontmatter after schema validation.
doc.vfileTransformOptions & PluginContextSequential pipeModifies the virtual file container for documents.

Sources: packages/mdx/src/core.ts:182-185, packages/mdx/src/core.ts:237-239, packages/mdx/src/core.ts:254-258, packages/mdx/src/core.ts:302-304, packages/mdx/src/core.ts:318-320, packages/mdx/src/core.ts:333-335

Caution

Workspace instantiation supports a maximum depth of 1; child workspaces recursively invoke createCore with prefixed output directories, and failing to respect this depth limitation results in unhandled configuration loops. Sources: packages/mdx/src/core.ts:187-203

Was this page helpful?