The Anatomy of a Perfect README File (With Examples)
Most READMEs die in the first three lines. Here's the structure that turns a forgotten repo into something people actually clone, read, and contribute to.
DocPilot Team
AI documentation research and engineering from Onzira Labs.
Most developers treat the README like a footnote. They write a half-sentence project description, paste an install command, push the commit, and move on. Then they wonder why their repo has twelve stars after eight months.
The README is not a footnote. For most open-source projects, it is the entire first impression. It is what a hiring manager skims before opening a single file. It is what a contributor reads before deciding whether to send a pull request. It is what a user copies from when they get stuck.
A great README does not need to be long. It needs to be honest, scannable, and structured in the order a reader actually thinks. Below is the anatomy of one that works, broken into the nine sections that consistently show up in the repositories developers actually use.
1. The Project Name and One-Line Description
The first line after the heading should answer three questions without scrolling: what is this, who is it for, and why should I care.
# pgwatch
Real-time PostgreSQL query monitor for backend engineers tired of `pg_stat_statements` guesswork.
Compare that with the more common version:
# My Project
A tool for monitoring stuff.
The second version gives the reader nothing to act on. The first tells a backend engineer exactly what they get and who it competes with. If your one-liner requires the reader to open your docs to understand it, the line has failed.
Keep it under 200 characters. Use active verbs. Name the technology and the audience. Save nuance for the next section.
2. Badges That Actually Mean Something
Badges are not decoration. They are compressed trust signals. A row of four well-chosen badges tells a reader more in two seconds than three paragraphs of marketing copy.
The badges that earn their place:
| Badge | What it signals |
|---|---|
| Build status | The code in this repo is not broken right now |
| License | I can legally use this |
| Version | This project is maintained, not abandoned |
| Coverage | The tests are not aspirational |
| Downloads | Real people ship this |
| Discord / Slack | I can get help when stuck |
Skip badges for package downloads on a library that has 40 weekly installs. Skip the "Made With" and "Stars" badges. Skip anything you have not earned or cannot defend.
A clean layout:
[](...)
[](...)
[](LICENSE)
[](...)
Four badges, one line, no scrolling. That is the target.
3. The Screenshot or Demo
A picture is worth roughly the same number of words as it always was. For a CLI tool, that means an animated terminal recording. For a web app, a screenshot of the main view. For a library, a minimal code example in a Gist-style image or asciinema cast.
If your project is hard to screenshot, write the smallest possible working example and put it second. The goal is to let a tired engineer decide in five seconds whether the project matches their problem.

