---
title: "Remote MDX"
description: "Remote MDX is a specialized subsystem within the Fumadocs ecosystem that enables the dynamic compilation and execution of MDX content, typically outside of the primary build-time bundler context. B..."
last_updated: "2026-07-02T09:46:39.656126+00:00"
canonical_url: "https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/content-engine/remote-mdx"
---

<details>
<summary>Relevant source files</summary>

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

- [packages/mdx/src/loaders/mdx/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/loaders/mdx/index.ts)
- [packages/mdx/src/runtime/dynamic.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/runtime/dynamic.ts)
- [packages/mdx/src/plugins/index-file.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/plugins/index-file.ts)
- [packages/preview/src/pages/[...slugs].tsx](https://github.com/blade47/fumadocs/blob/main/packages/preview/src/pages/%5B...slugs%5D.tsx)
- [packages/mdx/src/node/_loader.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/node/_loader.ts)
- [packages/core/src/source/dynamic.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/source/dynamic.ts)
- [packages/core/src/content/md.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/content/md.ts)
- [packages/local-md/src/md/renderer.ts](https://github.com/blade47/fumadocs/blob/main/packages/local-md/src/md/renderer.ts)
- [packages/local-md/src/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/local-md/src/index.ts)
- [packages/mdx/src/webpack/mdx.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/webpack/mdx.ts)
- [packages/mdx/src/webpack/meta.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/webpack/meta.ts)
- [packages/mdx-remote/src/compile.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx-remote/src/compile.ts)
- [packages/mdx/src/runtime/browser.tsx](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/runtime/browser.tsx)
- [packages/core/src/mdx-plugins/remark-llms.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/remark-llms.ts)
- [packages/mdx/src/runtime/server.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/runtime/server.ts)
- [packages/mdx/src/loaders/mdx/remark-include.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/loaders/mdx/remark-include.ts)
- [packages/mdx-remote/src/render.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx-remote/src/render.ts)
- [packages/mdx-remote/src/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx-remote/src/index.ts)
- [packages/mdx/src/loaders/mdx/build-mdx.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/loaders/mdx/build-mdx.ts)
- [packages/core/src/content/mdx/preset-runtime.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/content/mdx/preset-runtime.ts)
- [packages/asyncapi/src/ui/components/markdown.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/components/markdown.tsx)
- [packages/mdx-remote/src/client/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx-remote/src/client/index.ts)
- [packages/openapi/src/ui/components/markdown.tsx](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/components/markdown.tsx)
- [packages/local-md/src/md/compiler.ts](https://github.com/blade47/fumadocs/blob/main/packages/local-md/src/md/compiler.ts)
- [packages/preview/src/components/markdown.tsx](https://github.com/blade47/fumadocs/blob/main/packages/preview/src/components/markdown.tsx)
- [packages/core/src/mdx-plugins/remark-llms.runtime.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/remark-llms.runtime.ts)
- [packages/mdx/src/core.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/core.ts)
- [packages/content-collections/src/configuration.ts](https://github.com/blade47/fumadocs/blob/main/packages/content-collections/src/configuration.ts)
- [packages/preview/src/lib/md.ts](https://github.com/blade47/fumadocs/blob/main/packages/preview/src/lib/md.ts)
- [packages/mdx/src/utils/fs-cache.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/utils/fs-cache.ts)
</details>

Remote MDX is a specialized subsystem within the Fumadocs ecosystem that enables the dynamic compilation and execution of MDX content, typically outside of the primary build-time bundler context. By decoupling the MDX processor from static build steps, it allows for on-demand rendering, remote content fetching, and runtime evaluation of Markdown documents. This is essential for applications requiring highly flexible content delivery, such as CMS-backed documentation or platform-agnostic content rendering where source files may not be available to the compiler until runtime.

The subsystem bridges the gap between raw text content (stored as strings or files) and React-based UI components. It achieves this by providing a unified `dynamic` entry point that handles the initialization of the compiler core, mapping document collections to lazy-loading entries, and executing the compiled MDX via custom-built `AsyncFunction` wrappers. This architecture supports advanced features like frontmatter transformation, cached file reads, and structured data extraction, ensuring consistency between build-time and runtime content environments.

Interacting with the broader Fumadocs system, Remote MDX leverages existing remark and rehype plugin pipelines. Its design favors "pre-compilation" where possible—compiling content into a serialized JavaScript format—which allows runtime components to simply hydrate the result rather than re-running heavy transformation chains. This performance-oriented approach ensures that even "dynamic" content maintains the efficiency expected of statically generated documentation.

## Core Compilation Mechanism

The Remote MDX pipeline processes content by transforming raw source strings into executable JavaScript representations. This process is orchestrated by `buildMDX`, which utilizes `@mdx-js/mdx` to create a `Processor` instance configured according to the global Fumadocs settings.

```mermaid
flowchart TD
    A["Raw Content"] --> B["frontmatter()"]
    B --> C["buildMDX()"]
    C --> D["MDX Processor"]
    D --> E["Compiled Program String"]
    E --> F["executeMdx()"]
    F --> G["React Components"]
```
Sources: [packages/mdx/src/runtime/dynamic.ts:75-81](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/runtime/dynamic.ts#L75-L81), [packages/mdx/src/loaders/mdx/build-mdx.ts:92-102](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/loaders/mdx/build-mdx.ts#L92-L102)

The `buildMDX` function is the primary gatekeeper, ensuring that all plugins and post-processing steps (such as `remark-include`) are applied correctly before the content is serialized. The `executeMdx` helper then uses an `AsyncFunction` constructor to instantiate the compiled code string into a runnable object. This allows the system to treat the output of an MDX file as a standard, dynamic module that can be injected with specific React scopes and runtimes.

## Dynamic Collection Handling

The `dynamic` utility coordinates how individual documents within a collection are exposed for runtime access. By using `convertLazyEntries`, it wraps file content processing into asynchronous factory functions (`head` and `body` getters). 

> [!NOTE]
> The `body` getter uses a caching strategy where `(cachedResult ??= compile(entry))` ensures that a specific document is only compiled once per lifecycle, preventing redundant expensive CPU operations during concurrent requests.

Sources: [packages/mdx/src/runtime/dynamic.ts:91-91](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/runtime/dynamic.ts#L91-L91)

The system distinguishes between `doc` and `docs` collection types, applying appropriate metadata resolution via `getDocCollection`. When an entry is accessed, it triggers the file-system-based compilation process, reading the physical file from `info.fullPath` and processing it through the runtime MDX builder.

## Runtime Execution Architecture

The runtime execution layer uses the `executeMdx` function to handle the final conversion of compiled strings to interactive components. It establishes an isolated scope by merging user-provided context with the default JSX runtime.

```mermaid
sequenceDiagram
    participant Source as Compiled MDX String
    participant Exec as executeMdx()
    participant Runtime as JSX Runtime
    Source->>Exec: compiled body
    Exec->>Exec: Construct fullScope
    Exec->>Runtime: hydrateFn.apply(..., scope)
    Runtime-->>Exec: React Components
    Exec-->>Source: Rendered Output
```
Sources: [packages/mdx/src/runtime/dynamic.ts:32-45](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/runtime/dynamic.ts#L32-L45)

By creating a function via `new AsyncFunction(...Object.keys(fullScope), compiled)`, the system dynamically generates a closure that treats the MDX-compiled source as if it were a local module. This mechanism bypasses the need for manual file system writes in high-performance runtime environments.

## Index File Generation and Emission

The `index-file` plugin is responsible for generating the glue code that bridges static configuration with dynamic entry points. It works by inspecting the internal `Core` state and emitting TypeScript files that register collections to the runtime.

| Choice | Benefit | Cost |
| :--- | :--- | :--- |
| **Code Generation** | Type safety, static optimization | Adds complexity to build step |
| **Lazy Globbing** | Minimal memory overhead | Requires runtime resolution |
| **Caching Cache Dir** | Faster re-compilations | Disk I/O overhead |

Sources: [packages/mdx/src/plugins/index-file.ts:121-157](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/plugins/index-file.ts#L121-L157)

The `emit` loop systematically creates `server.ts`, `dynamic.ts`, and `browser.ts` entry points. The selection of which collections to include is performed by evaluating `isDynamic(collection)`, a check that ensures only collections specifically flagged for runtime compilation are subjected to the dynamic index generation logic.

## Frontmatter and Content Invariants

Remote MDX maintains strict invariants when handling frontmatter, especially in dynamic collections. The `core.transformFrontmatter` method is the centralized point for this, ensuring that data validation (via Zod schemas) and plugin-based transformations are always applied before the data touches the compiler.

> [!CAUTION]
> If a collection defines a `schema`, it MUST pass validation during the `transformFrontmatter` phase. Failure to do so at runtime will result in an `Error` thrown early in the pipeline, preventing partially malformed data from ever entering the rendering loop.

Sources: [packages/mdx/src/core.ts:153-169](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/core.ts#L153-L169)

## Integration Example

Below is a simplified example demonstrating how one would invoke the dynamic loader to access a document collection at runtime.

```typescript
import { dynamic } from 'fumadocs-mdx/runtime/dynamic';

// 1. Initialized with config exports, core options, and server runtime settings
const runtime = await dynamic(
  configExports, 
  { environment: 'runtime', configPath: './source.config.ts', outDir: '.source' },
  { doc: { passthroughs: ['extractedReferences'] } }
);

// 2. Fetch a document from the collection
const docEntry = await runtime.doc('blog', '/base/path', [
  { 
    info: { path: 'example.mdx', fullPath: './content/example.mdx' },
    data: { title: 'Hello World' } 
  }
]);
```
Sources: [packages/mdx/src/runtime/dynamic.ts:47-123](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/runtime/dynamic.ts#L47-L123)

## Related

- [MDX Bundling](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/content-engine/mdx-bundling)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/llms.txt) for all pages in this wiki.
