A long Markdown document without navigation is a wall of text. Adding a markdown table of contents (TOC) fixes this instantly: a clickable list of section links that jump readers to the part they actually need.
The good news is that Markdown already turns your headings into anchor links automatically, so building a TOC is mostly about pointing the right links at the right anchors. Below we cover how heading anchors are generated, how to hand-build a markdown toc as a nested list, how generator tools and static-site generators automate it, and the best practices that keep long docs and READMEs readable. To test any example, paste it into our editor.
How Markdown Generates Heading Anchors and IDs
Every Markdown heading becomes an HTML anchor with an auto-generated id. Once you understand the rules that produce those IDs, you can link to any heading with confidence — this is the foundation of any markdown toc. For a deeper treatment of heading syntax itself, see our markdown headings guide.
The conversion follows predictable, GitHub-flavored rules:
- Lowercase everything —
## Getting Startedbecomesgetting-started. - Spaces become hyphens — each run of whitespace collapses to a single
-. - Special characters are stripped — punctuation like
.,,,(,),?,!, and&is removed (though hyphens already present are kept). - Numbers are preserved —
## Step 3: Installbecomesstep-3-install. - Duplicate headings get a suffix — a second
## Overviewreceives-1, the third-2, and so on.
## Installation Guide
## Setup & Configuration
## What's New in 2.0?
## FAQ
## FAQThese render with the IDs installation-guide, setup--configuration, whats-new-in-20, faq, and faq-1. Notice that Setup & Configuration keeps a double hyphen because & is stripped while the surrounding spaces still collapse to hyphens. When in doubt, render the page once and inspect the heading's id in your browser's dev tools.
Building a Manual Markdown Table of Contents
A manual markdown table of contents is simply a nested bulleted list whose items are anchor links. Markdown link syntax — covered in detail in our markdown links guide — uses [text](#anchor), where the # prefix marks an in-page jump.
Here's a copy-paste-ready example that mirrors a typical docs page:
## Table of Contents
- [Introduction](#introduction)
- [Installation](#installation)
- [Requirements](#requirements)
- [Step-by-step Setup](#step-by-step-setup)
- [Usage](#usage)
- [Basic Commands](#basic-commands)
- [Advanced Options](#advanced-options)
- [FAQ](#faq)
## Introduction
Welcome to the project.
## Installation
### Requirements
Node.js 18+ and npm.
### Step-by-step Setup
Clone, install, and run.Indenting sub-items by two spaces nests them under their parent, mirroring the heading hierarchy. Each anchor matches the ID GitHub would generate from the corresponding heading. To brush up on nested bullets, see our markdown lists guide.
The biggest downside of a manual TOC is maintenance: every time you rename or reorder a heading, you must update the TOC by hand. For documents that change often, an automated approach is usually better.
Generating a TOC Automatically: Tools and Conventions
If maintaining links by hand sounds tedious, you're not alone — the ecosystem has settled on a few conventions and tools that build a markdown toc for you.
The _TOC_ Placeholder and markdown-toc
Some renderers and CI workflows recognize a _TOC_ marker placed at the top of a file: the renderer replaces it with an auto-generated TOC at build time. More universally, the npm package markdown-toc and similar CLI tools scan your headings and insert or update a TOC block between sentinel comments:
<!-- toc -->
- [Introduction](#introduction)
- [Installation](#installation)
<!-- tocstop -->Run markdown-toc -i README.md and the tool rewrites the section between the markers, leaving the rest of your file untouched. GitHub itself does not natively expand _TOC_ or sentinel blocks in plain repos, so for a README these tools are the pragmatic choice.
Editor and CI Helpers
VS Code extensions (such as the Markdown All in One extension), the Markdown TOC extension, and pre-commit hooks can regenerate the TOC on every save or commit. These are ideal for READMEs and living docs that live in a repo but aren't built by a static-site generator.
Automatic TOCs in Static-Site Generators
Docs sites usually skip hand-maintained TOCs entirely and let the framework generate one from the heading structure at build time.
- Docusaurus ships an on-page TOC out of the box; set
toc_min_heading_levelandtoc_max_heading_levelindocusaurus.config.jsto control depth. - mkdocs (with the Material theme) renders a sidebar and per-page outline automatically from your headings.
- Jekyll supports a TOC via the
jekyll-tocplugin or Kramdown's{: toc}marker placed where you want the list:
## Contents
{:toc}
## IntroductionThe generator handles anchor generation, deduplication, and nesting rules consistently across every page — the lowest-maintenance option when you control the build.
Comparing Markdown TOC Approaches
| Approach | Effort to set up | Maintenance | Best for |
|---|---|---|---|
| Manual anchor links | Low — just write the list | High — update on every heading change | Short posts, one-off notes |
Generator tool (markdown-toc, extensions) |
Medium — install once, learn markers | Low — re-run on save/commit | READMEs, repo docs, living Markdown |
| Static-site generator auto-TOC | Medium-high — depends on framework | None — fully automatic | Docs sites, handbooks, multi-page wikis |
For a single README, a generator or a manual TOC is plenty. For a docs site with dozens of pages, lean on your SSG's built-in TOC so you never touch it.
Markdown Table of Contents Best Practices
A useful markdown toc is short, accurate, and shallow enough to scan at a glance.
- Cap your depth. Link to H2s and H3s only. Anything deeper turns the TOC into noise and pushes real content below the fold.
- Keep it in sync. If you hand-edit the TOC, treat it like code: update it whenever you rename, add, or remove a heading. A stale TOC that jumps to a missing anchor is worse than no TOC.
- Automate where you can. For anything that changes weekly, use a generator or your SSG's auto-TOC so the list stays correct for free.
- Keep titles descriptive.
InstallationandConfigurationtell readers more thanStep 1andStep 2. Good headings also produce cleaner, more predictable anchors. - Place the TOC near the top. Right under a short intro is ideal — readers decide quickly whether to scroll or to jump.
These habits matter most in README files, where the TOC is often a visitor's first interaction with your project.
Frequently Asked Questions
Does GitHub render _TOC_ automatically?
No. Plain GitHub does not expand a _TOC_ marker in READMEs or other rendered Markdown. You can use the markdown-toc CLI, a VS Code extension, or a GitHub Action to generate and commit a TOC that GitHub then displays as normal links.
Why is my anchor link not jumping to the heading?
The link's #anchor must exactly match the heading's generated id. Common mismatches include leftover special characters (&, ?, (), capitalization differences, or extra spaces. Render the page and inspect the heading element to copy the exact id, then mirror it in your TOC.
How deep should a markdown table of contents go?
Two levels — H2 and H3 — is the sweet spot for most documents. Three levels is acceptable for very long references; deeper than that, the TOC becomes harder to scan than the document itself.
Can I auto-generate a TOC in any static-site generator?
Most popular ones — Docusaurus, mkdocs, Jekyll (with jekyll-toc or Kramdown's {: toc}), Hugo (via templates), and Eleventy (via plugins) — offer automatic TOCs. The mechanism differs, but the result is the same: a TOC derived from your headings with no manual upkeep.
Wrapping Up
A markdown table of contents turns a long, intimidating document into something navigable. Start with the anchor-generation rules, build a manual TOC for short pieces, reach for markdown-toc or an editor extension when docs grow, and let your static-site generator handle TOCs at scale. Keep the depth shallow, keep the links in sync, and your readers — and future you — will thank you. Paste your headings into the editor and watch the anchors render in real time.
Try it in your browser
Open the homepage editor to view, edit, and export Markdown instantly — no install required.