Skip to content
AZ Tools

Markdown Table of Contents Generator

Generate a [text](#anchor) TOC from Markdown headings — bullet, numbered, or HTML output with GitHub/GitLab/simple slug styles.

Table of contents
TOC appears here.

How to use

  1. Paste your Markdown in the left panel.
  2. Choose style (bullet / numbered / HTML), slug rule (matching where you'll publish), and min/max heading level.
  3. Copy the TOC and paste it at the top of your document.

About this tool

Show

Generate a table of contents from the headings in a Markdown document, as a nested list of links you can paste at the top of a README. Choose the heading depth to include, and pick the slug style your host actually uses — GitHub, GitLab and a plain simple form all build anchors differently, which is exactly why a table of contents copied from one repository quietly stops working when the file moves to another. Repeated headings are numbered the way GitHub numbers them, so a document with three sections called Usage gets links that land on the right one rather than all three pointing at the first. Everything runs locally in your browser — the document is never uploaded.

Frequently asked questions

Why three slug styles?

GitHub's slug rule keeps Unicode (한글 → 한글). GitLab strips more aggressively. 'Simple' is ASCII-only — useful for generic Markdown renderers.

How are duplicate headings handled?

Same as GitHub: the first instance gets the plain slug, later ones append -1, -2, etc. Anchors will resolve correctly.

Why is code block content ignored?

Lines starting with # inside fenced code (between lines of three backticks) are usually shell prompts or comments, not headings. The parser tracks fence state to skip them.

Does GitHub render [text](#slug) correctly?

Yes — GitHub auto-generates anchor IDs for every heading and resolves matching link slugs. Use the GitHub slug style here.

My table of contents broke after moving the file to another host. Why?

Because the anchor rules are not standardised. GitHub keeps Unicode and strips most punctuation; GitLab and other renderers differ on both counts, so a link that resolved on one produces a dead anchor on the next. Regenerate with the style matching wherever the file now lives.

Should I write the anchors by hand instead?

Only if you also stop editing headings, which nobody does. Anchors are derived from heading text, so renaming a section silently breaks any link pointing at it — including ones in other files and in issues. Regenerating the table after an edit is the cheaper habit.

Related tools