Auto Doc Updater
Keep documentation accurate, current, and in sync with the actual codebase.
Core Principle
Documentation drift is a bug. Treat outdated docs with the same severity as a broken test. Every meaningful code change should trigger a documentation review.
When to Update Docs (Triggers)
| Code Change | Docs to Update |
|---|---|
| New API endpoint/route | API reference, OpenAPI spec |
| New environment variable | .env.example, README setup section |
| New dependency | README prerequisites, package list |
| Breaking change | CHANGELOG, MIGRATION guide |
| New feature | README features list, user guide |
| Config schema change | Config docs, example configs |
| New CLI command/flag | CLI reference, --help text |
| Architecture change | Architecture diagram, ADR (Architecture Decision Record) |
| Deprecation | CHANGELOG, deprecation notice with timeline |
README Maintenance
Standard README Structure
# Project Name
One-line description.
## Features
- Feature 1
- Feature 2
## Quick Start
\`\`\`bash
git clone ...
pnpm install
pnpm dev
\`\`\`
## Prerequisites
- Node.js 20+
- PostgreSQL 16+
## Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| `DATABASE_URL` | Yes | PostgreSQL connection string |
## Project Structure
\`\`\`
src/
├── ...
\`\`\`
## Scripts
| Command | Description |
|---------|-------------|
| `pnpm dev` | Start dev server |
| `pnpm test` | Run tests |
## Contributing
See CONTRIBUTING.md
## License
MIT
README Audit Checklist
- Quick Start commands actually work on a fresh clone
- All required env vars are listed in
.env.example - Dependency versions in README match
package.json/Cargo.toml/pyproject.toml - Screenshots/GIFs are current (not showing old UI)
- Links are not broken (internal anchors, external URLs)
- Badges (build status, version, license) are accurate
CHANGELOG Maintenance
Keep a Changelog Format
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
### Added
- New `/api/export` endpoint for CSV export
### Changed
- Improved query performance for dashboard load
### Fixed
- Fixed timezone bug in date filters
## [1.3.0] - 2026-06-15
### Added
- Multi-tenant workspace support
- Passkey authentication
### Deprecated
- `/api/v1/users` — use `/api/v2/users` instead, removal in v2.0.0
### Security
- Patched RLS policy gap in `projects` table
Generating Changelog from Conventional Commits
# If using conventional commits (feat:, fix:, chore:, etc.)
npx conventional-changelog -p angular -i CHANGELOG.md -s
# Or use git-cliff (Rust-based, fast)
cargo install git-cliff
git-cliff --output CHANGELOG.md
# cliff.toml — git-cliff config
[git]
conventional_commits = true
filter_unconventional = false
[changelog]
header = "# Changelog\n\n"
body = """
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.message | upper_first }}
{% endfor %}
{% endfor %}\n
"""
API Documentation
OpenAPI/Swagger Sync (FastAPI auto-generates)
# FastAPI generates OpenAPI spec automatically from type hints
# Just ensure docstrings and response_model are accurate
@router.post(
"/posts",
response_model=PostResponse,
status_code=201,
summary="Create a new post",
description="Creates a post owned by the authenticated user. Requires `member` role or higher.",
responses={
401: {"description": "Not authenticated"},
403: {"description": "Insufficient permissions"},
422: {"description": "Validation error"},
},
)
async def create_post(data: PostCreate, user: User = Depends(get_current_user)):
...
# Auto-exposed at /docs (Swagger UI) and /redoc
TSDoc for TypeScript APIs
/**
* Creates a new post for the authenticated user.
*
* @param data - Post creation payload
* @param data.title - Post title (1-200 chars)
* @param data.content - Optional post body
* @returns The created post with generated ID
* @throws {ValidationError} If title is empty or exceeds 200 chars
* @throws {UnauthorizedError} If user is not authenticated
*
* @example
* ```ts
* const post = await createPost({ title: "Hello", content: "World" })
* ```
*/
export async function createPost(data: CreatePostInput): Promise<Post> {
// ...
}
# Generate docs site from TSDoc
npx typedoc --out docs src/index.ts
Architecture Decision Records (ADRs)
# docs/adr/0003-use-drizzle-over-prisma.md
# ADR 0003: Use Drizzle ORM over Prisma
## Status
Accepted
## Date
2026-06-10
## Context
We need a type-safe ORM for PostgreSQL. Prisma requires a separate query engine binary
and has slower cold starts on serverless. Drizzle generates SQL at build time with no
runtime engine.
## Decision
Use Drizzle ORM for all database access.
## Consequences
### Positive
- Faster cold starts on Vercel serverless functions
- SQL-like query builder is more transparent
- No binary/engine dependency
### Negative
- Smaller ecosystem than Prisma
- Migration tooling (drizzle-kit) is less mature
- Team needs to learn new query syntax
## Alternatives Considered
- Prisma: rejected due to cold start overhead
- Raw SQL with `pg`: rejected — loses type safety
Doc Sync Automation Script
// scripts/check-docs-sync.ts
import fs from "fs"
import path from "path"
function checkEnvVarsSynced() {
const envExample = fs.readFileSync(".env.example", "utf-8")
const envVarsInExample = new Set(
envExample.match(/^([A-Z_]+)=/gm)?.map(l => l.replace("=", "")) ?? []
)
// Scan source for process.env.X usage
const srcFiles = getAllFiles("src", [".ts", ".tsx"])
const envVarsInCode = new Set<string>()
for (const file of srcFiles) {
const content = fs.readFileSync(file, "utf-8")
const matches = content.matchAll(/process\.env\.([A-Z_]+)/g)
for (const match of matches) envVarsInCode.add(match[1])
}
const missing = [...envVarsInCode].filter(v => !envVarsInExample.has(v))
if (missing.length > 0) {
console.error("❌ Missing from .env.example:", missing)
process.exit(1)
}
console.log("✅ .env.example is in sync")
}
checkEnvVarsSynced()
# Run in CI to catch doc drift
- name: Check docs sync
run: npx tsx scripts/check-docs-sync.ts
Doc Review Checklist (Before Merging)
- README reflects any new setup steps
-
.env.examplehas all new environment variables - CHANGELOG has an entry under
[Unreleased] - API docs (OpenAPI/TSDoc) cover new/changed endpoints
- Breaking changes have a migration note
- Code comments explain why, not what (the code already shows what)
- Outdated screenshots/diagrams flagged for update
- No dead links introduced
Key Rules
- Doc updates are part of the PR, not a follow-up task — same commit/PR as the code change
- CHANGELOG
[Unreleased]section updated with every notable change .env.examplemust always match actual required env vars — verify in CI- ADRs for significant technical decisions — capture the "why," not just the "what"
- Auto-generate API docs from code (OpenAPI, TSDoc) — avoid hand-maintained duplicates
- Breaking changes need a migration guide, not just a changelog line
- Quick Start in README must work on a clean checkout — test it periodically
- Deprecations get a removal timeline — never silently remove without notice
- Link-check docs in CI — broken links are a doc bug
- Architecture diagrams updated when system boundaries change — not just code comments