Warning
This is an internal project, and is not intended for public use. No support or stability guarantees are provided.
A step-by-step guide to setting up a new Next.js project with the Docs Infra package, covering installation, configuration, and best practices for leveraging its features in your documentation site.
You should run this command at the root of your source code repository:
pnpm create next-app@latest docs
We recommend against using the src/ prefix.
We also depend on the @next/mdx package for MDX support, which is a peer dependency of @mui/internal-docs-infra. You can install both packages with the following command:
pnpm install --filter docs @mui/internal-docs-infra@canary @next/mdx
In the root package.json, add the following scripts:
{
"scripts": {
"docs:dev": "pnpm --filter docs dev",
"docs:build": "pnpm --filter docs build",
"docs:start": "pnpm --filter docs start",
"docs:validate": "pnpm --filter docs validate --command 'pnpm docs:validate'",
"docs:infra": "pnpm --filter docs docs-infra"
}
}
In the package.json of the docs package, add the following scripts:
{
"scripts": {
"docs-infra": "docs-infra",
"validate": "pnpm docs-infra validate --command 'pnpm validate'"
}
}
In the next.config.ts file of the docs package, add the following configuration:
import type { NextConfig } from 'next';
import { withDocsInfra, getDocsInfraMdxOptions } from '@mui/internal-docs-infra/withDocsInfra';
import createMDX from '@next/mdx';
const nextConfig: NextConfig = {
/* config options here */
};
const withMDX = createMDX({
options: getDocsInfraMdxOptions(),
});
export default withDocsInfra()(withMDX(nextConfig));
See Next.js plugin documentation for more details on configuration options and advanced usage.
We need to add a theme for syntax highlighting. Create a new file docs/app/syntax.css with the following content:
/* Syntax highlighting theme using prettylights with global color variables.
* Based on prettylights classes with extensions for Docs Infra. */
:root {
/* Prettylights syntax colors mapped to global theme */
--color-prettylights-syntax-comment: var(--color-gray);
--color-prettylights-syntax-constant: var(--color-blue);
--color-prettylights-syntax-constant-other-reference-link: var(--color-navy);
--color-prettylights-syntax-entity: var(--color-violet);
--color-prettylights-syntax-entity-tag: var(--color-green);
--color-prettylights-syntax-keyword: var(--color-red);
--color-prettylights-syntax-string: var(--color-navy);
--color-prettylights-syntax-string-regexp: var(--color-green);
--color-prettylights-syntax-variable: var(--color-red);
--color-prettylights-syntax-storage-modifier-import: var(--color-navy);
--color-prettylights-syntax-brackethighlighter-angle: var(--color-gray);
--color-prettylights-syntax-brackethighlighter-unmatched: var(--color-red);
--color-prettylights-syntax-sublimelinter-gutter-mark: var(--color-gray);
/* Invalid/error states */
--color-prettylights-syntax-invalid-illegal-bg: var(--color-red);
--color-prettylights-syntax-invalid-illegal-text: var(--color-content);
--color-prettylights-syntax-carriage-return-bg: var(--color-red);
--color-prettylights-syntax-carriage-return-text: var(--color-content);
/* Markup/markdown (unused in code demos but included for completeness) */
--color-prettylights-syntax-markup-heading: var(--color-blue);
--color-prettylights-syntax-markup-bold: var(--color-foreground);
--color-prettylights-syntax-markup-italic: var(--color-foreground);
--color-prettylights-syntax-markup-list: var(--color-red);
--color-prettylights-syntax-markup-changed-bg: transparent;
--color-prettylights-syntax-markup-changed-text: var(--color-red);
--color-prettylights-syntax-markup-deleted-bg: transparent;
--color-prettylights-syntax-markup-deleted-text: var(--color-red);
--color-prettylights-syntax-markup-inserted-bg: transparent;
--color-prettylights-syntax-markup-inserted-text: var(--color-green);
--color-prettylights-syntax-markup-ignored-bg: transparent;
--color-prettylights-syntax-markup-ignored-text: var(--color-gray);
--color-prettylights-syntax-meta-diff-range: var(--color-violet);
/* Docs-infra extensions for concepts not in prettylights */
--color-docs-infra-syntax-nullish: var(--color-gray-500);
--color-docs-infra-syntax-other: var(--color-foreground);
--color-docs-infra-syntax-bracket-tag: var(--color-gray);
--color-docs-infra-syntax-bracket-curly: var(--color-gray);
--color-docs-infra-syntax-bracket-round: var(--color-gray);
--color-docs-infra-syntax-bracket-square: var(--color-gray);
--color-docs-infra-syntax-bracket-angle: var(--color-gray);
--color-docs-infra-syntax-bracket-quote: var(--color-gray);
}
.pl-c {
color: var(--color-prettylights-syntax-comment);
}
.pl-c1,
.pl-s .pl-v {
color: var(--color-prettylights-syntax-constant);
}
.pl-e,
.pl-en {
color: var(--color-prettylights-syntax-entity);
}
.pl-smi,
.pl-s .pl-s1 {
color: var(--color-prettylights-syntax-storage-modifier-import);
}
.pl-ent {
color: var(--color-prettylights-syntax-entity-tag);
}
.pl-k {
color: var(--color-prettylights-syntax-keyword);
}
.pl-s,
.pl-pds,
.pl-s .pl-pse .pl-s1,
.pl-sr,
.pl-sr .pl-cce,
.pl-sr .pl-sre,
.pl-sr .pl-sra {
color: var(--color-prettylights-syntax-string);
}
.pl-v,
.pl-smw {
color: var(--color-prettylights-syntax-variable);
}
.pl-bu {
color: var(--color-prettylights-syntax-brackethighlighter-unmatched);
}
.pl-ii {
color: var(--color-prettylights-syntax-invalid-illegal-text);
background-color: var(--color-prettylights-syntax-invalid-illegal-bg);
}
.pl-c2 {
color: var(--color-prettylights-syntax-carriage-return-text);
background-color: var(--color-prettylights-syntax-carriage-return-bg);
}
.pl-sr .pl-cce {
font-weight: bold;
color: var(--color-prettylights-syntax-string-regexp);
}
.pl-ml {
color: var(--color-prettylights-syntax-markup-list);
}
.pl-mh,
.pl-mh .pl-en,
.pl-ms {
font-weight: bold;
color: var(--color-prettylights-syntax-markup-heading);}
.pl-mi {
font-style: italic;
color: var(--color-prettylights-syntax-markup-italic);
}
.pl-mb {
font-weight: bold;
color: var(--color-prettylights-syntax-markup-bold);
}
.pl-md {
color: var(--color-prettylights-syntax-markup-deleted-text);
background-color: var(--color-prettylights-syntax-markup-deleted-bg);
}
.pl-mi1 {
color: var(--color-prettylights-syntax-markup-inserted-text);
background-color: var(--color-prettylights-syntax-markup-inserted-bg);
}
.pl-mc {
color: var(--color-prettylights-syntax-markup-changed-text);
background-color: var(--color-prettylights-syntax-markup-changed-bg);
}
.pl-mi2 {
color: var(--color-prettylights-syntax-markup-ignored-text);
background-color: var(--color-prettylights-syntax-markup-ignored-bg);
}
.pl-mdr {
font-weight: bold;
color: var(--color-prettylights-syntax-meta-diff-range);
}
.pl-ba {
color: var(--color-prettylights-syntax-brackethighlighter-angle);
}
.pl-sg {
color: var(--color-prettylights-syntax-sublimelinter-gutter-mark);
}
.pl-corl {
text-decoration: underline;
color: var(--color-prettylights-syntax-constant-other-reference-link);
}
/* Docs-infra extensions (.di-* classes) */
/* Nullish values (null, undefined) */
.di-n {
color: var(--color-docs-infra-syntax-nullish);
}
/* Default text color */
.di-d {
color: var(--color-foreground);
}
/* Parameter highlighting */
.di-p {
color: var(--color-prettylights-syntax-storage-modifier-import);
}
/* Misc/other markup styling */
.di-o {
color: var(--color-docs-infra-syntax-other);
}
/* Bracket types */
.di-bt {
color: var(--color-docs-infra-syntax-bracket-tag);
}
.di-bc {
color: var(--color-docs-infra-syntax-bracket-curly);
}
.di-br {
color: var(--color-docs-infra-syntax-bracket-round);
}
.di-bs {
color: var(--color-docs-infra-syntax-bracket-square);
}
.di-ba {
color: var(--color-docs-infra-syntax-bracket-angle);
}
.di-bq {
color: var(--color-docs-infra-syntax-bracket-quote);
}
/* Diff additions */
.di-ins {
color: var(--color-prettylights-syntax-markup-inserted-text);
background-color: var(--color-prettylights-syntax-markup-inserted-bg);
}
/* Diff deletions */
.di-del {
color: var(--color-prettylights-syntax-markup-deleted-text);
background-color: var(--color-prettylights-syntax-markup-deleted-bg);
}
/* Diff changes */
.di-chg {
color: var(--color-prettylights-syntax-markup-changed-text);
background-color: var(--color-prettylights-syntax-markup-changed-bg);
}
/* Diff ignored/untracked */
.di-ign {
color: var(--color-prettylights-syntax-markup-ignored-text);
background-color: var(--color-prettylights-syntax-markup-ignored-bg);
}
/* Diff range indicator */
.di-rng {
font-weight: bold;
color: var(--color-prettylights-syntax-meta-diff-range);
}
/* Line highlighting */
pre [data-hl] {
background-color: var(--color-line-highlight);
}
pre [data-hl='strong'] {
background-color: var(--color-line-highlight-strong);
}
/* Character/word highlighting */
pre [data-hlc] {
color: var(--color-blue);
background-color: var(--color-inline-highlight);
}Add the syntax highlighting CSS file to your layout:
import type { Metadata } from 'next';
import { Geist, Geist_Mono } from 'next/font/google';
import './globals.css';
import './syntax.css';
const geistSans = Geist({
variable: '--font-geist-sans',
subsets: ['latin'],
});
const geistMono = Geist_Mono({
variable: '--font-geist-mono',
subsets: ['latin'],
});
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable}`}>{children}</body>
</html>
);
}