Orientation
Content Processing
Search Infrastructure
Rendering and UI
Developer Tooling
How It Works
The following files were used as context for generating this wiki page:
Fumadocs is a modular documentation framework designed to bridge the gap between static content and dynamic, reactive documentation sites. At its core, the system solves the complexity of managing Markdown/MDX content by providing a robust pipeline that handles everything from file parsing and MDX transformation to runtime data orchestration.
The system is architected around a collection-based data model. Instead of treating files as isolated entities, Fumadocs groups them into collections, allowing for structured access via plugins. This separation of concerns—parsing and transformation in the build/runtime phase versus presentation in the UI components—allows developers to use Fumadocs across various frameworks, including Next.js, Vite, and Waku.
Central to this architecture is the Core package, which provides the foundational logic for source handling and schema validation. By layering specific "source" packages (like mdx, local-md, or openapi) on top of this core, the framework enables high-performance content delivery, incremental updates via file system watchers, and specialized integrations like TypeScript type-table generation and OpenAPI documentation.
The content orchestration mechanism functions as a multi-stage pipeline that ensures data consistency across the development lifecycle. When a content collection is defined—for example, via docsCollection or mdxCollection—the framework registers hooks (like onEmit) to generate the necessary glue code that links the static source with the application's runtime.
The system uses a virtual file generator to create manifests. In the case of DocsCollection, this mechanism ensures that the relationship between documentation content and metadata is preserved and type-safe.
Sources: packages/mdx/src/vite/index.ts:106-108, packages/content/src/index.ts:58-69
Fumadocs employs a two-pronged strategy for content processing: static compilation for production and dynamic runtime execution for development or edge-case scenarios. The mdx package provides a Vite plugin interface (mdx(config)) that manages this transition.
During the Vite build process, the plugin initializes a Core instance that builds the configuration, then configures mdxLoader and metaLoader to intercept file transformations.
Note
The id.includes('virtual:vite-rsc') guard in the Vite plugin is a crucial invariant. It prevents the MDX loader from attempting to process compiled RSC (React Server Components) client references, which would otherwise corrupt the JavaScript output stream.
Sources: packages/mdx/src/vite/index.ts:57-86
When running in dynamic mode (e.g., during development or when using dynamic.ts), content is evaluated using executeMdx. This avoids re-compilation for every single request by leveraging a caching mechanism in convertLazyEntries.
The flow for retrieving dynamic content is:
getDocCollection verifies the collection name.convertLazyEntries registers a map of file paths to lazy compilation functions.body[path]) uses cachedResult to ensure the compilation occurs only once per instance.Sources: packages/mdx/src/runtime/dynamic.ts:67-92
The packages/core system exposes schema definitions (pageSchema, metaSchema) that are used by all content collections. This standardizes the frontmatter structure across different content types.
Sources: packages/content/src/index.ts:6, packages/content/src/runtime.ts:44-50
Fumadocs supports an extensible architecture through "Registry" plugins, used primarily by the CLI for scaffolded UI components. Components are registered with a dir and a files array that maps source paths to destination targets in the consumer's project.
Tip
Use the pluginPreserveLayouts helper if you are developing custom documentation layouts. It prevents the CLI from overwriting core fumadocs-ui layout files unless a direct installation is requested by the user.
Sources: packages/cli/src/registry/plugins/preserve.ts:6-13, packages/radix-ui/registry/index.ts:9-14
The architecture makes deliberate choices to balance speed against developer experience.
Sources: packages/mdx/src/vite/index.ts:35, packages/mdx/src/runtime/dynamic.ts:91
To integrate a new collection that automatically includes shared remark plugins, you can use the docsMdxCollection utility.
import { docsMdxCollection } from 'fumadocs-content';
import { pageSchema } from 'fumadocs-core/source/schema';
// This demonstrates how to define a collection that
// includes standard remark plugins during the bundling phase.
export const docCollection = docsMdxCollection({
dir: 'content/docs',
frontmatter: pageSchema,
options: {
remarkPlugins: [/* Add custom plugins here */],
},
});Sources: packages/content/src/index.ts:16-33