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.
Potential slug collisions
Slugs that repeat across documents or differ across headings.#introduction
Appears in 2 document(s), 2 heading(s) total.
- guide.mdL1“Introduction”
- api.mdL1“Introduction”
#getting-started
Appears in 2 document(s), 2 heading(s) total.
- guide.mdL5“Getting started”
- api.mdL5“Getting started”
How to use the slug collision simulator
- Each panel represents one Markdown document. Rename the label to match the file you're testing (e.g.,
guide.md). - Paste headings or full Markdown into each panel, or click the file icon to open a
.mdfrom disk. - Add or remove panels with the Add document button or the trash icon — there's no hard limit.
- 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.mdandupgrade.mdmay have a## Prerequisitesheading. 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
## Summaryin 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:
- Lowercase the heading text.
- Strip everything that isn't a word character, space, or hyphen.
- Collapse runs of whitespace into single hyphens.
- Collapse runs of hyphens into single hyphens.
- 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
| Strategy | When to use |
|---|---|
| Rename to add context | Public docs where descriptive titles help |
Add explicit {#custom-id} anchors | Stable URLs that must not change |
| Place each file under its own route | Sites where pages stay separate (Docusaurus) |
| Scope by section (folder-as-prefix) | Sphinx, MkDocs material themes |
Accept GitHub's -1 suffix | Single-file READMEs only |
Companion tools
- Markdown Slug Generator — see slugs for a single document with TOC.
- Markdown Heading Audit — ensure each file's outline is valid first.
- Markdown Merge & Split — actually combine the files once collisions are resolved.
Privacy & data
The slug algorithm and collision detection both run in your browser. Document contents stay on your machine.
Frequently asked questions
- 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.
- 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.
- 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.
- 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.
- 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.
- No. The slug algorithm and the collision check both run inside your browser. We never upload, log, or store any document contents.
What is a slug collision?
When does this tool matter?
How are slugs generated?
Can I add more than three documents?
How do I fix a collision once it's flagged?
Is anything uploaded?
Related tools
More free browser tools in the same workflow.
Use the API
Automate this workflow in your app with the same engine that powers these browser tools.
New to the platform? Start with the API quickstart, then try a live request in the API playground.
Explore the API platform