MUI Docs Infra

Warning

This is an internal project, and is not intended for public use. No support or stability guarantees are provided.

With Docs Infra

The withDocsInfra function is a Next.js configuration plugin that sets up webpack loaders, Turbopack rules, and page extensions required for MUI docs infrastructure. It automatically configures code highlighting loaders for demo files and provides sensible defaults for documentation sites.

Features

  • Configures webpack and Turbopack loaders for demo files (index.ts and client.ts)
  • Sets up page extensions to support .md, .mdx, .ts, .tsx, .js, .jsx files
  • Enables export output mode by default for static site generation
  • Provides extensible patterns for custom demo file structures
  • Includes companion getDocsInfraMdxOptions for MDX plugin configuration

Basic Usage

// next.config.mjs
import { withDocsInfra } from '@mui/internal-docs-infra/withDocsInfra';

const nextConfig = {
  // Your existing Next.js config
};

export default withDocsInfra()(nextConfig);

Advanced Configuration

// next.config.mjs
import { withDocsInfra, getDocsInfraMdxOptions } from '@mui/internal-docs-infra/withDocsInfra';
import createMDX from '@next/mdx';

const withMDX = createMDX({
  options: getDocsInfraMdxOptions({
    // Control index generation
    extractToIndex: {
      include: ['app/docs', 'app/api'],
      exclude: ['app/docs/internal'],
    },
  }),
});

const nextConfig = {
  // Your Next.js config
};

export default withDocsInfra({
  // Add support for additional file extensions
  additionalPageExtensions: ['vue', 'svelte'],

  // Disable export output if using server features
  enableExportOutput: false,

  // Add custom demo patterns beyond the defaults
  additionalDemoPatterns: {
    index: ['./app/**/demos/*/demo-*/index.ts'],
    client: ['./app/**/demos/*/demo-*/client.ts'],
  },

  // Add custom Turbopack rules
  additionalTurbopackRules: {
    './custom/**/*.ts': {
      loaders: ['custom-loader'],
    },
  },

  // Comment extraction for sourceEnhancers
  // Collect @highlight comments to pass to enhancers
  notableCommentsPrefix: ['@highlight', '@focus'],
  // Strip @internal comments from displayed source
  removeCommentsWithPrefix: ['@internal'],

  // Strip "Documentation: <url>" suffixes from extracted JSDoc descriptions
  descriptionReplacements: [{ pattern: '\\n\\nDocumentation:.*$', replacement: '', flags: 'm' }],
})(withMDX(nextConfig));

Default Configurations

Page Extensions

By default, withDocsInfra enables these page extensions:

  • js, jsx - JavaScript files
  • md, mdx - Markdown files
  • ts, tsx - TypeScript files

Demo File Patterns

The plugin automatically configures loaders for these patterns:

Turbopack Rules:

{
  './app/**/demos/*/index.ts': {
    loaders: ['@mui/internal-docs-infra/pipeline/loadPrecomputedCodeHighlighter']
  },
  './app/**/demos/*/client.ts': {
    loaders: ['@mui/internal-docs-infra/pipeline/loadPrecomputedCodeHighlighterClient']
  }
}

Webpack Rules:

{
  test: /[/\\]demos[/\\][^/\\]+[/\\]index\.ts$/,
  use: [
    defaultLoaders.babel,
    '@mui/internal-docs-infra/pipeline/loadPrecomputedCodeHighlighter'
  ]
}

MDX Integration

Use getDocsInfraMdxOptions to configure MDX with docs-infra plugins:

import { withDocsInfra, getDocsInfraMdxOptions } from '@mui/internal-docs-infra/withDocsInfra';
import createMDX from '@next/mdx';

// Default docs-infra MDX plugins with automatic index generation
const withMDX = createMDX({
  options: getDocsInfraMdxOptions(),
});

const nextConfig = {
  // Your Next.js config
};

export default withDocsInfra()(withMDX(nextConfig));

// With additional plugins
const withMDX = createMDX({
  options: getDocsInfraMdxOptions({
    additionalRemarkPlugins: [['remark-emoji']],
    additionalRehypePlugins: [['rehype-highlight']],
  }),
});

// Custom plugin overrides (replaces all default plugins)
const withMDX = createMDX({
  options: getDocsInfraMdxOptions({
    remarkPlugins: [['remark-gfm'], ['custom-plugin']],
    rehypePlugins: [['custom-rehype-plugin']],
  }),
});

Controlling Index Generation

The extractToIndex option is passed via getDocsInfraMdxOptions, not withDocsInfra:

// Disable index generation
const withMDX = createMDX({
  options: getDocsInfraMdxOptions({
    extractToIndex: false,
  }),
});

