Markdown Table of Contents: How to Add a TOC
Manual anchor links, GitHub auto-TOC, and generator tools
Quick Answer
Markdown has no built-in TOC syntax. Create one manually with a list of anchor links that point to headings in the same file. Most Markdown processors auto-generate heading anchors, so the links just work.
## Table of Contents
- [Installation](#installation)
- [Usage](#usage)
- [Basic Example](#basic-example)
- [Advanced Options](#advanced-options)
- [FAQ](#faq)
Each link uses the format [Display Text](#anchor), where the anchor is the heading text lowercased with spaces replaced by hyphens and special characters removed.
How Heading Anchors Work
When a Markdown processor renders a heading, it automatically creates an HTML id attribute that you can link to. The rules for generating anchors vary slightly by platform:
| Heading text | Generated anchor |
|---|---|
| ## Getting Started | #getting-started |
| ## What Is an .md File? | #what-is-an-md-file |
| ## Step 1: Install | #step-1-install |
| ## C++ Templates | #c-templates |
Anchor generation rules (GitHub / CommonMark)
- Convert to lowercase
- Replace spaces with hyphens (
-) - Remove punctuation except hyphens and underscores
- If duplicate, append
-1,-2, etc.
Tip: not sure what anchor GitHub generates? Click any heading on a rendered Markdown page — the URL hash shows the exact anchor.
Method 1: Manual TOC
Write an unordered or ordered list of links at the top of your document. Use nesting to reflect the heading hierarchy:
Table of Contents
**Table of Contents**
1. [Overview](#overview)
2. [Installation](#installation)
1. [macOS](#macos)
2. [Windows](#windows)
3. [Configuration](#configuration)
4. [API Reference](#api-reference)
Pros: works everywhere, full control over which headings to include.
Cons: must be updated manually when headings change.
Method 2: GitHub Auto-Generated TOC
GitHub renders a TOC icon (three horizontal lines) at the top of any Markdown file with two or more headings. Clicking it opens a sidebar navigation panel with all headings as clickable links.
This works on:
- README files and any
.mdfile in a repository - Wiki pages
- Gists with Markdown content
The auto-TOC is read-only — you cannot customize which headings appear or change their names. For that, write a manual TOC or use a generator tool.
Method 3: TOC Generator Tools
Tools that scan headings and insert a TOC automatically, so you do not have to maintain it by hand:
| Tool | Type | How it works |
|---|---|---|
| Markdown All in One (VS Code) | Extension | Inserts TOC at cursor; updates on save |
| doctoc | npm CLI | Inserts between <!-- START --> markers |
| markdown-toc | npm CLI | Outputs TOC to stdout or inserts inline |
| gh-md-toc | Shell script | Generates TOC from GitHub-rendered HTML |
| MDViewer | macOS app | Renders clickable TOC sidebar from any .md file |
VS Code: Markdown All in One
The most popular method for VS Code users. After installing the extension:
- Open a Markdown file
- Open the Command Palette (Cmd+Shift+P)
- Run Markdown All in One: Create Table of Contents
The TOC updates automatically when you save. It respects heading levels and skips any heading you mark with <!-- omit from toc -->.
doctoc (CLI)
Installs via npm and inserts a TOC between comment markers:
npx doctoc README.md
Re-running the command updates the existing TOC without duplicating it. Works well in CI pipelines for keeping TOCs in sync.
Collapsible TOC
For long documents, wrap the TOC in a collapsible section so it does not take up the full screen:
Table of Contents
<details>
<summary>Table of Contents</summary>
- [Installation](#installation)
- [Usage](#usage)
- [Configuration](#configuration)
- [FAQ](#faq)
</details>
This works on GitHub, GitLab, and any processor that supports HTML in Markdown.
Platform Support
| Platform | Auto anchors | Built-in TOC | Manual links |
|---|---|---|---|
| GitHub | Yes | Yes (sidebar icon) | Yes |
| GitLab | Yes | Yes ([[_TOC_]]) | Yes |
| Bitbucket | Yes | No | Yes |
| VS Code Preview | Yes | Via extension | Yes |
| MDViewer | Yes | Yes (sidebar) | Yes |
| Obsidian | Yes | Yes ([[toc]]) | Yes |
| Notion | Yes | Yes (/toc block) | N/A |
| Typora | Yes | Yes (outline panel) | Yes |
GitLab: Built-in TOC tag
GitLab supports a special tag that renders an auto-generated TOC inline:
[[_TOC_]]
## First Heading
Content here...
## Second Heading
More content...
Place [[_TOC_]] anywhere in the document and GitLab renders a full heading list at that position.
Best Practices
- Skip H1 in the TOC. The document title (H1) is usually obvious — start the TOC from H2.
- Limit depth. Include H2 and H3 for readability. H4+ adds clutter in most documents.
- Keep headings unique. Duplicate headings create confusing anchors like
#setupand#setup-1. - Place TOC after the title. Readers expect it at the top, not buried in the middle.
- Use a generator for long docs. Manual TOCs in 50+ heading documents drift out of sync.
FAQ
How do I create a table of contents in Markdown?
Write a list of links using the [Title](#anchor) format. The anchor is the heading text lowercased, with spaces replaced by hyphens and special characters removed. Most platforms auto-generate these anchors, so the links work without extra configuration.
Does GitHub automatically generate a table of contents?
Yes. GitHub shows a TOC icon at the top of any Markdown file with two or more headings. Clicking it opens a sidebar with clickable heading links. You can also write a manual TOC for more control.
What tools auto-generate a Markdown TOC?
The VS Code Markdown All in One extension inserts and updates a TOC on save. CLI tools like doctoc and markdown-toc scan headings and generate a linked list. MDViewer for macOS renders a clickable TOC sidebar from any .md file automatically.
Preview Your Markdown with MDViewer
MDViewer is a native macOS app that renders a clickable table of contents sidebar from any .md file. Open a document from Finder and navigate headings instantly — no manual TOC needed. Lite is free; Pro adds editing, Git history, and PDF export.
Requires macOS 13.0 or later. Intel and Apple Silicon.