Warning
This is an internal project, and is not intended for public use. No support or stability guarantees are provided.
The createSitemap factory function defines sitemap data for documentation sites. It works with the webpack loader for build-time precomputation in Next.js builds.
Tip
Place your sitemap at
app/sitemap/index.tsfor automatic detection bywithDocsInfra.
import { createSitemap } from '@mui/internal-docs-infra/createSitemap';
import DocsInfraComponents from '../docs-infra/components/page.mdx';
import DocsInfraFunctions from '../docs-infra/functions/page.mdx';
export const sitemap = createSitemap(import.meta.url, {
DocsInfraComponents,
DocsInfraFunctions,
});
During Next.js builds, the loadPrecomputedSitemap webpack loader processes this file and precomputes the sitemap data. Outside Next.js, use loadServerSitemap for runtime loading.
For loading sitemap data outside of Next.js builds (e.g., in tests, scripts, or non-Next.js applications), use loadServerSitemap:
import { loadServerSitemap } from '@mui/internal-docs-infra/pipeline/loadServerSitemap';
// Load sitemap at runtime by parsing the sitemap index file
const sitemap = await loadServerSitemap('file:///path/to/app/sitemap/index.ts');
// sitemap.schema contains the Orama schema
// sitemap.data contains all page metadata organized by section
The sitemap index file should be placed at app/sitemap/index.ts:
app/
├── sitemap/
│ └── index.ts ← Sitemap definition
├── docs-infra/
│ ├── components/
│ │ └── page.mdx ← Section index
│ └── functions/
│ └── page.mdx ← Section index
Each imported page component should be a markdown file that serves as a section index (e.g., components/page.mdx lists all components).
Creates sitemap data from page components with optional precomputed data. Returns a sitemap data object containing schema and page data.
In Next.js builds, the webpack loader precomputes the sitemap data.
Outside Next.js (e.g., tests or scripts), use loadServerSitemap() for runtime loading.
| Parameter | Type | Description |
|---|---|---|
| sourceUrl | | Depends on |
| pages | | Record of page components indexed by path. |
| meta | | Additional meta and precomputed sitemap configuration. |
Sitemap | undefinedtype Audience = 'private' | 'introductory' | 'intermediate' | 'advanced' | 'business'Page metadata type extending Next.js Metadata.
Adds the audience field under other using the WHATWG MetaExtensions audience meta name.
All standard Next.js metadata fields (title, description, openGraph, etc.) remain available.
type NextMetadata = Metadata & { other?: { [key: string]: unknown; audience?: Audience } }Orama schema property types See: https://docs.orama.com/docs/orama-js/usage/create#schema-properties-and-types
type OramaSchemaType =
'string' | 'number' | 'boolean' | 'string[]' | 'number[]' | 'boolean[]' | `vector[${number}]`A route-group section heading in a grouped index (see SitemapSectionData.sections).
Maps a Next.js route group to the human-editable heading its pages are listed under.
type PageIndexSection = {
/** The route group this section collects (e.g. `(components)`). */
group: string;
/** The (human-editable) heading text shown for the section. */
title: string;
/** Heading depth for the section title. Defaults to 2 (`##`). */
depth?: number;
}Sitemap structure
type Sitemap = {
schema: Record<string, OramaSchemaType>;
data: Record<string, SitemapSectionData>;
}Export data structure from sitemap (for exported functions/components)
type SitemapExport = { props?: string[]; dataAttributes?: string[]; cssVariables?: string[] }Page data structure from sitemap
type SitemapPage = {
title?: string;
slug: string;
path: string;
description?: string;
keywords?: string[];
sections?: Record<string, SitemapSection>;
parts?: Record<string, SitemapPart>;
exports?: Record<string, SitemapExport>;
types?: string[];
?: string[];
skipDetailSection?: boolean;
audience?: Audience;
index?: boolean;
/**
* The title of the route-group section this page is listed under in a grouped index
* (e.g. `Components`), resolved from the page's route group. `null` for a page in a flat
* index or with no route group, so the field is always present. Useful for
* grouping/faceting search results.
*/
section: string | null;
image?: { url: string; alt?: string };
}Part data structure from sitemap (for component parts)
type SitemapPart = {
props?: string[];
dataAttributes?: string[];
cssVariables?: string[];
parameters?: (string | string[])[];
returns?: string[];
}Section data structure from sitemap
type SitemapSection = { title: string; children?: Record<string, SitemapSection> }Section data from sitemap
type SitemapSectionData = {
title: string;
prefix: string;
pages: SitemapPage[];
/**
* Ordered route-group sections when the index is grouped (its `##` subtitles), so
* search can recover the sections a page belongs to. An empty array for a flat index,
* so the field is always present.
*/
sections: PageIndexSection[];
/** Heading of the detail-region wrapper in a grouped index (defaults to `Details`). */
detailsSectionTitle?: string;
}Disable precomputation for development or testing:
export const sitemap = createSitemap(
import.meta.url,
{ DocsInfraComponents, DocsInfraFunctions },
{ skipPrecompute: true },
);
The webpack loader must be configured for the sitemap index file. See withDocsInfra or loadPrecomputedSitemap for configuration details.
The sitemap data is designed for use with Orama search. For a ready-made React hook that handles index creation, querying, and result formatting, see useSearch.
Here's a lower-level example using Orama directly:
import { create, insertMultiple, search } from '@orama/orama';
import { loadServerSitemap } from '@mui/internal-docs-infra/pipeline/loadServerSitemap';
// Load the sitemap at runtime
const sitemap = await loadServerSitemap('file:///path/to/app/sitemap/index.ts');
// Create search index with the schema
const searchIndex = await create({
schema: sitemap.schema,
});
// Flatten and insert pages
const pages = Object.entries(sitemap.data).flatMap(([_key, section]) =>
section.pages.map((page) => ({
...page,
section: section.title,
prefix: section.prefix,
})),
);
await insertMultiple(searchIndex, pages);
// Search
const results = await search(searchIndex, { term: 'button' });
The sitemap's page data (titles, descriptions, sections, keywords) comes from metadata exported by each MDX page. Use the transformMarkdownMetadata remark plugin to automatically extract this metadata:
// Each MDX page exports metadata like:
export const metadata = {
title: 'Button',
description: 'A clickable button component.',
keywords: ['button', 'click', 'action'],
};
The plugin extracts:
syncPageIndex title overrides)See transformMarkdownMetadata for configuration options and automatic index generation.
Additional sitemap metadata is managed through the index files maintained by syncPageIndex. For example, in your index page.mdx:
- Button [New] - ([Outline](#button), [Contents](./button/page.mdx))
- Input - ([Outline](#text-field), [Contents](./text-field/page.mdx))
This shows:
[New] is a lifecycle label that appears in the sitemap as page.tags. See syncPageIndex tags.syncPageIndex title overrides.syncPageIndex preserves manual ordering during updates.syncPageIndex - Maintain index pages with tags, title overrides, and orderingtransformMarkdownMetadata - Extract metadata from MDX pagesloadPrecomputedSitemap - Webpack loader for build-time processingloadServerSitemap - Runtime sitemap loadingloadServerPageIndex - Loads individual page metadatawithDocsInfra - Next.js plugin that configures the loader