| name | readme-that-converts |
| description | Write or rewrite a README that turns a visitor into a user. Use when creating a README, when a project's README is a wall of text or a stub, when the user says "nobody understands what my project does", or when preparing a repo for launch. Covers the 30-second rule, section ordering, badge discipline, install and quickstart blocks, screenshots/demos, comparison tables, and multi-language README structure. Also use for polishing package-registry descriptions (npm, PyPI, crates.io) and the GitHub repo About blurb. |
A README That Converts
The README is the product page. For most visitors it is the entire product — they
will decide in under 30 seconds whether to keep reading, and they are on a phone about
40% of the time.
The 30-second test
A first-time visitor must be able to answer, above the fold, without scrolling past
the first screen:
- What is this? (category — "a CLI", "a Python library", "a Postgres extension")
- What problem does it solve? (their problem, in their words)
- Should I keep reading? (is it for their language/platform/scale)
If a visitor must scroll to learn what the project is, the README has already failed.
Badges, logos, and tables of contents are not answers to those questions.
Apply the test literally: read only the first 15 lines aloud and ask whether a
stranger could describe the project. If not, cut until they can.
Section order
Ordered by how many readers get that far. Later sections cost nothing; earlier ones
are expensive real estate.
# Name
> One sentence. Under 15 words. Category + differentiator.
[badges: build | version | license] ← 3–5 max, one line
[hero: screenshot, GIF, or 6-line code sample]
## Why <Name>? ← 3–5 bullets, comparative, concrete
## Install ← copy-pasteable, one command if possible
## Quickstart ← smallest complete working example
## Usage / Features ← progressive depth
## Documentation ← link out once docs exceed the README
## Comparison ← if entering a crowded space
## Contributing ← one line + link to CONTRIBUTING.md
## License
Notably absent near the top: table of contents (GitHub renders one from the outline
menu), long feature matrices, architecture diagrams, and the origin story. They belong
in docs/, or below the fold.
Writing the one-liner
Formula: <category> for <audience> that <differentiator>
- "A build tool for JavaScript that skips bundling in development."
- "A Rust HTTP client with connection pooling and no async runtime."
- "Kubernetes operator that snapshots Postgres to S3 on a schedule."
Delete these words: modern, blazing-fast, simple, powerful, elegant, robust,
lightweight, next-generation, developer-friendly, opinionated, batteries-included.
They carry zero information because every project claims them. If removing an adjective
does not change the meaning, it was noise.
Use the same one-liner in the GitHub About field, the package description, and the
social preview. Consistency compounds recognition.
The hero
Pick exactly one, matched to the project type:
| Project type | Best hero |
|---|
| CLI tool | Terminal recording (asciinema, VHS) or a copy-pasteable session |
| Library / API | 6–10 line code sample showing the core call |
| UI / app | Screenshot, dark mode, real data, no lorem ipsum |
| Infrastructure | A small architecture diagram, or a config + result pair |
Rules:
- Real output, real data.
foo/bar examples read as untested.
- Under 10 lines for code heroes. If the minimum viable example is 40 lines, the
API is the problem — see
api-design.
- GIFs under ~3 MB, or the mobile experience is a gray box. Prefer
VHS for terminal demos: it is scripted, so
it regenerates when the CLI changes instead of rotting.
- Host images in-repo (
docs/assets/ or .github/assets/), not on an image host
that will 404 in two years.
Install and quickstart
The single highest-value block in the file. Requirements:
- Copy-pasteable verbatim. No
<your-token-here> in the first command.
- Ordered by likelihood. Put the package manager 80% of users have first; hide
the rest behind a
<details> block.
- Show the expected output. It tells the user it worked.
- Test it. Run the exact commands in a clean container before shipping. A broken
install command is the most expensive bug a project can have — it converts every
arriving user into a lost one, silently.
## Install
```bash
npm install -g widget
```
<details>
<summary>Other install methods</summary>
```bash
brew install widget # macOS
cargo install widget # from source
docker run ghcr.io/org/widget:latest
```
</details>
## Quickstart
```bash
widget init my-app && cd my-app
widget dev
```
```
✓ Ready on http://localhost:3000 (142ms)
```
Badges
Three to five, one line, all meaningful. Each badge must answer a question a user
actually has:
- Build status — is
main healthy?
- Latest version — is this maintained?
- License — may I use it?
- Downloads — do others use it? (only once the number is non-embarrassing)
- Discord/Slack — where do I get help? (only if it is staffed)
Skip: code style, PRs-welcome, made-with-love, "awesome" self-badges, and coverage
percentages under 80%. A wall of 14 badges reads as compensating and pushes the
one-liner below the fold.
Comparison tables
Only if entering a crowded category. Rules that keep it credible:
- Be fair. Users will verify, and a dishonest table is remembered longer than the
project. Include a column where a competitor wins.
- Compare on axes users choose by — not on feature counts.
- Date it. "As of 2026-03, v2.1 vs v4.0." Comparisons rot.
- Never disparage. "X is bloated" reads as insecurity; "X bundles a runtime; we
don't" is a fact the reader can act on.
Alternative that ages better: a "When not to use this" section. It builds more
trust than any table, costs three lines, and filters out users who would have opened
mismatched issues.
Multi-language READMEs
For projects with international users, a language switcher at the top:
<div align="center">
**English** · [简体中文](i18n/README.zh-CN.md) · [日本語](i18n/README.ja.md) · [Español](i18n/README.es.md)
</div>
Conventions that work:
- English is
README.md at the root — GitHub renders it by default and it is the
lingua franca of the issue tracker. Translations live in i18n/README.<tag>.md,
using BCP-47 tags (zh-CN, pt-BR, es, ja, ko, fr, de).
- Same switcher block at the top of every translation, with the current language
bolded and un-linked.
- Translations are contributions. Name a maintainer per language in
CONTRIBUTING.md and stamp each file with the commit or version it tracks.
- A stale translation is worse than none — it ships wrong install commands. If a
translation falls more than a minor version behind, add a banner linking to English.
- Never machine-translate code blocks, flags, or error strings. Translate prose;
leave the commands identical.
Anti-patterns
- README as changelog. Move it to
CHANGELOG.md.
- The origin story first. "In 2023 I was frustrated with..." Nobody has bought in
yet. Put it at the bottom, or in a blog post.
- Install instructions that don't work. Test in a clean container, every release.
- Screenshots of code. Unsearchable, uncopyable, inaccessible. Use code fences.
- A wall of badges above the name.
- "Documentation coming soon." Three honest sentences beat a promise.
- Emoji headers on every section. Fine in moderation; at every heading it reads as
filler and hurts screen readers.
- Full API reference inline. Once it exceeds a screen, move to
docs/ and link.
- No link back to the docs site from the README, and no link back to the repo
from the docs site.
Maintenance
The README decays fastest of any file, because it is the one nobody re-reads.
- Re-run every command block at each minor release (automate it — see
ci-pipelines)
- Regenerate terminal recordings when the CLI output changes
- Re-check comparison tables twice a year, or delete them
- When the project's scope changes, rewrite the one-liner first — everything
downstream inherits its framing