Warning
This is an internal project, and is not intended for public use. No support or stability guarantees are provided.
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.
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 justcreateTypes. You can create custom factory functions usingabstractCreateTypeslikecreateApiReference()orcreateTypeDocs()that return documentation components.
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);
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 />;
}
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.
For debugging or development, you can skip the build-time processing:
export const TypesComponent = createTypes(import.meta.url, Component, {
skipPrecompute: true,
});
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
});
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;
},
};
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
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' },
],
},
},
],
});
| Parameter | Type | Description |
|---|---|---|
| source | |
Promise<void>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[];
}The loader follows these steps to precompute your type documentation:
Finds your createTypes function call and extracts the component references and options.
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.
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 */ },
},
});
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.
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.
loadServerTypes - Server-side function that coordinates the pipelinesyncTypes - Core type synchronization logicabstractCreateTypes - Create custom type factorieswithDocsInfra - Next.js plugin with auto-configuration