Skip to main content

Markdown Table of Contents Generator

Generate a table of contents from Markdown headings. Select the available anchor style and heading depth for your document.

Markdown TOC Generator workspace

Markdown input(14 total headings, 14 included)
Table of contents
- [Toolk Project Documentation](#toolk-project-documentation)
  - [Getting Started](#getting-started)
    - [Prerequisites](#prerequisites)
    - [Installation](#installation)
    - [First Run](#first-run)
  - [Architecture](#architecture)
    - [Frontend Stack](#frontend-stack)
    - [Component Library](#component-library)
      - [Color Tokens](#color-tokens)
      - [Typography](#typography)
  - [Contributing](#contributing)
    - [Code Style](#code-style)
    - [Pull Requests](#pull-requests)
  - [License](#license)

Auto-Indented Nesting

Each heading depth (#, ##, ###) becomes one level deeper in the list output. Base level is normalized so the TOC starts flush regardless of the source's top heading.

Three Slug Styles

GitHub (default), GitLab, and Pandoc — pick the platform where the document will be rendered. Duplicate slugs auto-suffix with -1, -2, -3 (the GitHub convention).

Configurable Depth

Restrict to top-N levels (e.g. include only H1-H3 and skip the leaf-level sub-headings). Choose ordered (numbered) or unordered list output, 2 or 4 space indent.

100% Client-Side

Markdown documents may contain drafts, internal notes, or sensitive prose. The parser runs entirely in your browser — nothing leaves the page.

Markdown TOC Generator: build a linked table of contents from your headings

Generate a table of contents from Markdown headings. Select the available anchor style and heading depth for your document. Heading-anchor rules differ between renderers. Duplicate headings, punctuation, and non-Latin text can produce different fragments on different platforms. Test the generated links in the rendered destination document rather than assuming one anchor style works everywhere.

How to use the Markdown TOC generator

  1. Paste your Markdown into the input pane, or press Sample to load an example document.
  2. Set Min level and Max level to choose which heading depths appear (default H1 to H4).
  3. Choose a Slug style — GitHub, GitLab, or Pandoc — to match where the document will render.
  4. Pick Indent (2 or 4 spaces), toggle Numbered list for ordered output, and toggle Include #anchors off for a plain-text list.
  5. Press Copy on the Table of contents pane and paste the result at the top of your README or post.

What is an anchor slug, and how is it generated?

When a Markdown renderer turns a heading into HTML, it adds an id attribute so the heading can be linked directly with a #fragment URL. That id is the slug. The WHATWG HTML standard defines how a browser scrolls to that fragment, but the slug text itself is decided by the renderer. GitHub's rule is the most widely copied: lowercase the heading, drop punctuation, and replace each run of spaces with a single hyphen. The reference implementation is github-slugger, which the GitHub team mirrors for README anchors.

This tool also nests by heading level: an ## under an # indents one step, an ### two steps, and so on. It detects the smallest level used and treats it as depth zero, so a document that starts at H2 still produces a flush-left TOC. Duplicate slugs are disambiguated with -1, -2, -3 suffixes, exactly as GitHub does.

How each platform slugifies headings

PlatformSlug RuleNotes
GitHublowercase → replace whitespace with hyphens → drop everything except [a-z0-9-_]Used by README anchors on github.com. Most permissive about underscores.
GitLablowercase → replace any non-alphanumeric run with single hyphen → trim hyphensGitLab pages and wiki anchors. Stricter — collapses runs of punctuation.
PandocSame as GitHub for common casesUsed by Pandoc-rendered HTML and many static-site generators.

Worked examples: heading → slug → TOC line

Plain heading · GitHub style

## Getting Started → - [Getting Started](#getting-started)

Punctuation · GitHub style

### What is New in 2026? → [What is New in 2026?](#what-is-new-in-2026)

Underscores · GitHub vs GitLab

## node_modules → #node_modules (GitHub) vs #node-modules (GitLab)

Edge case · emoji & non-Latin headings

A heading like ## 你好 World reduces to #world in this tool, because it strips non-ASCII characters. On github.com the same heading anchors as #你好-world, since GitHub keeps Unicode letters. For non-Latin or emoji headings, confirm the rendered anchor on the target platform before relying on the link.

Where TOC generation helps

README and documentation

GitHub renders Markdown READMEs with auto-anchored headings — paste your draft and generate the TOC to put at the top.

Blog posts

Long-form posts benefit from a TOC for scannability. Generate one quickly from your draft headings.

Technical specifications

RFC-style specs and design docs need a TOC. Generating it deterministically prevents drift between body and TOC.

Wiki pages

GitLab and Confluence wikis use slug-based anchors. Pick the right slug style for your platform.

Documentation sites

Static-site generators (Docusaurus, MkDocs, VitePress) can auto-generate TOCs at build time, but a generator helps when porting drafts.

The slug detail that silently breaks anchors

Most TOC generators advertise "GitHub-compatible" slugs but quietly drop characters GitHub keeps. This tool's GitHub rule allows only a-z, 0-9, hyphen, and underscore, then strips everything else. Real GitHub, per github-slugger, preserves Unicode letters — so привет stays привет on github.com but collapses here. For purely ASCII headings the two match exactly; the divergence only appears with accented, Cyrillic, CJK, or emoji text.

The practical fix is the same advice that prevents most broken anchors: keep heading text ASCII and unique. Duplicate headings auto-suffix with -1, -2, which makes a link target shift the moment you insert or remove a section above it. Unique, plain headings produce stable slugs that survive reorders.

Four TOC authoring tips

1. Stop at H3 for most documents

H4 and deeper rarely belong in a top-level TOC. Set Max level to H3 for blogs, H4 for long technical specs.

2. Keep headings concise

Long headings produce long slugs and ugly anchor URLs. Aim for 2 to 6 words and move detail to the body text.

3. Avoid duplicate heading text

Duplicates auto-suffix with -1, -2, which produces fragile anchors that shift when you insert or remove sections.

4. Regenerate after big edits

If you reshuffle sections, the TOC at the top drifts. Re-paste the document and re-extract — it takes seconds.

Last updated: September 15, 2026 · Runs 100% in your browser — no uploads, tool input is not sent to Toolk.

Frequently asked questions

Are headings inside fenced code blocks ignored?

Yes. Lines within ``` or ~~~ fences are skipped entirely, so a Bash comment like # define inside a sample never masquerades as an H1 and pollutes the contents list. ATX headings from # through ###### are recognized, and trailing closing hashes on a heading line are stripped cleanly.

Which anchor slug conventions does it match?

GitHub, GitLab, and Pandoc each slugify heading text slightly differently — punctuation stripping, underscore handling, and space replacement vary. Pick the platform you publish to, and duplicate headings receive GitHub’s -1, -2 suffix convention so every link stays unique.

Can I generate a TOC without clickable links?

Yes. Turning off Include #anchors emits a clean, indented outline of heading text only — the format you want for changelogs, code-review notes, or repository files like AGENTS.md where anchors would add noise rather than navigation.

Do my documents get sent anywhere while processing?

No. Parsing and TOC construction happen in memory inside your browser tab, and Toolk’s page analytics do not receive your content. Drafts that have not been published anywhere stay private, and generation keeps working offline once loaded.

How do I keep the TOC accurate as the document grows?

Regenerate it after structural edits rather than hand-maintaining entries, then paste the fresh block over the old one. For the rendered HTML version of the same document, Toolk’s Markdown to HTML converter (/tools/markdown-to-html) produces matching heading tags for the anchors to hit.

Need a different tool?

Browse all 103 browser-based tools (103 currently marked free), or tell us what useful utility we should build next.

Browse all tools