export default withDocsInfra()(withMDX(nextConfig));

// Custom path filters for index generation
const withMDX = createMDX({
  options: getDocsInfraMdxOptions({
    extractToIndex: {
      include: ['app/docs', 'app/api'],
      exclude: ['app/docs/internal'],
    },
  }),
});

export default withDocsInfra()(withMDX(nextConfig));

Default MDX Plugins

Remark Plugins (Markdown processing)

Rehype Plugins (HTML processing)

Example: Custom Demo Structure

If your demos follow a different pattern (e.g., demo-variant/index.ts):

const nextConfig = withDocsInfra({
  additionalDemoPatterns: {
    index: ['./app/**/demos/*/demo-*/index.ts'],
    client: ['./app/**/demos/*/demo-*/client.ts'],
  },
})({});

This will configure loaders for paths like:

  • ./app/components/demos/Button/demo-variant/index.ts
  • ./app/components/demos/Button/demo-basic/client.ts

How It Works

  1. Page Extensions: Configures Next.js to recognize additional file types as pages
  2. Export Output: Enables static export mode for documentation sites
  3. Turbopack Rules: Sets up fast refresh and bundling for demo files in development
  4. Webpack Rules: Configures production bundling with appropriate loaders
  5. Pattern Conversion: Converts glob patterns to webpack regex for file matching

Integration Example

Complete Next.js configuration for a docs site:

// next.config.mjs
import { withDocsInfra, getDocsInfraMdxOptions } from '@mui/internal-docs-infra/withDocsInfra';
import createMDX from '@next/mdx';

const withMDX = createMDX({
  options: getDocsInfraMdxOptions({
    additionalRemarkPlugins: [['remark-emoji']],
  }),
});

const nextConfig = {
  // Your app-specific config
  experimental: {
    appDir: true,
  },
};

export default withDocsInfra({
  additionalDemoPatterns: {
    index: ['./app/**/demos/*/demo-*/index.ts'],
    client: ['./app/**/demos/*/demo-*/client.ts'],
  },
})(withMDX(nextConfig));

Automatic Index Generation

By default, the plugin automatically extracts page metadata and maintains parent directory indexes. See examples in Controlling Index Generation above.

