A README that renders perfectly on github.com can render strangely when the same file is mirrored to a docs site, embedded in a package registry, or pulled into a static site generator. The cause is rarely a bug. It is the gap between GitHub Flavored Markdown (GFM) and CommonMark, the two specs most modern parsers claim to follow.
This piece is about where the two specs diverge, why it matters specifically for README files, and how to write README content that survives leaving GitHub.

Photo by ready made on Pexels
The short history of the divergence
The original Markdown spec, published in 2004, was small and intentionally permissive. It did not include tables, fenced code blocks, strikethrough, task lists, autolinks, or several other features that feel essential today. Every platform that needed those features added them, and they did not coordinate.
CommonMark emerged around 2014 as a careful re-specification of the original that resolved hundreds of ambiguities about exactly how nested constructs should parse. It deliberately omitted features that the original did not have. CommonMark says nothing about tables, nothing about task lists, nothing about strikethrough.
GitHub Flavored Markdown is CommonMark plus an explicit extension list. GFM adds tables, task lists, strikethrough, autolinking of URLs and email addresses, and a few other things. GitHub publishes the GFM spec as a strict superset of CommonMark, which is the cleanest place this whole story has ever gotten.
The trouble is that most other parsers say they support "Markdown" without saying which dialect. A parser that aims at strict CommonMark will not render your task lists. A parser that aims at "GitHub-style" but predates the GFM spec will render task lists slightly differently. A parser that calls itself "Markdown" without further qualification could be anything.
Where this hits you in a real README
A README that uses task lists for a roadmap section will render with checkboxes on github.com and with literal - [ ] characters in most other contexts. A README with strikethrough notes about deprecated features will render those notes with literal tildes. A README using GFM-style autolinks (a bare URL that becomes clickable without explicit Markdown link syntax) will render those as plain text in any strict CommonMark parser.
The most common embedding contexts for a README outside GitHub are package registries. The Node.js package registry renders README files with their own parser. The Python Package Index renders README files using readme_renderer, which is strict about supported features. The Rust package registry renders with yet another parser. Each one is close to GFM but not identical.
The second most common embedding context is documentation sites. A README pulled into MkDocs, Docusaurus, or a Hugo theme is going through that toolchain's parser, which is usually CommonMark-based with some extensions. The mismatch is exactly the same as with package registries.
The defensive subset for portable READMEs
The fix is to write the README inside the intersection of CommonMark and GFM, which is most of GFM minus the parts the original spec did not have.
- Use ATX headings (the
#style) only, levels 1 through 3. - Use fenced code blocks with common language hints. Skip the obscure language names.
- Use ordinary unordered and ordered lists. Skip task lists for anything that matters off-GitHub.
- Use tables sparingly. They are GFM-only but most modern parsers support them, so they are a reasonable risk.
- Skip strikethrough. Rewrite the sentence instead.
- Skip task lists when the README is the only documentation. Use a real "Roadmap" heading with bulleted entries.
- Use explicit Markdown link syntax for every URL. Do not rely on autolinking. A bare URL in your README will render as plain text in strict parsers.
- Skip footnotes. They are neither GFM nor CommonMark.
This is most of what you would write anyway. The painful part is task lists and autolinks, both of which feel like features you should be able to use. They are GFM-only and they will fail silently the first time someone mirrors your README to a docs site.

Photo by Erika Andrade on Pexels
A small test that catches almost everything
A useful workflow trick: render your README locally with a strict CommonMark parser before pushing. If anything looks wrong, the issue is a GFM-only feature you are leaning on. Fix it now and the README survives every downstream tool that will eventually consume it.
A drafting tool with a strict-CommonMark preview makes this test instant. The Markdown Editor at EvvyTools renders against a CommonMark-compliant pipeline so the preview shows you exactly what a strict parser will produce. Features that work in GitHub but not in CommonMark show up immediately as raw syntax in the preview pane, which is faster feedback than waiting for someone to flag the broken render after mirroring.
The same logic applies to internal company documentation. If your team mirrors READMEs into Confluence or Notion or a generated docs site, the parser at the destination is not GFM. Defensive writing pays off every time the file moves.
"READMEs end up in more places than the writer expects. The portability discipline you bring to a published blog post is worth applying to a README the first time it leaves the repo." - Dennis Traina, founder of 137Foundry
A small audit you can run on any existing README
If you maintain READMEs already and want to know which ones are at risk, a five-minute audit catches most of the trouble. Open the README and scan for these constructs:
- Task lists (lines starting with
- [ ]or- [x]) - Strikethrough (text wrapped in double tildes)
- Bare URLs that should autolink (URLs in the text without explicit Markdown link syntax)
- Footnote markers (
[^1]references with definitions at the bottom) - Tables with column alignment colons in the separator row
Each of these is a candidate for breaking when the file moves outside GitHub. You do not have to remove them all immediately. The triage that matters is whether the README is mirrored anywhere downstream. If it is, fix the constructs that broke last time the mirror updated. If it is not, leave them alone but note the dependency so future you knows what to check before mirroring.
A useful supplementary tool here is a strict parser that you can paste into. The interactive playground on the CommonMark site is the easiest one, since it spits out the exact HTML a strict parser would produce. If task lists become raw text in that output, that is the canary.
When GFM-only features are worth using
There are cases where a feature being GFM-only is fine. If the file lives on github.com only and is read in GitHub's own UI, you can use any GFM feature freely. Task lists in an issue body, strikethrough in a PR comment, autolinks in a wiki page - all fine. The portability concern only matters when the file is going to leave the GitHub renderer.
The decision is therefore not "avoid GFM features." It is "know which files travel and which do not, and write the traveling ones defensively." A README is almost always a traveling file. An issue comment almost never is.
For a longer walkthrough of the portable subset across GitHub, Notion, and blog CMSes - including the line-break and link traps that catch most writers - the companion guide on the EvvyTools blog covers the same problem from a writing-workflow angle rather than a README-specific one.
More writing-workflow tools live at the EvvyTools homepage, all browser-based and worth a look if you do most of your drafting in plain text.











