A README is usually the first real interaction someone has with your project, and most of it is plain Markdown. The good news is that the rules that make Markdown render reliably are also the rules that make it readable as raw text in a terminal or a diff.
This guide covers the parts of Markdown that matter for docs: the syntax essentials, the formatting that breaks most often, and the structural decisions that separate a README people skim and bounce from one that gets them running your project.
Markdown essentials worth getting right
Most Markdown is intuitive, but a few mechanics trip people up constantly.
Blank lines are significant. Markdown collapses single line breaks. If you write two lines back to back with no blank line between them, they render as one paragraph. To force a paragraph break, leave a blank line. To force a hard line break without a new paragraph, end a line with two trailing spaces (or a backslash in some flavors, though trailing spaces are more portable).
Lists need a blank line before them. This is the single most common rendering bug:
markdownHere are the steps: - Install dependencies - Run the build
Many parsers will glue that first list item onto the paragraph above it. Add a blank line after the intro sentence and the list renders correctly.
Escape characters when you mean them literally. Underscores, asterisks, backticks, and angle brackets all carry meaning. If you need a literal asterisk or an
<email@example.com>\**Pick a flavor and know it. GitHub Flavored Markdown (GFM) is the practical baseline because it powers GitHub, GitLab, and most static-site generators. It adds tables, task lists, strikethrough, and fenced code blocks on top of the original CommonMark spec. If your docs live somewhere else, confirm which features that renderer supports before relying on them.
If you want to see exactly how a file will render before you commit it, a live editor helps. The free Markdown preview tool renders as you type, which catches the blank-line and escaping issues above before they ship.
Headings: the spine of the document
Headings do two jobs. They give readers a visual outline, and on most platforms they generate the anchor links and the auto-built table of contents. Treat them as structure, not styling.
Use ATX-style headings (the
#markdown# Project Name ## Installation ### From source
A few rules keep headings clean:
- One H1 per document. It is the title. On GitHub the repo name is already shown, so many READMEs start at the title and never repeat it.
- Do not skip levels. Going from straight totext
##breaks the implied outline and the generated anchors look arbitrary.text#### - Keep them short and descriptive. "Configuration" beats "How to configure the various available settings." The heading is a label, not a sentence.
- Avoid inline code or links inside headings where you can. They make for ugly auto-generated anchor IDs and awkward URLs.
If your README is long, a manual table of contents near the top earns its keep. Each entry is just a link to the heading's anchor, which GFM derives by lowercasing the text and replacing spaces with hyphens.
Code fences over indentation
Fenced code blocks, opened and closed with three backticks, are the only code-block style you should use. The old four-space-indent style still works but breaks the moment your code itself contains indentation, and it carries no language information.
Always tag the fence with a language. The label drives syntax highlighting and signals intent:
javascriptconst config = { retries: 3, timeout: 5000, };
Use
bashshjsonyamlpythondockerfiletextTwo details people miss:
Showing literal backticks. If your code block needs to contain a triple-backtick fence itself, open the outer block with four backticks. The parser closes on a matching count.
Inline code for names. Wrap file names, flags, env vars, and function names in single backticks:
npm install--verboseAPI_KEYOne honest caveat: never put real secrets in example blocks. Use obvious placeholders like
YOUR_API_KEYTables that stay maintainable
GFM tables are pipe-delimited with a separator row of dashes:
markdown| Flag | Default | Description | | ----------- | ------- | ------------------------------ | | `--port` | 8080 | Port the server binds to | | `--verbose` | false | Enable detailed logging |
You can control alignment with colons in the separator row:
:---:---:---:The raw source does not need to be visually aligned to render correctly. The columns above are padded only for human readability in the source file. That said, aligned source is genuinely easier to edit, and most editors and formatters can auto-align it.
Know when not to use a table. Markdown tables cannot contain block elements such as lists, multiple paragraphs, or fenced code blocks. If a cell needs more than a short phrase, use a definition-style list or sub-headings instead. Tables shine for flat, scannable reference data such as CLI flags, environment variables, or supported versions, and they get painful for anything richer.
Task lists for roadmaps and checklists
Task lists are list items with a checkbox marker:
markdown- [x] Core parser - [x] CLI interface - [ ] Plugin system - [ ] Documentation site
On GitHub these render as interactive checkboxes, and in issues and pull requests they roll up into a progress indicator. In a README they are a clean way to communicate project status or a contributor's setup checklist. The
x[ ]Links, images, and reference style
Inline links are the familiar
[text](url)markdownSee the [contributing guide](./CONTRIBUTING.md) for details.
Images use the same syntax with a leading bang, and the alt text is not optional courtesy. It is what screen readers announce and what shows when the image fails to load:
markdown
When the same URL appears several times, or when a long URL clutters a sentence, use reference-style links. You write a short label inline and define the target elsewhere, usually at the bottom of the section or file:
markdownWe follow [semantic versioning][semver] for all releases. [semver]: https://semver.org
Reference links keep prose readable and make it trivial to update a URL in one place. They are especially worth it in long documents.
For good anchor text, link the meaningful phrase, not "click here" or a bare URL. "See the installation steps" reads better and is more accessible than "see the steps here."
Badges: useful, until they are noise
Badges are just images, usually linked, that sit at the top of a README to show build status, version, license, or coverage:
markdown[](../../actions) [](LICENSE)
They are genuinely useful for at-a-glance status, but a wall of fifteen badges signals insecurity more than quality. Keep the ones that answer real questions a new user has: Is this maintained? What license? What version? Drop decorative ones. And make sure every badge actually reflects live state. A green "build passing" badge that has not updated in two years erodes trust in the whole document.
Structuring a README people actually read
Syntax aside, the ordering of a README is what determines whether it works. People arrive with questions in a predictable sequence, and a good README answers them in that order.
A reliable skeleton:
- Title and one-line description. What is this, in a single sentence, before any badges or prose.
- A short paragraph on the problem it solves. Why this exists and who it is for. Keep it to a few sentences.
- Installation. Exact, copy-pasteable commands. This is the highest-traffic section.
- Quick start or usage. The smallest example that does something real. One working snippet beats three paragraphs of description.
- Configuration and reference. Tables for flags, options, and environment variables.
- Contributing, license, and links. Where to go next.
A few principles that hold across all of these:
- Front-load the payoff. A reader should understand what your project does and see it working within the first screen. Move deep architecture notes and design rationale to a separate file or further down.text
docs/ - Every command should be runnable as written. Test your own quick-start in a clean clone. Broken setup instructions are the fastest way to lose a user.
- Prefer one excellent example over many shallow ones. A single end-to-end snippet teaches more than a catalog of one-liners.
- Keep line length reasonable in the source. Wrapping prose at around 80 to 100 characters keeps diffs clean and readable, though some teams prefer one sentence per line so edits produce minimal diffs. Either is fine; just be consistent.
Finally, treat the README as code. Run it through a linter or formatter so spacing and list markers stay consistent, and preview it before merging rather than trusting that it looks the way the raw text suggests. Rendering and reading are different acts, and the gap between them is exactly where Markdown bugs live. A quick pass through a live Markdown preview closes that gap and costs nothing.
Clean Markdown is not about clever syntax. It is about consistent, predictable structure that reads well as raw text and renders without surprises, so the content can do its job.