Place the image early, ideally right after the badges. Readers who would have left at the second paragraph will stay if they recognize their own use case in a single frame.
4. Installation That Survives a Clean Machine
The install section is the most-copied section of any README. It is also the most lied about. Authors test it on their own laptops, where half the dependencies are already installed, where Python is the right version, where the right Node version was set two years ago and never updated.
Write your install instructions on a fresh container. Then write them again. Then have someone else run them.
## Installation
Requires Node 18+ and pnpm 9.
```bash
git clone https://github.com/user/repo.git
cd repo
pnpm install
pnpm build
Verify it works:
pnpm test
Three properties of a good install section:
1. **State the prerequisites explicitly.** Node version, OS, system libraries, environment variables. If you assume them, you will lose half your audience.
2. **Show every command.** Do not write "run the setup script." Show the script.
3. **Include a verification step.** A test run, a `--version` flag, a health check. Something that confirms the install worked.
## 5. Usage With a Minimal Working Example
The Usage section is where most libraries either earn their complexity or expose it. Show the smallest possible example that produces a non-trivial result. Not a snippet that prints "hello world." A snippet that does the thing your library exists to do.
For a query monitor:
```typescript
import { watch } from "pgwatch";
const monitor = watch({
connection: "postgres://localhost/mydb",
thresholdMs: 200,
});
monitor.on("slow", (query) => {
console.warn(`Slow query detected: ${query.sql} (${query.durationMs}ms)`);
});
That is eight lines and the reader now understands the value proposition, the API shape, the event model, and the configuration surface. They can decide in 30 seconds whether this fits their stack.
If your library has three valid use cases, pick the most common one for the example. Link to recipes for the others.
6. Configuration as a Table
Once a project has more than three configuration knobs, prose stops working. Readers scan tables. They do not scan paragraphs.
## Configuration
| Option | Type | Default | Description |
|---|---|---|---|
| `connection` | string | required | Postgres connection URI |
| `thresholdMs` | number | `500` | Queries slower than this trigger the `slow` event |
| `sampleRate` | number | `1.0` | Fraction of queries to inspect (0.0 to 1.0) |
| `logFile` | string | `null` | Optional path to write structured logs |
Tables also force you to be precise. If you cannot fill the Default column, your configuration is not actually configurable. If you cannot fill the Description in one sentence, your configuration is too complex.
7. Architecture and How the Pieces Fit
Most projects skip this section. The ones that include it have noticeably fewer GitHub issues in the "how does this work" category. A reader who understands the architecture can debug, extend, and contribute. A reader who does not is reduced to copying examples and hoping.
You do not need a full system design document. One paragraph and a diagram is enough.
## Architecture
pgwatch runs a local agent that tails PostgreSQL's `pg_stat_statements` view,
forwards normalized query events to an embedded ring buffer, and exposes a
WebSocket endpoint for live consumers.
+-------------+ +-----------+ +-------------+
| Postgres | ---> | Agent | ---> | WebSocket |
| (source) | | (parser) | | (consumer) |
+-------------+ +-----------+ +-------------+
If you do not have a diagram, point to the file that documents it. A link to ARCHITECTURE.md is better than nothing. A docs/ folder with three pages is better than that.
8. Contributing Without a Lecture
The Contributing section is where projects accidentally write job descriptions for maintainer positions. Keep it short. Tell contributors how to run tests, what the PR format looks like, and who to ping for questions.
## Contributing
Pull requests welcome. Please:
1. Run `pnpm test` and `pnpm lint` before opening the PR.
2. Add a test for any new behavior.
3. Keep changes focused. Open an issue first for large refactors.
For questions, open a GitHub Discussion or join `#pgwatch` on the project Discord.
A CODE_OF_CONDUCT.md link belongs here, but the file should be separate. A CONTRIBUTING.md link is fine for anything longer than 15 lines. Do not embed both in the README. The README is for orientation, not policy.
9. License and Acknowledgments
End with the license. This is not bureaucratic. It tells a corporate user whether they can ship your code in their product, whether they need to include attribution, and whether they need to call their lawyer.
## License
MIT — see [LICENSE](./LICENSE) for the full text.
Built on top of [pg_stat_statements](https://www.postgresql.org/docs/current/pgstatstatements.html)
and inspired by [posthog](https://github.com/PostHog/posthog).
The acknowledgment line is optional but builds goodwill with the projects you depended on. People notice.
A Note on Length
The above sections total roughly 400 lines for a real project. That is the upper bound for a README. If your README is more than 600 lines, you have started writing documentation. Move it to a docs/ folder, link from the README, and keep the README as a table of contents.
The job of the README is to orient. The job of the docs is to teach. Conflating the two produces a 2,000-line wall of text that nobody reads.
Writing a great README takes about an hour the first time, fifteen minutes once you have a template, and zero minutes if you generate it from your code. That last option is what DocPilot is built for. Connect it to a GitHub repo and it produces a README, setup guide, architecture summary, and API reference from the actual code, then keeps everything in sync through webhooks so the docs never drift behind the latest commit. The free tier covers public repositories, and for most side projects it is the fastest way to ship a README that does not embarrass you. Try it on your own repo before you push the next commit.
Read next
api-documentation
The Underrated Power of Well-Structured API Docs
Most API docs fail not because of missing information, but because of missing structure. Here's why architecture beats aesthetics every time.
Read
roadmap
Building a Public Documentation Roadmap: Best Practices
A public documentation roadmap signals that you take your docs seriously. Here's how to build one that earns user trust instead of empty promises.
Read
open-source
Documentation for Open Source Projects: A Growth Playbook
Great docs are the single highest-leverage growth tool in open source. Here's the playbook maintainers actually use to turn docs into contributors, stars, and trust.
Read