Good documentation is crucial for team success. This comprehensive guide covers best practices for creating and maintaining technical documentation.
Types of Documentation
Documentation Pyramid
flowchart TD
A[API Reference] --> B[Code Examples]
B --> C[Guides & Tutorials]
C --> D[Conceptual Docs]
D --> E[Architecture]
A -.- F[Code First]
E -.- G[Start Here]
style A fill:#e3f2fd
style B fill:#bbdefb
style C fill:#90caf9
style D fill:#64b5f6
style E fill:#42a5f5
README Files
Project README
# Project Name
Brief description of what this project does.
## Features
- Feature 1
- Feature 2
- Feature 3
## Quick Start
npm install my-project npm start
## Installation
npm install my-project
## Usage
import { myFunction } from ‘my-project’;
const result = myFunction(‘hello’); console.log(result);
## API
### myFunction(input)
| Parameter | Type | Description |
|-----------|------|--------------|
| input | string | Input description |
Returns: `string`
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Submit a pull request
## License
MIT
Component README
# Button Component
A button component with multiple variants.
## Usage
import { Button } from ‘./components/Button’;
function App() { return ( <Button variant=“primary” onClick={() => {}}> Click Me ); }
## Props
| Prop | Type | Default | Description |
|------|------|---------|--------------|
| variant | 'primary' \\| 'secondary' | 'primary' | Button style |
| size | 'sm' \\| 'md' \\| 'lg' | 'md' | Button size |
| disabled | boolean | false | Disabled state |
| onClick | () => void | - | Click handler |
## Examples
### Primary Button
### Secondary Button
## Accessibility
- Keyboard navigable
- ARIA labels included
- Focus indicators
Architectural Decision Records (ADRs)
ADR Template
# ADR-001: Use PostgreSQL as Primary Database
## Status
Accepted
## Context
We need to choose a primary database for our application. Options include:
- PostgreSQL
- MySQL
- MongoDB
## Decision
We will use PostgreSQL.
## Consequences
### Positive
- Strong ACID compliance
- Excellent JSON support
- Great ecosystem
- Strong community
### Negative
- Requires more setup than SQLite
- Horizontal scaling needs more work
## Notes
- Reviewed on: 2024-01-15
- Last updated: 2024-02-01
ADR Index
# Architectural Decision Records (ADR)
| ADR | Title | Status | Date |
|-----|-------|--------|------|
| 001 | Use PostgreSQL | Accepted | 2024-01-15 |
| 002 | Use React | Accepted | 2024-01-20 |
| 003 | Use GraphQL | Proposed | 2024-02-01 |
| 004 | Use AWS | Accepted | 2024-02-05 |
Code Comments
Good Comments
// Calculate discount based on user tier
// Users with 10+ orders get 20% off
function calculateDiscount(user) {
if (user.orderCount >= 10) {
return 0.20;
}
return 0;
}
// Handle API rate limiting
// Exponential backoff: 1s, 2s, 4s, 8s...
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fetch(url);
} catch (error) {
if (i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000);
}
}
}
JSDoc Comments
/**
* Calculates the total price including tax and discounts.
*
* @param {number} basePrice - The original price before tax/discount
* @param {Object} options - Calculation options
* @param {number} options.taxRate - Tax rate as decimal (0.1 = 10%)
* @param {number} [options.discount=0] - Discount as decimal
* @returns {number} Final calculated price
*
* @example
* calculateTotal(100, { taxRate: 0.1, discount: 0.1 }); // 99
*
* @since 1.2.0
* @deprecated Use calculatePrice instead
*/
function calculateTotal(basePrice, options) {
const { taxRate, discount = 0 } = options;
return basePrice * (1 + taxRate) * (1 - discount);
}
TypeScript Documentation
interface User {
/** Unique identifier */
id: string;
/** User's display name */
name: string;
/** Email address */
email: string;
/** When user was created */
readonly createdAt: Date;
}
/**
* Creates a new user in the system.
*
* @param data - User creation data
* @returns Created user with generated ID
* @throws {ValidationError} When data is invalid
*
* @example
* const user = await createUser({
* name: 'John',
* email: '[email protected]'
* });
*/
async function createUser(data: CreateUserInput): Promise<User>
API Documentation
OpenAPI/Swagger
openapi: 3.0.0
info:
title: User API
version: 1.0.0
paths:
/users:
get:
summary: List users
parameters:
- name: page
in: query
schema:
type: integer
default: 1
- name: limit
in: query
schema:
type: integer
default: 20
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
pagination:
$ref: '#/components/schemas/Pagination'
components:
schemas:
User:
type: object
properties:
id:
type: string
name:
type: string
email:
type: string
format: email
Gitbook/MkDocs
Structure
docs/
├── index.md
├── getting-started/
│ ├── installation.md
│ ├── quick-start.md
│ └── configuration.md
├── guides/
│ ├── authentication.md
│ ├── deployment.md
│ └── troubleshooting.md
├── api/
│ ├── users.md
│ └── orders.md
└── reference/
├── cli-commands.md
└── environment-variables.md
Navigation (mkdocs.yml)
nav:
- Home: index.md
- Getting Started:
- Installation: getting-started/installation.md
- Quick Start: getting-started/quick-start.md
- Guides:
- Authentication: guides/authentication.md
- Deployment: guides/deployment.md
- API Reference:
- Users: api/users.md
- CLI:
- Commands: reference/cli-commands.md
Writing Style
Be Clear and Concise
<!-- Bad -->
The functionality of this method is to iterate through the array and return the first element that matches the predicate.
<!-- Good -->
Returns the first array element that matches the predicate.
Use Examples
<!-- Good with example -->
To create a user:
const user = await createUser({ name: ‘John’, email: ‘[email protected]’ });
### Include Context
Use process.env.NODE_ENV to check the environment:
development: Local developmentstaging: Testing environmentproduction: Live environment
## Tools
### Documentation Generators
| Tool | Description |
|------|-------------|
| JSDoc | Generates API docs from code |
| Docusaurus | React-based documentation |
| GitBook | Collaborative docs |
| MkDocs | Python-based, Markdown |
| Starlight | Astro-based docs |
### JSDoc Example
// jsdoc.json { “source”: { “include”: [“src”] }, “opts”: { “destination”: “./docs”, “template”: “node_modules/docdash” }, “plugins”: [“plugins/markdown”] }
## Maintenance
### Review Checklist
Documentation Review
- All public APIs documented
- Code examples tested
- Links work
- Spelling/grammar correct
- Diagrams up-to-date
- Version numbers current
- Examples run without errors
### Automation
.github/workflows/docs.yml
name: Documentation
on: push: branches: [main] paths: [‘docs/**’]
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: ‘3.11’ - run: pip install mkdocs-material - run: mkdocs gh-deploy –force
## External Resources
- [Write the Docs](https://www.writethedocs.org/)
- [Google Developer Documentation Style Guide](https://developers.google.com/style)
- [Docusaurus](https://docusaurus.io/)
- [MkDocs](https://www.mkdocs.org/)
## Conclusion
Good documentation:
- Is clear and concise
- Includes practical examples
- Stays up-to-date
- Is easy to navigate
- Answers common questions
Invest in documentation - it saves time in the long run.
Comments