Skip to main content
HomeBlogHow to Create a Table of Contents in Markdown

How to Create a Table of Contents in Markdown

Learn how to make a table of contents in Markdown — manual TOC links using heading anchors, auto-generated TOCs, and best practices for long documents, docs sites, and READMEs.

Published: 2026-06-21


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:

  1. Lowercase everything## Getting Started becomes getting-started.
  2. Spaces become hyphens — each run of whitespace collapses to a single -.
  3. Special characters are stripped — punctuation like ., ,, (, ), ?, !, and & is removed (though hyphens already present are kept).
  4. Numbers are preserved## Step 3: Install becomes step-3-install.
  5. Duplicate headings get a suffix — a second ## Overview receives -1, the third -2, and so on.
## Installation Guide
## Setup & Configuration
## What's New in 2.0?
## FAQ
## FAQ

These 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_level and toc_max_heading_level in docusaurus.config.js to 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-toc plugin or Kramdown's {: toc} marker placed where you want the list:
## Contents
{:toc}

## Introduction

The 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. Installation and Configuration tell readers more than Step 1 and Step 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.

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.

More articles

How to Create a Table of Contents in Markdown | MD File Viewer