Technical documentation best practices for READMEs, API docs, architecture docs, runbooks, and developer guides. Use when writing or reviewing documentation, creating onboarding guides, or establishing documentation standards.
Good documentation is the difference between a project that scales and one that stalls. Write for the reader who has zero context.
Trigger conditions:
Every project README follows this order:
# Project Name
One-sentence description of what this does and who it's for.
## Quick Start
Minimum steps to run the project locally (≤5 commands).
## Prerequisites
- Runtime versions (Python 3.12+, Node 22+)
- Required tools (Docker, pnpm)
- Required accounts/access
## Installation
Step-by-step setup with copy-pasteable commands.
## Usage
Common tasks with examples.
## Architecture
Brief overview with a diagram (link to detailed docs).
## Contributing
How to submit changes, run tests, and follow conventions.
## License
Rules:
<placeholder> without explanation)# ADR-{NNN}: {Decision Title}
## Status
Accepted | Superseded by ADR-{NNN} | Deprecated
## Context
What problem are we solving? What constraints exist?
## Decision
What did we decide and why?
## Alternatives Considered
| Option | Pros | Cons | Why Not |
|--------|------|------|---------|
## Consequences
What changes as a result? What new constraints are introduced?
# Runbook: {Incident Type}
## Symptoms
What does the user/monitor see?
## Impact
Who is affected? What's the blast radius?
## Diagnosis Steps
1. Check {metric/log/dashboard} — expected: {value}
2. Run `{command}` — look for {pattern}
3. ...
## Resolution Steps
1. {Step with exact command}
2. {Verification step}
3. ...
## Escalation
If not resolved in {time}, contact {team/person}.
## Post-Incident
- [ ] Update this runbook with new learnings
- [ ] File ticket for permanent fix
| Reader | Needs | Writing Style |
|---|---|---|
| New developer | Setup, concepts, where things are | Step-by-step, no assumptions |
| Experienced dev | API reference, edge cases, configuration | Concise, scannable, tables |
| Ops/SRE | Runbooks, monitoring, deployment | Commands, checklists, decision trees |
| Stakeholder | What it does, status, decisions | High-level, diagrams, outcomes |
Put the most important information first. Readers scan, they don't read.
┌─────────────────────────┐
│ What + Why (lead) │ ← First paragraph answers the key question
├─────────────────────────┤
│ How (details) │ ← Supporting details, steps, configuration
├─────────────────────────┤
│ Reference (appendix) │ ← Edge cases, history, alternatives
└─────────────────────────┘
| Do | Don't |
|---|---|
| "This function returns the user's name" | "This function facilitates the retrieval of the nomenclature associated with the user entity" |
"Run npm install" | "Execute the package installation command" |
| "Fails if the file doesn't exist" | "In the event that the specified file is not present in the filesystem, the operation will not succeed" |
| Short sentences (< 25 words) | Run-on sentences with multiple clauses |
| Active voice | Passive voice |
# ✅ GOOD: Complete, runnable example with imports
from datetime import datetime
from myapp.models import User
def create_user(name: str, email: str) -> User:
"""Create a user and return the saved instance."""
user = User(name=name, email=email, created_at=datetime.now())
user.save()
return user
# Usage
user = create_user("Alice", "[email protected]")
print(user.id) # => "usr_abc123"
# ❌ BAD: Incomplete snippet, no context
def create_user(name, email):
user = User(name=name, email=email) # What is User? Where is it imported?
user.save() # Does this return something?
Rules:
Use diagrams for architecture, data flow, and sequences. Text alone fails for spatial relationships.
| Diagram | Use For |
|---|---|
| Flowchart | Decision trees, process flows |
| Sequence | API call chains, auth flows |
| Architecture | System overview, service boundaries |
| ERD | Database schema relationships |
| State | Lifecycle transitions (order, ticket) |
### `POST /api/v1/customers`
Create a new customer record.
**Auth:** Bearer token required
**Request Body:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | string | Yes | Customer full name (1-200 chars) |
| email | string | Yes | Valid email address |
**Response:** `201 Created`
```json
{
"data": { "id": "cust_abc", "name": "Alice", "email": "[email protected]" }
}
Errors:
| Code | When |
|---|---|
| 400 | Missing required field |
| 409 | Email already exists |
| 422 | Invalid email format |
## 7. Documentation Maintenance
### Keep Docs Near Code
src/ auth/ login.py README.md ← Auth module docs live with auth code docs/ architecture.md ← System-level docs in docs/ runbooks/ ← Operational docs
### Freshness Rules
| Trigger | Action |
|---------|--------|
| API endpoint changed | Update API docs in same PR |
| New environment variable | Update README + .env.example |
| Architecture decision | Write or update ADR |
| Production incident | Update or create runbook |
| New developer onboarded | Test README, fix gaps found |
## 8. Review Checklist
When reviewing documentation:
- [ ] Answers "what does this do?" in the first paragraph
- [ ] Code examples are complete and runnable
- [ ] Commands are copy-pasteable
- [ ] No stale references to old code, endpoints, or config
- [ ] Diagrams are up to date
- [ ] Written for the target audience (not the author)
- [ ] No jargon without definition
- [ ] Links work and point to current resources
## 9. Anti-Patterns
| Anti-Pattern | Problem | Fix |
|---|---|---|
| Docs written once, never updated | Stale docs are worse than no docs | Update in same PR as code changes |
| Wall of text | Nobody reads it | Use headings, tables, code blocks, diagrams |
| Documenting obvious code | Noise, maintenance burden | Document "why", not "what" |
| Screenshots of terminal output | Can't copy-paste, hard to update | Use code blocks with text output |
| "See the code for details" | Reader has to reverse-engineer | Write the explanation |
| Assuming reader context | "Just run the usual setup" | Spell out every step |