Skip to main content

Auto TOC Plugin

The auto TOC (Table of Contents) plugin automatically injects a table of contents section before the first ## Heading in your documentation pages.

Features

  • Automatic Insertion - No manual TOC creation needed
  • Smart Placement - Inserts before the first H2 heading
  • Internationalized - TOC title respects your locale settings
  • Styled Component - Uses built-in <Toc> component

How It Works

The plugin is a remark plugin that:
  1. Scans the markdown AST for the first ## Heading (depth 2)
  2. Inserts a TOC section before that heading
  3. Uses the useTranslation hook for the “Table of Contents” title
  4. Renders the built-in <Toc> component

Configuration

The plugin is automatically enabled. No configuration is needed:
packages/doom/src/plugins/auto-toc/index.ts:5-12
export const autoTocPlugin = (): RspressPlugin => {
  return {
    name: 'doom-auto-toc',
    markdown: {
      remarkPlugins: [remarkAutoToc],
    },
  }
}

Implementation

The plugin transforms your markdown:
packages/doom/src/plugins/auto-toc/remark-auto-toc.ts:6-19
export const remarkAutoToc: Plugin<[], Root> = function () {
  return (root) => {
    let foundIndex = -1

    for (const [index, node] of root.children.entries()) {
      if (node.type === 'heading' && node.depth === 2) {
        foundIndex = index
        break
      }
    }

    if (foundIndex === -1) {
      return
    }
    // ... inserts TOC
  }
}

Generated Output

For a page like this:
# Page Title

Introduction text.

## First Section

Content...

## Second Section

More content...
The plugin generates:
# Page Title

Introduction text.

<div className="doom-auto-toc rp-toc-exclude">
  <h2>{useTranslation()('toc')} {#toc}</h2>
  <Toc />
</div>

## First Section

Content...

Customization

Excluding from Rspress TOC

The generated TOC has rp-toc-exclude class to prevent it from appearing in Rspress’s own TOC sidebar.

Translation

The TOC title is translatable. Add translations in your i18n configuration:
i18n.yaml
en:
  toc: "Table of Contents"
zh:
  toc: "目录"

Styling

The TOC container has the doom-auto-toc class for custom styling:
.doom-auto-toc {
  margin: 2rem 0;
  padding: 1rem;
  border: 1px solid var(--rp-c-divider);
  border-radius: 8px;
}

When TOC is Not Generated

The plugin skips TOC generation if:
  • No ## Heading (H2) is found in the page
  • The page only has H1 or H3+ headings
  • The page is too short to warrant a TOC

Disabling Auto TOC

To disable the auto TOC for specific pages, you can:
  1. Use only H1 headings - The plugin requires an H2 to trigger
  2. Remove the plugin - Comment it out in your config:
export default defineConfig({
  plugins: [
    // autoTocPlugin(),  // Disabled
  ]
})
  1. Create a custom plugin - Override the behavior for specific routes

Manual TOC

If you need more control, you can disable auto TOC and use Rspress’s manual TOC:
import { Toc } from '@rspress/runtime'

# My Page

<Toc />

## Section 1

Best Practices

  1. Use H2 for Major Sections - The plugin triggers on the first H2
  2. Consistent Heading Hierarchy - Follow H1 → H2 → H3 order
  3. Descriptive Headings - Headings appear in the TOC, make them clear
  4. Not Too Many Headings - Keep TOC manageable (5-10 items ideal)

Integration with Rspress

Doom’s auto TOC works alongside Rspress’s built-in TOC sidebar:
  • Auto TOC - In-page TOC before content
  • Sidebar TOC - Right sidebar navigation
Both use the same heading structure but serve different purposes.

Build docs developers (and LLMs) love