How to Make a Table of Contents in Markdown
(there is no native syntax)
Markdown has no native table-of-contents syntax. There is no tag you drop in to get one. What you have instead are three routes: write the TOC by hand as a list of links, let a platform like GitHub generate one from your headings, or skip writing one entirely and navigate the file with an outline panel. Here is each, and when to use it.
The three routes at a glance
| Route | What it is | Where it works |
|---|---|---|
| Write it by hand | A list of anchor links you type yourself | Works everywhere, including plain GitHub and GitLab |
| Let the platform build it | GitHub auto-shows one; some editors support a [TOC] marker | Only on that platform; not portable |
| Use an outline panel | A live heading list the app shows beside the note | For navigating, not for putting a TOC in the file |
Write it by hand (the portable way)
A Markdown TOC is just a bulleted list where each item is an anchor link to a heading. You write it once and it travels with the file:
## Table of contents
- [Getting started](#getting-started)
- [Configuration](#configuration)
- [FAQ](#faq)
## Getting started
... The one thing that trips people up is the anchor itself. The link target is not the heading text as-is; it is a slugged version:
- Lowercase everything.
- Turn spaces into hyphens.
- Drop punctuation, so
## My Setup!becomes#my-setup.
Get that wrong and the link just does nothing when clicked. If a link looks right but will not jump, the slug is almost always the reason. This is one more case of Markdown looking broken when it is really a small rule.
Let a platform build it
Some tools generate the TOC so you do not have to:
- GitHub shows an interactive table of contents in the header of any rendered
.mdwith two or more headings. You write nothing; it reads your headings. - Some editors (StackEdit, and the Python-Markdown extension) turn a
[TOC]marker into a generated list.
The catch is portability. A [TOC] marker is not standard Markdown, so in a plain renderer it just shows up as the literal text [TOC]. And GitHub's header TOC lives on GitHub, not inside your file. Handy where they work, gone the moment the file moves somewhere else.
Or skip the TOC and use an outline
Often you do not actually want a table of contents written into the file. You want to move around a long document, which is a different problem, and it is the one that bites when an AI hands you a plan.md too long to read.
An outline panel solves that without a TOC. NoteLoom shows one in its right panel: it lists every heading in the current note, updates live as you edit, highlights the section you are scrolled to, and jumps you there when you click. So you navigate a long file by its structure, with nothing to write and nothing to keep in sync.
The honest line between the two: the outline is for reading and navigating; it does not write a TOC into your .md. If you need a table of contents that lives in the file itself, for GitHub or a handoff, that is still the by-hand list of anchor links above.
FAQ
Does Markdown have a table-of-contents syntax?
How do I link to a heading in the same file?
Why does my [TOC] show up as literal text?
Does GitHub make a table of contents automatically?
How do I just navigate a long Markdown file without making a TOC?
Will a hand-written TOC keep working if I move the file?
Navigate a long .md by its headings
Open a long .md in NoteLoom in Chrome / Edge / Arc, and the outline panel lists every heading so you can jump around it, no TOC to write. Local file in, local file out, nothing uploaded.