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 textGenerated 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)

  1. Convert to lowercase
  2. Replace spaces with hyphens (-)
  3. Remove punctuation except hyphens and underscores
  4. 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**

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 .md file 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:

ToolTypeHow it works
Markdown All in One (VS Code)ExtensionInserts TOC at cursor; updates on save
doctocnpm CLIInserts between <!-- START --> markers
markdown-tocnpm CLIOutputs TOC to stdout or inserts inline
gh-md-tocShell scriptGenerates TOC from GitHub-rendered HTML
MDViewermacOS appRenders 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:

  1. Open a Markdown file
  2. Open the Command Palette (Cmd+Shift+P)
  3. 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

PlatformAuto anchorsBuilt-in TOCManual links
GitHubYesYes (sidebar icon)Yes
GitLabYesYes ([[_TOC_]])Yes
BitbucketYesNoYes
VS Code PreviewYesVia extensionYes
MDViewerYesYes (sidebar)Yes
ObsidianYesYes ([[toc]])Yes
NotionYesYes (/toc block)N/A
TyporaYesYes (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 #setup and #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.

Download MDViewer

Requires macOS 13.0 or later. Intel and Apple Silicon.