The default filter { include: ['app', 'src/app'], exclude: [] } processes all pages in both app/ and src/app/ directories (without trailing slashes - they're added automatically during matching). Index files (e.g., app/page.mdx, app/components/page.mdx) are automatically excluded to prevent them from creating parent indexes. The base directory is automatically detected from process.cwd().

For complete details, see the transformMarkdownMetadata documentation.

When to Use

  • Required for any Next.js app using MUI docs-infra components
  • When building documentation sites with live demos
  • When you need automatic code highlighting for demo files
  • When using MDX with docs-infra markdown transformations

Types

withDocsInfra

Next.js plugin for MUI docs infrastructure. Configures webpack loaders, turbopack rules for docs sites. Use getDocsInfraMdxOptions() with createMDX for MDX integration.

PropertyTypeDescription
additionalPageExtensions
string[] | undefined

Additional page extensions to support beyond the default docs-infra extensions. Default docs-infra extensions are: [‘js’, ‘jsx’, ‘md’, ‘mdx’, ‘ts’, ‘tsx’]

enableExportOutput
boolean | undefined

Whether to enable the export output mode.

demoPathPattern
string | undefined

Custom demo path pattern for loader rules.

clientDemoPathPattern
string | undefined

Custom client demo path pattern for loader rules.

additionalDemoPatterns
| { index?: string[]; client?: string[] }
| undefined

Additional demo loader patterns for both Turbopack and Webpack. Each pattern will use the appropriate code highlighter loaders.

additionalTurbopackRules
Record<string, { loaders: string[] }> | undefined

Additional Turbopack rules to merge with the default docs-infra rules.

performance
| {
    logging: boolean;
    notableMs?: number;
    showWrapperMeasures?: boolean;
  }
| undefined

Performance logging options

deferCodeParsing
'gzip' | 'json' | 'none' | undefined

Defer AST parsing option for code highlighter output. ‘gzip’ — Default, outputs gzipped HAST for best performance. ‘json’ — Outputs JSON HAST, requires client-side parsing. ‘none’ — Outputs raw HAST, requires client-side parsing and is largest size.

removeCommentsWithPrefix
string[] | undefined

Prefixes for comments that should be stripped from the source output. Comments starting with these prefixes will be removed from the returned source. They can still be collected via notableCommentsPrefix.

notableCommentsPrefix
string[] | undefined

Prefixes for notable comments that should be collected and included in the result. Comments starting with these prefixes will be returned in the comments field, which can be used by sourceEnhancers to modify the highlighted output.

typesIndexFileName
string | undefined

Name of the index file to update when syncing types metadata to parent indexes. The types loader will call syncPageIndex to update the parent directory’s index with props, dataAttributes, and cssVariables extracted from component types.

errorIfTypesIndexOutOfDate
boolean | undefined

Throw an error if any types index is out of date or missing. Useful for CI environments to ensure indexes are committed.

ordering
OrderingConfig | undefined

Custom ordering configuration for sorting props, data attributes, component exports, namespace parts, and type suffixes in generated documentation.

Each array defines the order in which items should appear. Items not in the array are placed at the position of the __EVERYTHING_ELSE__ marker, sorted alphabetically.

All fields are optional — unspecified fields use the built-in defaults.

descriptionReplacements
DescriptionReplacement[] | undefined

Pattern/replacement pairs to apply to JSDoc descriptions during type extraction. Each entry has a pattern (regex string) and replacement string.

Return Type
((nextConfig?: NextConfig) => NextConfig)

getDocsInfraMdxOptions

Get default MDX options for docs-infra

PropertyTypeDescription
remarkPlugins
(string | [string, any])[] | undefined
rehypePlugins
(string | [string, any])[] | undefined
additionalRemarkPlugins
(string | [string, any])[] | undefined

Additional remark plugins to add to the default docs-infra plugins

additionalRehypePlugins
(string | [string, any])[] | undefined

Additional rehype plugins to add to the default docs-infra plugins

extractToIndex
| boolean
| { include: string[]; exclude: string[] }
| undefined

Whether to automatically extract page metadata (title, description, headings) from MDX files and maintain an index in the parent directory’s page.mdx file.

Index files themselves (e.g., pattern/page.mdx) are automatically excluded from extraction.

Can be:

  • false — Disabled
  • true — Enabled with default filter: { include: ['app', 'src/app'], exclude: [] }
  • { include: string[], exclude: string[] } — Enabled with custom path filters
baseDir
string | undefined

Base directory for path filtering. Defaults to process.cwd(). Only needed when calling the plugin directly (not via withDocsInfra).

errorIfIndexOutOfDate
boolean | undefined

Throw an error if any index is out of date or missing. Useful for CI environments to ensure indexes are committed.

defaultInlineCodeLanguage
string | false | undefined

Default language for inline code syntax highlighting. Set to false to disable default highlighting for inline code.

Return Type
DocsInfraMdxOptions
KeyTypeDescription
remarkPlugins
(string | [string, any])[] | undefined
rehypePlugins
(string | [string, any])[] | undefined
additionalRemarkPlugins
(string | [string, any])[] | undefined

Additional remark plugins to add to the default docs-infra plugins

additionalRehypePlugins
(string | [string, any])[] | undefined

Additional rehype plugins to add to the default docs-infra plugins

extractToIndex
| boolean
| { include: string[]; exclude: string[] }
| undefined

Whether to automatically extract page metadata (title, description, headings) from MDX files and maintain an index in the parent directory’s page.mdx file.

Index files themselves (e.g., pattern/page.mdx) are automatically excluded from extraction.

Can be:

  • false — Disabled
  • true — Enabled with default filter: { include: ['app', 'src/app'], exclude: [] }
  • { include: string[], exclude: string[] } — Enabled with custom path filters
baseDir
string | undefined

Base directory for path filtering. Defaults to process.cwd(). Only needed when calling the plugin directly (not via withDocsInfra).

errorIfIndexOutOfDate
boolean | undefined

Throw an error if any index is out of date or missing. Useful for CI environments to ensure indexes are committed.

defaultInlineCodeLanguage
string | false | undefined

Default language for inline code syntax highlighting. Set to false to disable default highlighting for inline code.

withDeploymentConfig

ParameterTypeDescription
nextConfig
NextConfig
Return Type
NextConfig

Additional Types

DocsInfraMdxOptions
type DocsInfraMdxOptions = {
  remarkPlugins?: (string | [string, any])[];
  rehypePlugins?: (string | [string, any])[];
  /** Additional remark plugins to add to the default docs-infra plugins */
  additionalRemarkPlugins?: (string | [string, any])[];
  /** Additional rehype plugins to add to the default docs-infra plugins */
  additionalRehypePlugins?: (string | [string, any])[];
  /**
   * Whether to automatically extract page metadata (title, description, headings) from MDX files
   * and maintain an index in the parent directory's page.mdx file.
   *
   * Index files themselves (e.g., pattern/page.mdx) are automatically excluded from extraction.
   *
   * Can be:
   * - `false` - Disabled
   * - `true` - Enabled with default filter: `{ include: ['app', 'src/app'], exclude: [] }`
   * - `{ include: string[], exclude: string[] }` - Enabled with custom path filters
   * @default true
   */
  extractToIndex?: boolean | { include: string[]; exclude: string[] };
  /**
   * Base directory for path filtering. Defaults to process.cwd().
   * Only needed when calling the plugin directly (not via withDocsInfra).
   */
  baseDir?: string;
  /**
   * Throw an error if any index is out of date or missing.
   * Useful for CI environments to ensure indexes are committed.
   * @default false
   */
  errorIfIndexOutOfDate?: boolean;
  /**
   * Default language for inline code syntax highlighting.
   * Set to `false` to disable default highlighting for inline code.
   * @default 'tsx'
   */
  defaultInlineCodeLanguage?: string | false;
}
WebpackOptions
type WebpackOptions = {
  buildId: string;
  dev: boolean;
  isServer: boolean;
  nextRuntime?: 'nodejs' | 'edge';
  config: NextConfig;
  defaultLoaders: { babel: RuleSetRule };
}
WithDocsInfraOptions
type WithDocsInfraOptions = {
  /**
   * Additional page extensions to support beyond the default docs-infra extensions.
   * Default docs-infra extensions are: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx']
   */
  additionalPageExtensions?: string[];
  /**
   * Whether to enable the export output mode.
   * @default true
   */
  enableExportOutput?: boolean;
  /**
   * Custom demo path pattern for loader rules.
   * @default './app/ ** /demos/ * /index.ts'
   */
  demoPathPattern?: string;
  /**
   * Custom client demo path pattern for loader rules.
   * @default './app/ ** /demos/ * /client.ts'
   */
  clientDemoPathPattern?: string;
  /**
   * Additional demo loader patterns for both Turbopack and Webpack.
   * Each pattern will use the appropriate code highlighter loaders.
   */
  additionalDemoPatterns?: { index?: string[]; client?: string[] };
  /** Additional Turbopack rules to merge with the default docs-infra rules. */
  additionalTurbopackRules?: Record<string, { loaders: string[] }>;
  /** Performance logging options */
  performance?: { logging: boolean; notableMs?: number; showWrapperMeasures?: boolean };
  /**
   * Defer AST parsing option for code highlighter output.
   * 'gzip' - Default, outputs gzipped HAST for best performance.
   * 'json' - Outputs JSON HAST, requires client-side parsing.
   * 'none' - Outputs raw HAST, requires client-side parsing and is largest size.
   * @default 'gzip'
   */
  deferCodeParsing?: 'gzip' | 'json' | 'none';
  /**
   * Prefixes for comments that should be stripped from the source output.
   * Comments starting with these prefixes will be removed from the returned source.
   * They can still be collected via `notableCommentsPrefix`.
   * @example ['@highlight', '@internal']
   */
  removeCommentsWithPrefix?: string[];
  /**
   * Prefixes for notable comments that should be collected and included in the result.
   * Comments starting with these prefixes will be returned in the `comments` field,
   * which can be used by sourceEnhancers to modify the highlighted output.
   * @example ['@highlight', '@focus']
   */
  notableCommentsPrefix?: string[];
  /**
   * Name of the index file to update when syncing types metadata to parent indexes.
   * The types loader will call syncPageIndex to update the parent directory's index
   * with props, dataAttributes, and cssVariables extracted from component types.
   * @default 'page.mdx'
   */
  typesIndexFileName?: string;
  /**
   * Throw an error if any types index is out of date or missing.
   * Useful for CI environments to ensure indexes are committed.
   * @default Boolean(process.env.CI)
   */
  errorIfTypesIndexOutOfDate?: boolean;
  /**
   * Custom ordering configuration for sorting props, data attributes, component exports,
   * namespace parts, and type suffixes in generated documentation.
   *
   * Each array defines the order in which items should appear. Items not in the array
   * are placed at the position of the `__EVERYTHING_ELSE__` marker, sorted alphabetically.
   *
   * All fields are optional — unspecified fields use the built-in defaults.
   */
  ordering?: OrderingConfig;
  /**
   * Pattern/replacement pairs to apply to JSDoc descriptions during type extraction.
   * Each entry has a `pattern` (regex string) and `replacement` string.
   * @example
   * ```js
   * [
   *   { pattern: '\\n\\nDocumentation: .*$', replacement: '', flags: 'm' },
   * ]
   * ```
   */
  descriptionReplacements?: DescriptionReplacement[];
}