Writing Technical Documentation That Developers Actually Read
Let’s be honest: most technical documentation sucks. It’s either too sparse (“just read the code”), too verbose (walls of text nobody reads), or so outdated that it’s actively harmful.
But great documentation? That’s a superpower. It reduces support burden, accelerates adoption, and turns confused users into confident advocates.
Here’s how to write documentation that developers actually read, reference, and respect.
The Documentation Hierarchy of Needs
Section titled “The Documentation Hierarchy of Needs”Not all documentation serves the same purpose. Think of docs as a pyramid:
┌─────────────────┐ │ API Reference │ ← Complete, generated, searchable └─────────────────┘ ┌───────────────────────┐ │ How-To Guides │ ← Task-focused solutions └───────────────────────┘ ┌─────────────────────────────┐ │ Tutorials │ ← Learning-oriented, step-by-step └─────────────────────────────┘ ┌─────────────────────────────────┐ │ Getting Started │ ← Quick wins, hello world └─────────────────────────────────┘Each level serves a different audience with different needs:
- Getting Started: “I need to see if this works for me” (5 minutes)
- Tutorials: “I want to learn by doing” (30-60 minutes)
- How-To Guides: “I need to accomplish a specific task” (10-20 minutes)
- API Reference: “I need to look up exact syntax” (2 minutes)
The Cardinal Rules
Section titled “The Cardinal Rules”Rule #1: Respect the Reader’s Time
Section titled “Rule #1: Respect the Reader’s Time”Developers are busy. Every unnecessary word is a tax on their attention.
Bad:
In order to facilitate the initialization of the application in your local development environment, you will need to execute the installation command using the npm package manager.
Good:
Install dependencies:
Terminal window npm install
Rule #2: Show, Then Tell
Section titled “Rule #2: Show, Then Tell”Code examples first, explanations second.
Bad:
The
createUserfunction accepts a configuration object with properties for username, email, and optional role assignment. The role parameter defaults to ‘user’ if not specified. The function returns a Promise that resolves to a User object.
Good:
// Create a basic userconst user = await createUser({ username: 'alice',});
// Create an admin userconst admin = await createUser({ username: 'bob', role: 'admin'});Rule #3: Test Everything You Write
Section titled “Rule #3: Test Everything You Write”If your code examples don’t actually work, your documentation is worse than useless—it actively harms trust.
How to ensure examples work:
- Extract code examples into test files
- Run them in your CI/CD pipeline
- Use tools like
doctestor equivalent - Include version numbers for dependencies
Rule #4: Write for Scanning, Not Reading
Section titled “Rule #4: Write for Scanning, Not Reading”Developers scan documentation looking for the specific piece they need. Help them.
Techniques:
- Use descriptive headings
- Add code syntax highlighting
- Include a table of contents for long pages
- Use callouts for warnings and tips
- Add visual hierarchy with consistent formatting
Rule #5: Maintain or Remove
Section titled “Rule #5: Maintain or Remove”Outdated docs are worse than no docs. They waste time and erode trust.
Strategies:
- Set up automated checks for broken links
- Review docs with each major release
- Add “last updated” dates
- Archive old versions clearly
- Use version switchers if you support multiple versions
The Anatomy of Great Documentation
Section titled “The Anatomy of Great Documentation”1. Getting Started (The Critical 5 Minutes)
Section titled “1. Getting Started (The Critical 5 Minutes)”Your getting started guide should answer three questions:
- What is this? (1 sentence)
- How do I install it? (1 command)
- Can I see it work? (1 minimal example)
Example:
# Getting Started with SuperAuth
SuperAuth is a zero-config authentication library for Node.js.
## Installation
\`\`\`bashnpm install superauth\`\`\`
## Quick Example
\`\`\`javascriptimport { auth } from 'superauth';
// Protect a routeapp.get('/dashboard', auth.required(), (req, res) => { res.json({ user: req.user });});\`\`\`
That's it! SuperAuth handles session management, CSRF protection,and password hashing automatically.
**Next:** [Learn about configuration →](./config.md)2. Tutorials (Learning by Doing)
Section titled “2. Tutorials (Learning by Doing)”Tutorials are journeys. They should:
- Start from a clean slate (no assumed knowledge)
- Build something real (not contrived examples)
- Explain why, not just how
- End with a working project
- Take 30-60 minutes
Structure:
# Tutorial: Building a Real-Time Chat App
## What You'll Build[Screenshot/GIF of the finished product]
## Prerequisites- Node.js 18+- Basic JavaScript knowledge- 45 minutes
## Step 1: Project Setup[Clear, testable instructions]
## Step 2: Creating the Server[Code + explanation]
## Step 3: Adding Real-Time Features[Code + explanation of concepts]
## Step 4: Deployment[Production-ready deployment]
## What You Learned- WebSocket basics- Real-time data synchronization- Production deployment
## Next Steps- [Add user authentication](./auth-tutorial.md)- [Scale with Redis](./scaling-tutorial.md)3. How-To Guides (Task-Focused Solutions)
Section titled “3. How-To Guides (Task-Focused Solutions)”How-to guides answer specific questions: “How do I…?”
Characteristics:
- Goal-oriented
- Assumes base knowledge
- Gets straight to the point
- Shows the solution, then explains nuances
Example:
# How to Enable Rate Limiting
Rate limiting prevents API abuse. Here's how to add it:
\`\`\`typescriptimport { rateLimit } from 'superauth';
app.use(rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100 // limit each IP to 100 requests per window}));\`\`\`
## Customizing by Route
\`\`\`typescript// Stricter limit for auth endpointsapp.post('/login', rateLimit({ max: 5 }), handleLogin);
// Generous limit for read operationsapp.get('/posts', rateLimit({ max: 1000 }), getPosts);\`\`\`
## Using Redis for Distributed Apps
[Code example with Redis store]
## Common Issues
**Q: Rate limits not working with proxies?**A: Enable trust proxy in Express:\`\`\`typescriptapp.set('trust proxy', 1);\`\`\`4. API Reference (The Single Source of Truth)
Section titled “4. API Reference (The Single Source of Truth)”API documentation should be:
- Complete: Every public method documented
- Generated: Automated from code/types
- Searchable: Easy to find specific methods
- Linked: Cross-references between related items
Good API doc includes:
## createUser(options)
Creates a new user account.
### Parameters
- `options` (Object) - `username` (string, required) - Unique username (3-20 characters) - `email` (string, required) - Valid email address - `password` (string, required) - Minimum 8 characters - `role` (string, optional) - User role. Default: 'user'
### Returns
Promise<User> - Resolves to created user object
### Throws
- `ValidationError` - Invalid input parameters- `DuplicateError` - Username or email already exists
### Example
\`\`\`typescriptconst user = await createUser({ username: 'alice', email: '[email protected]', password: 'secure-password-123'});\`\`\`
### See Also
- [User object structure](#user-object)- [Authentication guide](./auth.md)- [updateUser()](#updateuser)Documentation Anti-Patterns
Section titled “Documentation Anti-Patterns”❌ “Just Read the Code”
Section titled “❌ “Just Read the Code””Code is documentation of how, not why. Developers need context, not just implementation.
❌ Everything in the README
Section titled “❌ Everything in the README”Your README is a billboard, not a manual. Link to detailed docs.
❌ Walls of Text
Section titled “❌ Walls of Text”Break up large paragraphs. Use subheadings. Add code examples.
❌ No Examples
Section titled “❌ No Examples”Theory without practice is useless. Every concept needs a working example.
❌ Assuming Expertise
Section titled “❌ Assuming Expertise”Write for the beginner, organize for the expert. Use progressive disclosure.
❌ No Search Functionality
Section titled “❌ No Search Functionality”If developers can’t find it, it doesn’t exist. Add search to your docs site.
❌ Broken Links and Examples
Section titled “❌ Broken Links and Examples”Maintain or remove. There’s no middle ground.
Tools for Better Documentation
Section titled “Tools for Better Documentation”Documentation Site Generators
Section titled “Documentation Site Generators”- Starlight (Astro) - Modern, fast, great DX
- Docusaurus (React) - Feature-rich, popular
- VitePress (Vue) - Simple, performant
- MkDocs (Python) - Clean, Material theme
Code Example Testing
Section titled “Code Example Testing”- Doctest - Python built-in
- doctest-ts - TypeScript examples
- markdown-doctest - Language agnostic
- CI/CD integration - Run examples in your pipeline
API Documentation
Section titled “API Documentation”- TypeDoc - TypeScript
- JSDoc - JavaScript
- rust-doc - Rust
- godoc - Go
- Sphinx - Python
Diagrams and Visuals
Section titled “Diagrams and Visuals”- Mermaid - Markdown-based diagrams
- Excalidraw - Hand-drawn style diagrams
- Carbon - Beautiful code screenshots
- Asciinema - Terminal recordings
Measuring Documentation Quality
Section titled “Measuring Documentation Quality”How do you know if your docs are good? Track these metrics:
- Time to First Success - How quickly can a new user complete getting started?
- Support Ticket Volume - Are docs answering common questions?
- Bounce Rate - Do people leave docs immediately?
- Search Analytics - What are people searching for (and not finding)?
- Feedback - Add “Was this helpful?” buttons
- Contribution Rate - Are developers fixing docs when they find issues?
The Documentation Culture
Section titled “The Documentation Culture”Great documentation isn’t a one-time effort—it’s a culture.
Make documentation part of your workflow:
- Require docs for all new features
- Review docs in PR reviews
- Celebrate documentation improvements
- Give contributors credit for doc fixes
- Schedule regular documentation sprints
- Make it easy to contribute (edit on GitHub links)
Your Action Plan
Section titled “Your Action Plan”This week, improve your documentation:
- ✅ Audit your getting started guide (can someone go from zero to working in 5 minutes?)
- 🧪 Test all code examples (set up automated testing)
- 📋 Create a documentation hierarchy (getting started → tutorials → how-tos → API ref)
- 🔍 Add search to your docs site
- 📊 Set up analytics to understand how people use your docs
- 🎯 Write one new how-to guide for a common use case
The Bottom Line
Section titled “The Bottom Line”Documentation is not an afterthought—it’s a core product feature. Developers judge your project by its docs before they judge it by its code.
Invest in documentation, and developers will invest in your project.
Need help improving your documentation? We specialize in developer experience and would love to help.