Build a documentation site with Next.js and MDX
01/13/2025
What is MDX?
How does MDX work with Next.js?
Next.js provides a detail documentation about how to use MDX in MDX with Next.js.
There are 3 ways to use MDX in Next.js:
- Static page or app routing like page.tsx
- Dynamic page like [slug].tsx
- Remote MDX like MDXRemote
Next.js -> webpack -> loader -> mdx -> react components
remark plugins and rehype plugins
- remark: parse markdown to mdx
- rehype: convert mast to hast and then to html
MDX compiled to React components and rendered on the page.
service side rendering rsc
client side rendering
How to use MDX in Next.js
Static page or app routing like page.tsx
This is the simplest way to use MDX in Next.js.
- Create a new page in the app directory
app/docs/static-mdx-page/page.mdx - Add the MDX content to the page. You can write it as plain markdown or even use React components. This is just like how you write a tsx file, but with markdown and component code.
- The page will be rendered on the server side and the MDX content will be compiled to React components, and the page will be served as an HTML file.
You can access the page at
http://localhost:3000/docs/static-mdx-page, just like any other tsx page in Next.js.
Here the basic setting is to config 'mdx' support in snext.config.ts
// next.config.ts
const nextConfig: NextConfig = {
pageExtensions: ["ts", "tsx", "js", "jsx", "md", "mdx"],
...
}If you want to support GitHub Flavored Markdown, you can add the following plugins in remarkPlugins and rehypePlugins in next.config.ts
// next.config.ts
import configMdx from "@next/mdx";
// import moonlightTheme from './assets/moonlight-ii.json' with { type: 'json' };
/** @type {import('next').NextConfig} */
const withMDX = configMdx({
options: {
remarkPlugins: [['remark-gfm'], ['remark-frontmatter'], ['remark-mdx-frontmatter'], ['remark-math']],
rehypePlugins: [['rehype-katex', { strict: true, throwOnError: true }],
['rehype-slug'], ['rehype-pretty-code', { keepBackground: true,}],
],
},
});More or less, based on your requirement, you can add more plugins in remarkPlugins and rehypePlugins.
In your mdx file, you may need to use some components, you can define them in mdx-components.tsx and import them in your mdx file.
// mdx-components.tsx
import { MDXComponents } from 'mdx/types';
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
...components,
}
}Dynamic page like [slug].tsx
Remote MDX like MDXRemote
Styling with tailwind and @tailwind/typography
Math
Mdx use remark-math to convert markdown math to katex. And use rehype-katex to convert katex to html. Or optionally you can use rehype-mathjax to convert math to mathjax. See Mdx Math Support
- For Next.js with MDX support, configure the plugins in
next.config.ts - For Katex,
cssneeds to be imported inlayout.tsxormdx-components.tsx, see**./src/app/docs/layout.tsxand./src/mdx-components.tsx.
katex
See Mdx Math Support
- Simple inline math:
- Block math:
remark-breaks
You may test remark-breaks to break the line.
// next.config.js
const withMDX = configMdx({
options: {
remarkPlugins: [['remark-breaks']],
},
});
When remark-breaks is enabled, the line break will be converted to a line break.
It will go to the next line when you press enter. This is the second line.
Table
| Header 1 | Header 2 | Header 3 |
|---|---|---|
| Cell 1 | Cell 2 | Cell 3 |
| Cell 4 | Cell 5 | Cell 6 |
| Cell 7 | Cell 8 | Cell 9 |
MDX plugins
-
remark
- remark-mdx-frontmatter
- remark-breaks
- remark-gfm
- remark-math
- remark-frontmatter
-
rehype
- rehype-katex
- rehype-slug
- rehype-pretty-code