MUI Docs Infra

Warning

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

Load Precomputed Types

The precomputed types loader is a Webpack/Turbopack loader that automatically generates comprehensive type documentation for your TypeScript components at build time. Write your components in TypeScript, and the loader extracts props, methods, and type signatures—ready to display in your documentation.

Tip

For the high-level rationale behind this pattern see the Built Factories Pattern.

Overview

The loader processes types.ts files that use the createTypes factory pattern, analyzing your TypeScript components and extracting detailed metadata about their APIs. It delegates the actual type processing to loadServerTypes (with sync: true), then injects the precomputed results back into your source code.

Note

The loader works with any create* function that follows the types factory pattern, not just createTypes. You can create custom factory functions using abstractCreateTypes like createApiReference() or createTypeDocs() that return documentation components.

Key Features

  • Webpack/Turbopack integration: Works as a standard loader in your build pipeline
  • Automatic precomputation: Type analysis happens during compilation for zero runtime overhead
  • Dependency tracking: Tracks all source files and updates when types change
  • Performance logging: Optional detailed timing measurements for debugging
  • Configurable formatting: Control how union types and default values are displayed

Usage

Basic Types File

Create a types.ts file with the factory pattern using a descriptive named export:

import { createTypes } from '../createTypes';
import Component from './Component';

export const TypesComponent = createTypes(import.meta.url, Component);

Using Types in Pages

Your page.tsx or page.mdx files can then import and render the component returned by createTypes:

// page.tsx
import { TypesComponent } from './types';

export default function ComponentPage() {
  return <TypesComponent />;
}

Multiple Components

When a component has multiple parts (like Checkbox.Root and Checkbox.Indicator), use createMultipleTypes and export the types object directly:

// types.ts
import { createMultipleTypes } from '../createTypes';
import { Checkbox } from '@base-ui/react/checkbox';

const { types, AdditionalTypes } = createMultipleTypes(import.meta.url, Checkbox);

export const TypesCheckbox = types;
export const TypesCheckboxAdditional = AdditionalTypes;

See abstractCreateTypes for the recommended usage patterns, including dot notation in MDX and handling additional types.

Skipping Precomputation

For debugging or development, you can skip the build-time processing:

export const TypesComponent = createTypes(import.meta.url, Component, {
  skipPrecompute: true,
});

Configuration

The easiest way to configure this loader is with the withDocsInfra Next.js plugin:

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

export default withDocsInfra({
  // Automatically includes types.ts loader pattern
});

Manual Next.js Setup

If you need manual control, add the loader directly to your next.config.mjs:

Note

The Turbopack loader requires Next.js version v15.5 or later (depends on this fix)

/** @type {import('next').NextConfig} */
const nextConfig = {
  turbopack: {
    rules: {
      './app/**/types.ts': {
        loaders: ['@mui/internal-docs-infra/pipeline/loadPrecomputedTypes'],
      },
    },
  },
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    config.module.rules.push({
      test: /[/\\\\]app[/\\\\].*[/\\\\]types\.ts$/,
      use: [defaultLoaders.babel, '@mui/internal-docs-infra/pipeline/loadPrecomputedTypes'],
    });

    return config;
  },
};

File Structure

The loader processes types.ts files that contain createTypes factory functions:

app/
├── components/
│   ├── button/
│   │   ├── types.ts          # ← createTypes() processed here
│   │   ├── page.tsx          # ← Next.js page that uses the types
│   │   ├── Button.tsx
│   │   └── demos/
│   │       └── basic/
│   │           └── index.ts
│   └── input/
│       ├── types.ts          # ← And here
│       ├── page.mdx          # ← Or MDX page that uses the types
│       ├── Input.tsx
│       ├── InputLabel.tsx
│       └── demos/
│           └── advanced/
│               └── index.ts

Options Reference

Loader Options

Configure the webpack/Turbopack loader with these options. See the Types for the full LoaderOptions definition.

Example configuration:

