How to Write a README.md That Developers Actually Read

February 5, 2026 · 9 min read

A README is the front door to your project. It's the first thing visitors see on GitHub, npm, or any repository hosting platform. A great README turns curious visitors into users and contributors. A bad one — or worse, a missing one — sends them looking for alternatives.

This guide walks through the anatomy of an effective README, with real examples and a template you can adapt for your own projects.

Why READMEs Matter

Studies of open-source projects consistently show that projects with good READMEs get significantly more stars, forks, and contributions. Why? Because:

  • Developers evaluate projects in seconds. If they can't figure out what your project does and how to use it within 30 seconds, they're gone.
  • The README is your documentation's landing page. Even if you have a full docs site, the README is what people see first.
  • It signals project quality. A well-written README suggests the code is also well-written and maintained. A sloppy README raises red flags.

The Essential Sections

Not every project needs every section, but here are the ones that make the biggest difference, in recommended order:

1. Project Title and Description

Start with a clear, concise description of what the project does. Not how it works — what it does for the user. One to three sentences max:

# Fastify

Fast and low overhead web framework for Node.js.
Fastify is a web framework highly focused on providing
the best developer experience with the least overhead
and a powerful plugin architecture.

2. Badges

Badges provide at-a-glance project metadata — build status, version, license, download count. They go right after the title:

# My Project

[![npm version](https://img.shields.io/npm/v/my-project)](https://npmjs.com/package/my-project)
[![Build Status](https://img.shields.io/github/actions/workflow/status/user/repo/ci.yml)](https://github.com/user/repo/actions)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Downloads](https://img.shields.io/npm/dm/my-project)](https://npmjs.com/package/my-project)

Use shields.io to generate badges. Don't overdo it — 3-5 relevant badges is the sweet spot. Too many badges make the header look cluttered.

3. Quick Start / Installation

Get the reader from zero to "it works" in as few steps as possible. Show the install command and the most basic usage:

## Quick Start

```bash
npm install my-project
```

```javascript
import { createApp } from 'my-project';

const app = createApp();
app.get('/', () => 'Hello World!');
app.listen(3000);
```

The quicker someone can copy-paste this and see a result, the more likely they are to adopt your project. Avoid walls of configuration — show the simplest possible example first.

4. Features

A bulleted list of what the project offers. Be specific and focus on user benefits:

## Features

- ⚡ **Fast** — handles 30k req/sec on a single core
- 🔌 **Plugin system** — extend with 200+ community plugins
- 📝 **TypeScript** — full type safety out of the box
- 🔒 **Secure** — built-in schema validation with Ajv
- 📊 **Logging** — structured logging with Pino

5. Usage Examples

After the quick start, show 2-3 more examples that cover common use cases. Each example should be self-contained and copy-pasteable:

## Usage

### Basic routing

```javascript
app.get('/users/:id', async (request) => {
  const user = await getUser(request.params.id);
  return user;
});
```

### With middleware

```javascript
app.use(authMiddleware());
app.get('/protected', (request) => {
  return { user: request.user };
});
```

6. API Reference or Configuration

For libraries, document the main API. Tables work well for configuration options:

## Configuration

| Option    | Type     | Default | Description              |
|-----------|----------|---------|--------------------------|
| port      | number   | 3000    | Server port              |
| host      | string   | '0.0.0.0' | Bind address          |
| logger    | boolean  | false   | Enable request logging   |
| maxBody   | string   | '1mb'   | Maximum request body     |

7. Contributing

If you want contributions, make it easy. A brief section or link to a CONTRIBUTING.md:

## Contributing

Contributions are welcome! Please read our
[Contributing Guide](CONTRIBUTING.md) before submitting
a pull request.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing`)
5. Open a Pull Request

8. License

Always include the license. One line is enough:

## License

MIT © [Your Name](https://github.com/username)

Common Mistakes

  • No description at all. A repo with just code and no README is a mystery box. Even a one-paragraph description is better than nothing.
  • Too much detail up front. Don't lead with architecture decisions or implementation details. Start with what it does and how to use it. Move deep dives to a docs folder or wiki.
  • Outdated examples. Nothing kills trust faster than code examples that don't work. When you update the API, update the README.
  • No installation instructions. "It's obvious" isn't a valid installation guide. Even for simple npm packages, spell out npm install your-package.
  • Screenshot-only documentation. Screenshots can't be searched, copied, or updated easily. Use text and code examples as the primary documentation, with screenshots as supplements.
  • Wall of text. Use headers, bullet points, code blocks, and visual breaks. Scannable READMEs get read; paragraphs get skimmed.

README Template

Here's a complete template you can copy and adapt:

# Project Name

Brief description of what this project does and why
someone would want to use it.

[![npm version](https://img.shields.io/npm/v/project)]()
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)]()

## Quick Start

```bash
npm install project-name
```

```javascript
import { thing } from 'project-name';
// Minimal working example
```

## Features

- Feature one with brief description
- Feature two with brief description
- Feature three with brief description

## Usage

### Common Use Case 1

```javascript
// Example code
```

### Common Use Case 2

```javascript
// Example code
```

## API

| Method | Description | Returns |
|--------|------------|---------|
| `create()` | Creates a new instance | `Instance` |
| `destroy()` | Cleans up resources | `void` |

## Contributing

Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md).

## License

MIT © [Your Name](https://github.com/username)

Advanced Techniques

  • Add a demo GIF. A short screen recording showing the project in action is worth a thousand words. Keep it under 10 seconds and under 5MB.
  • Use collapsible sections for verbose content like changelogs or full API docs. The <details> HTML tag works in GitHub Markdown.
  • Include a table of contents for READMEs longer than a few screens. GitHub shows an auto-generated TOC icon, but an explicit one is more visible.
  • Link to related projects. If your library works well with others, mention them. The community appreciates cross-references.
  • Test your code examples. Some projects use tools that extract and test code blocks from README files to prevent them from going stale.

Try it yourself

Draft your next README in MarkdownFTW with live preview — see how it looks before pushing.

Open the Editor →