Last modified: July 26, 2025
·
4 min read

How to Add Table of Contents to MD/MDX Files in Next.js with rehype-toc

Adding a table of contents (TOC) to your MDX files in Next.js can significantly improve the user experience, especially for long-form content. In this guide, we'll explore a simple and maintainable approach, by using rehype-toc and rehype-slug libraries.

Why Add a Table of Contents?

Before diving into implementation, let's understand why TOC is valuable:

  • Improved Navigation: Users can quickly jump to specific sections
  • Content Overview: Provides a bird's-eye view of the article structure
  • Better SEO: Search engines can better understand your content hierarchy
  • Accessibility: Screen readers can navigate content more effectively

How to Add a Table of Contents

There are many ways of achieving this, and you can also create a custom TOC component. However, in this guide, we'll focus on using rehype plugins to automatically generate heading IDs and extract TOC data during the build process. This solution is easy to integrate with your existing MDX setup and doesn't require complex logic. Let's go through the following steps:

1. Install Required Dependencies

Let's install rehype-toc to generate table of contents, and rehype-slug to automatically generate heading IDs.

npm install rehype-toc rehype-slug

2. Update Next.js Configuration

// next.config.ts
import createMDX from '@next/mdx';
import rehypeSlug from 'rehype-slug';
import rehypeToc from 'rehype-toc';

const withMDX = createMDX({
  extension: /\.(md|mdx)$/,
  options: {
    remarkPlugins: [],
    rehypePlugins: [
      rehypeSlug,
      [rehypeToc, { 
        headings: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'], //list of headings to include in the TOC
        cssClasses: {
          toc: 'toc', //custom classes for the TOC
          listItem: 'toc-item',
          list: 'toc-list',
          link: 'toc-link'
        }
      }],
    ],
  }
});

You can customize the classes to fit your design. E.g. by adding a className to cssClasses.listItem, all items in the generated TOC will have that class.

3. Add Smooth Scrolling CSS (Optional)

This step is optional, but it's a good idea to add smooth scrolling to the page so that when a user clicks on a TOC item, the page scrolls to the corresponding section smoothly. Also, it's important to add scroll margin to the headings so that when a user clicks on a TOC item, without it the page will jump to the heading, but the heading might be hidden behinde a fixed header (if you have one).

html {
  scroll-behavior: smooth;
}

h1, h2, h3, h4, h5, h6 {
  scroll-margin-top: 100px;
}

4. Customize the TOC components (Optional)

You can not only customize the CSS classes, but also the HTML for the TOC components. rehype-toc provides a customizeTOC option, which allows you to customize the entire TOC HTML node tree. It also has a customizeTOCItem option, which allows you to customize each item in the TOC, or to completely remove an item or replace it.

import rehypeToc, { HtmlElementNode, ListItemNode } from 'rehype-toc';

const withMDX = createMDX({
  options: {
    rehypePlugins: [
      [rehypeToc, { 
        customizeTOC: (toc: HtmlElementNode) => {
          // return undefined to use the existing toc
          // return a new node to replace the existing toc
          // return false to prevent the toc from being added
        },
        customizeTOCItem: (tocItem: ListItemNode, heading: HtmlElementNode) => {
          // return undefined to use the existing toc item
          // return a new node to replace the existing toc item
          // return false to prevent the toc item from being added
        }
      }],
    ],
  }
});

Best Practices and Considerations

Responsiveness

  • Collapsible TOC: Consider making TOC collapsible on mobile, or hide it
  • Sticky Positioning: Use sticky positioning on larger screens, so that the TOC is always visible when scrolling down the page

SEO Considerations

  • Structured Data: Consider adding structured data for better SEO
  • Heading Hierarchy: Maintain proper heading hierarchy (h1 → h2 → h3)
  • Internal Linking: TOC provides natural internal linking structure

Conclusion

Adding a table of contents to your MDX files in Next.js can significantly enhance the user experience. The approach you choose depends on your specific requirements. In this article we've covered a simple approach and maintainable approach, taking full use of rehype-toc and rehype-slug capabilities.

Resources