// next.config.mjs
config.module.rules.push({
  test: /[/\\\\]app[/\\\\].*[/\\\\]types\.ts$/,
  use: [
    defaultLoaders.babel,
    {
      loader: '@mui/internal-docs-infra/pipeline/loadPrecomputedTypes',
      options: {
        performance: { logging: true, notableMs: 100 },
        formatting: { shortTypeUnionPrintWidth: 50, defaultValueUnionPrintWidth: 40 },
        socketDir: '.next/docs-infra',
        // Strip "Documentation: <url>" suffixes from descriptions
        descriptionReplacements: [
          { pattern: '\\n\\nDocumentation:.*$', replacement: '', flags: 'm' },
        ],
      },
    },
  ],
});

Types

ParameterTypeDescription
source
string
Return Type
Promise<void>
LoaderOptions
type LoaderOptions = {
  /** Performance tracking and logging options */
  performance?: {
    logging?: boolean;
    notableMs?: number;
    showWrapperMeasures?: boolean;
    significantDependencyCountThreshold?: number;
  };
  /** Options for formatting types in tables */
  formatting?: FormatInlineTypeOptions;
  /**
   * Directory path for socket and lock files used for IPC between workers.
   * Useful for Windows where the default temp directory may not support Unix domain sockets.
   * @example '.next/docs-infra'
   */
  socketDir?: string;
  /**
   * Options for updating the parent index page with component metadata.
   * When provided, will call syncPageIndex to update the parent directory's page.mdx
   * with props, dataAttributes, and cssVariables extracted from the component types.
   */
  updateParentIndex?: {
    baseDir?: string;
    onlyUpdateIndexes?: boolean;
    markerDir?: string;
    errorIfOutOfDate?: boolean;
    indexFileName?: string;
  };
  /**
   * Optional regex pattern to filter which external types to include.
   * External types are named union types (like `Orientation = 'horizontal' | 'vertical'`)
   * that are referenced in props but not exported from the component's module.
   *
   * When not provided, ALL qualifying named union types (unions of literals) will be
   * collected automatically. This is the recommended behavior.
   *
   * When provided, only external types whose names match this pattern will be collected.
   * @example '^(Orientation|Side|Align)$'
   */
  externalTypesPattern?: string;
  /** Custom ordering configuration for sorting props, data attributes, exports, etc. */
  ordering?: OrderingConfig;
  /**
   * Pattern/replacement pairs to apply to JSDoc descriptions.
   * Each entry has a `pattern` (regex string) and `replacement` string.
   */
  descriptionReplacements?: DescriptionReplacement[];
}

Processing Pipeline

The loader follows these steps to precompute your type documentation:

1. Parse Factory Call

Finds your createTypes function call and extracts the component references and options.

2. Delegate to loadServerTypes

Calls loadServerTypes with sync: true, which coordinates the full pipeline: extracting types from TypeScript source, writing types.md, and converting type data to syntax-highlighted HAST. See loadServerTypes for details on what happens in this step.

3. Insert Precompute Value

Injects the precompute object into your source code with the processed type data.

// Your source before processing
export const TypesButton = createTypes(import.meta.url, Button);

// After processing (simplified)
export const TypesButton = createTypes(import.meta.url, Button, {
  precompute: {
    exports: {
      Button: {
        type: /* HighlightedTypesMeta with HAST fields */,
        additionalTypes: [/* related types like .Props, .State */],
      },
    },
    additionalTypes: [/* top-level non-namespaced types */],
    variantOnlyAdditionalTypes: { /* variant name → types for types-only modules */ },
    variantTypeNames: { /* variant to type names mapping */ },
    singleComponentName: 'Button',
    anchorMap: { 'Button': '#button', /* type name to anchor href */ },
  },
});

4. Rewrite Component Imports

Rewrites the component import(s) to null modules to prevent loading React component code on the server. The precomputed data replaces the need for the actual component reference.

5. Track Dependencies

Adds all discovered TypeScript source files to webpack's watch list for hot reloading.

Deep dive: To understand the full type extraction and highlighting pipeline that runs during step 2, see loadServerTypes.