Skip to content

Slug Collision Simulator

Find duplicate Markdown heading IDs before they break deep links

Paste or open multiple Markdown documents and instantly see where GitHub-style heading slugs would clash. Add as many documents as you like, with line-accurate hit lists for every conflict. Runs entirely in your browser.

3 document(s) compared · 2 collision(s) found

Potential slug collisions

Slugs that repeat across documents or differ across headings.
  • #introduction

    Appears in 2 document(s), 2 heading(s) total.

    • guide.mdL1Introduction
    • api.mdL1Introduction
  • #getting-started

    Appears in 2 document(s), 2 heading(s) total.

    • guide.mdL5Getting started
    • api.mdL5Getting started

How to use the slug collision simulator

  1. Each panel represents one Markdown document. Rename the label to match the file you're testing (e.g., guide.md).
  2. Paste headings or full Markdown into each panel, or click the file icon to open a .md from disk.
  3. Add or remove panels with the Add document button or the trash icon — there's no hard limit.
  4. The Potential slug collisions panel updates live: every slug that repeats across documents (or differs only by heading title) is flagged with line numbers.

Why slug collisions matter

A Markdown heading like ## Getting Started becomes the anchor #getting-started. Inside a single GitHub README, two identical headings get auto-suffixed (#getting-started, #getting-started-1). That suffix is document-local and does not survive merging — so the moment you concatenate two files, you get either:

  • Silent duplicates — the second occurrence wins, the first becomes unreachable.
  • Renumbered anchors — every deep link that pointed to the original ID now goes to the wrong section.

Either way, links break. The simulator surfaces the problem before publication.

Real scenarios this catches

  • Migrating a multi-file docs repo to a single-page docs site. Both installation.md and upgrade.md may have a ## Prerequisites heading. The simulator flags the collision; you rename one to ## Prerequisites (upgrade) and ship.
  • Stitching chapter files for a static site. A book or course built from per-chapter Markdown often has ## Summary in every chapter. The simulator shows all of them at once.
  • Merging release notes from two repos. Each repo's CHANGELOG.md probably has a ## [Unreleased] heading. When merging, decide whether to scope the slug (## Frontend Unreleased) or to keep the files separate on the rendered site.
  • Cross-file deep links. If your team uses [See Configuration in api.md](api.md#configuration) patterns, this tool helps confirm the target ID will still resolve after a docs reorg.

How the slug algorithm works

"Getting Started!" → "getting-started"

Step by step:

  1. Lowercase the heading text.
  2. Strip everything that isn't a word character, space, or hyphen.
  3. Collapse runs of whitespace into single hyphens.
  4. Collapse runs of hyphens into single hyphens.
  5. Trim leading and trailing hyphens.

That matches GitHub's renderer closely enough for cross-file work. If your downstream platform uses a different algorithm (e.g., Docusaurus's emoji-stripping rules, or Jekyll's kramdown), spot-check a few headings before relying on the result.

Strategies for resolving collisions

StrategyWhen to use
Rename to add contextPublic docs where descriptive titles help
Add explicit {#custom-id} anchorsStable URLs that must not change
Place each file under its own routeSites where pages stay separate (Docusaurus)
Scope by section (folder-as-prefix)Sphinx, MkDocs material themes
Accept GitHub's -1 suffixSingle-file READMEs only

Companion tools

Privacy & data

The slug algorithm and collision detection both run in your browser. Document contents stay on your machine.

Frequently asked questions

What is a slug collision?
A slug is the URL-safe ID derived from a Markdown heading (for example, `Getting started` → `getting-started`). A collision happens when two headings produce the same slug — either within a document or across documents that will be merged into one site. GitHub auto-disambiguates within a single file by appending `-1`, `-2`, but cross-file collisions silently break deep links.
When does this tool matter?
Mostly when you're merging content. Examples: stitching multiple READMEs into a microsite, importing chapters from separate `.md` files into a single docs page, migrating from one platform to another, or generating a sitemap from a multi-file repo. If every heading lives in its own file forever, you can usually ignore it.
How are slugs generated?
The tool uses the same slug algorithm as the rest of the site: lowercase, strip non-word characters, collapse whitespace into hyphens. This matches GitHub's renderer closely enough that the results map cleanly when published.
Can I add more than three documents?
Yes. Click 'Add document' to add another panel; click the trash icon on any panel to remove it. There's no hard cap — the simulator runs in real time even with dozens of documents.
How do I fix a collision once it's flagged?
Three options: (1) rename one of the conflicting headings to be more specific (`## Setup` becomes `## Setup (API)`); (2) prefix the merged content with file-specific anchor IDs; (3) place each document under a unique sub-route on your site so the slug namespaces are separate.
Is anything uploaded?
No. The slug algorithm and the collision check both run inside your browser. We never upload, log, or store any document contents.