Skip to content
ToolBoxGeniehome

Markdown TOC Generator

Developer Tools · Added

A long README earns a table of contents, and hand-maintaining one guarantees a stale link within a month. Paste the document and this reads its headings, builds the nesting, and generates anchors that match how your host actually slugs them.

Paste a README or any Markdown document. Headings inside fenced code blocks are ignored.

What GitHub, and most Markdown viewers, generate

How to use the markdown toc generator

  1. 1Paste your Markdown document into the box.
  2. 2Pick the slug style for wherever it will be published — GitHub, GitLab or plain.
  3. 3Set which heading levels to include, and whether to keep the top-level title.
  4. 4Copy the result as Markdown, or as HTML if you need a rendered list.

Examples

A document with a repeated heading

Input
# Title, ## Setup, ### Install, ## Usage, ## Setup
Result
A nested list where the second Setup links to #setup-1, matching the numbered suffix GitHub appends — flagged with a note explaining the rename.

Skipping the title

Input
A README whose H1 is the project name
Result
A contents list starting at the H2 sections, since linking to the title from directly beneath it adds nothing.

About the markdown toc generator

Anchors are a property of the renderer

The single most common reason a generated table of contents does not work is that its anchors were built for a different renderer. Markdown itself has no concept of a heading anchor at all: the link target only exists because whatever converts the file to HTML invented an id for each heading, and every such tool made its own choices about case, punctuation and duplicates.

So the question is never 'what is the correct slug for this heading' but 'what will the thing rendering this file produce'. That is why the style setting sits at the top of this page rather than being decided for you.

How deep is worth listing

A table of contents that lists every heading down to the fourth level stops being navigation and becomes a second copy of the document. Two levels is usually right for a README, three for a specification with genuinely nested structure.

The other judgement is where to start. A README whose first heading is the project name gains nothing from a link back to it, and dropping that entry also removes a level of indentation from everything underneath — which is why skipping the H1 is the default here.

Frequently asked questions

Why do slug styles differ between hosts?
Because no specification covers it. CommonMark says nothing about heading anchors, so every renderer invented its own scheme. GitHub lower-cases, drops most punctuation and joins words with hyphens; GitLab handles some edge cases differently; plain style is the conservative subset that works nearly everywhere. Pick the one matching where the file will actually be read, because a mismatch produces links that silently go nowhere.
What happens when two headings have the same text?
The second gets a numeric suffix, so a repeated 'Overview' becomes #overview-1, then #overview-2. That is what GitHub does, and matching it is the whole point — anchors have to agree with the renderer's, not merely be unique among themselves. The count of renamed headings is reported so you know it happened.
Are headings inside code blocks picked up?
No. Fenced blocks are tracked and skipped, so a shell comment beginning with a hash inside triple backticks is not mistaken for a heading. Both backtick and tilde fences are recognised, including the longer runs used to nest one fence inside another.
Does it understand the underlined heading style?
Yes. Setext headings — text underlined with equals signs or hyphens — are read as level one and level two respectively, alongside the usual hash-prefixed form. Mixed documents are common in older projects and both styles end up in the same list.