--- name: technical-documentation description: Use when writing a README, documenting an API with OpenAPI, drafting a runbook for on-call engineers, authoring a technical spec or ADR, or setting up docs-as-code with auto-deploy to GitHub Pages. --- # Technical Documentation Good technical documentation reduces onboarding time, prevents repeated questions, and makes systems maintainable by people who didn't build them. ## When to Activate - Writing a README for a new project or service - Documenting an API with OpenAPI/Swagger - Writing a runbook for an on-call engineer - Creating an onboarding guide for a team - Documenting a significant technical decision (ADR) - Setting up documentation-as-code with auto-deploy to GitHub Pages ## README Structure A README is the front door to your project — it answers "what is this and how do I use it?" in under 5 minutes. ```markdown # service-name [![CI](https://github.com/org/repo/actions/workflows/ci.yml/badge.svg)](...) [![Coverage](https://codecov.io/gh/org/repo/badge.svg)](...) One-sentence description of what this service does. ## Prerequisites - Python 3.12+ / Node.js 20+ / Go 1.22+ - Docker 24+ - PostgreSQL 16 (or `docker compose up db`) ## Quickstart \```bash git clone https://github.com/org/service-name cd service-name cp .env.example .env # fill in required values docker compose up -d db # start dependencies make install # install dependencies make dev # start dev server on :8000 \``` ## Configuration | Variable | Required | Default | Description | |----------|----------|---------|-------------| | `DATABASE_URL` | Yes | — | PostgreSQL connection string | | `JWT_SECRET` | Yes | — | 32-byte secret for JWT signing | | `LOG_LEVEL` | No | `INFO` | Log verbosity (DEBUG/INFO/WARN/ERROR) | | `PORT` | No | `8000` | HTTP server port | ## Development \```bash make test # run unit + integration tests make lint # run linters make typecheck # run type checker make build # build production artifact \``` See [docs/development.md](docs/development.md) for detailed setup, running locally, and debugging. ## Deployment This service is deployed via GitHub Actions. See [docs/deployment.md](docs/deployment.md). ## Contributing 1. Fork the repo and create a branch: `feat/your-feature` 2. Make changes, write tests 3. Open a PR — the CI must be green before review See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide. ## License MIT — see [LICENSE](LICENSE) ``` ### README Anti-Patterns - Wall of text with no headings — add structure - "Works on my machine" setup steps — use Docker or make targets - Outdated screenshots — use text commands instead - Missing prerequisites — list every external dependency - No copy-paste quickstart — someone must be able to run it in 3 commands ## OpenAPI / Swagger OpenAPI 3.x is the standard for documenting REST APIs. Write it by hand (spec-first) or generate from code annotations. ### Basic Structure ```yaml openapi: 3.1.0 info: title: Payment Service API version: 1.0.0 description: | Processes payments and manages payment methods. ## Authentication All endpoints require a Bearer token in the `Authorization` header. servers: - url: https://api.example.com/v1 description: Production - url: https://staging-api.example.com/v1 description: Staging security: - BearerAuth: [] paths: /payments: post: operationId: createPayment summary: Create a payment tags: [Payments] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreatePaymentRequest' example: amount: 10000 currency: USD source: tok_visa responses: '201': description: Payment created content: application/json: schema: $ref: '#/components/schemas/Payment' '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' /payments/{id}: get: operationId: getPayment summary: Get a payment by ID tags: [Payments] parameters: - $ref: '#/components/parameters/PaymentId' responses: '200': description: Payment found content: application/json: schema: $ref: '#/components/schemas/Payment' '404': $ref: '#/components/responses/NotFound' components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT parameters: PaymentId: name: id in: path required: true schema: type: string format: uuid description: Payment identifier schemas: CreatePaymentRequest: type: object required: [amount, currency, source] properties: amount: type: integer description: Amount in smallest currency unit (cents for USD) example: 10000 minimum: 1 currency: type: string enum: [USD, EUR, GBP] example: USD source: type: string description: Stripe payment method token example: tok_visa Payment: type: object properties: id: type: string format: uuid amount: type: integer currency: type: string status: type: string enum: [pending, succeeded, failed] created_at: type: string format: date-time Error: type: object required: [code, message] properties: code: type: string example: VALIDATION_ERROR message: type: string example: amount must be greater than 0 details: type: array items: type: object responses: ValidationError: description: Request validation failed content: application/json: schema: $ref: '#/components/schemas/Error' Unauthorized: description: Missing or invalid authentication content: application/json: schema: $ref: '#/components/schemas/Error' NotFound: description: Resource not found content: application/json: schema: $ref: '#/components/schemas/Error' ``` ### `$ref` Reuse Rules - Define all reusable schemas in `components/schemas` - Define reusable responses in `components/responses` - Define reusable parameters in `components/parameters` - Never duplicate a schema — use `$ref` everywhere it appears ### Tooling | Tool | Purpose | |------|---------| | Swagger UI | Interactive API browser, served locally or hosted | | Redoc | Clean read-only API docs, good for public docs | | Stoplight Elements | Embeddable, modern OpenAPI renderer | | `openapi-generator` | Generate client SDKs from spec | | `prism` | Mock server from OpenAPI spec | ## Runbook Writing See `incident-response` skill for the full runbook template. Key principles: - **Write for the 3am engineer** — no tribal knowledge, no assumed context - **Number every step** — so the engineer can say "I'm stuck on step 4" - **Include expected output** — show what success looks like for each step - **Copy-paste commands** — no `` placeholders in commands - **Decision branches** — "if X, do Y; otherwise do Z" - **Keep runbooks current** — update after every incident that required improvisation ## Architecture Decision Records (ADRs) ADRs document *why* a significant decision was made — not just what was decided. Future engineers need context, not just conclusions. See `system-design` skill for the full ADR template and lifecycle. ### When to Write an ADR - Choosing a database or message queue technology - Adopting a new framework or library with significant lock-in - Changing authentication mechanism - Moving from monolith to microservices (or vice versa) - Adopting a new infrastructure pattern (Kubernetes, serverless) - Any decision that would surprise a new team member ### Conventions ``` docs/ └── adr/ ├── 0001-use-postgresql-for-primary-store.md ├── 0002-use-kafka-for-event-streaming.md └── 0003-adopt-opentelemetry-for-tracing.md ``` - Number sequentially, never renumber - Superseded ADRs stay — add "Superseded by ADR-0012" to the status - Store in-repo alongside code — ADRs are code ## Technical Spec Template Write a spec when the feature is large enough to need design alignment before implementation (> 1 sprint, or involves multiple services). ```markdown # Technical Spec: [Feature Name] **Status:** Draft | In Review | Accepted | Implemented **Author:** [name] **Last updated:** YYYY-MM-DD **Related:** [Jira/Linear ticket], [ADR-XXXX] ## Problem [1–3 paragraphs: what problem are we solving? Why now? What happens if we don't?] ## Proposed Solution [Describe the solution at a level where another engineer can implement it. Include: API contracts, data model changes, component interactions, migration plan.] ### API Changes [List new or modified endpoints with request/response shapes] ### Data Model [Schema changes, new tables, index additions] ### Component Diagram [ASCII or Mermaid diagram showing how components interact] ## Alternatives Considered | Option | Pros | Cons | Reason not chosen | |--------|------|------|------------------| | ... | ... | ... | ... | ## Implementation Plan 1. [ ] Phase 1: ... 2. [ ] Phase 2: ... 3. [ ] Phase 3: ... ## Risks and Mitigations | Risk | Likelihood | Impact | Mitigation | |------|-----------|--------|-----------| | ... | ... | ... | ... | ## Open Questions | Question | Owner | Due | |----------|-------|-----| | ... | ... | ... | ## Stakeholder Sign-off - [ ] Engineering lead: @name - [ ] Product: @name - [ ] Security (if auth/data): @name ``` ## Documentation as Code Keep docs alongside code in the same repository. Auto-deploy to GitHub Pages on merge. ### Tool Comparison | Tool | Language | Best for | Config | |------|----------|---------|--------| | MkDocs + Material | Python | Technical docs, clean theme | `mkdocs.yml` | | Docusaurus | Node/React | Developer portals, versioned docs | `docusaurus.config.js` | | mdBook | Rust | Books, guides (no JS required) | `book.toml` | | VitePress | Vue | Fast, modern Vue-based docs | `vitepress.config.ts` | ### MkDocs Example ```yaml # mkdocs.yml site_name: Payment Service Docs theme: name: material features: - navigation.tabs - search.suggest nav: - Home: index.md - API Reference: api.md - Runbooks: - Overview: runbooks/index.md - High Error Rate: runbooks/high-error-rate.md - ADRs: adr/index.md plugins: - search - git-revision-date-localized ``` ### GitHub Actions — Auto-deploy Docs ```yaml name: Deploy Docs on: push: branches: [main] paths: ['docs/**', 'mkdocs.yml'] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # for git-revision-date plugin - uses: actions/setup-python@v5 with: python-version: '3.12' cache: pip - run: pip install mkdocs-material mkdocs-git-revision-date-localized-plugin - run: mkdocs gh-deploy --force ``` > See also: `api-design`, `system-design`, `incident-response` ## Red Flags - **README with only "git clone && npm install"** — a quickstart without prerequisites (runtime version, env vars, required services) fails for every new developer; list every dependency - **OpenAPI spec written after the API is built** — spec-first forces design conversations before code is committed; spec-after just documents the implementation's accidents - **`$ref` components duplicated across paths** — duplicate schemas diverge silently; extract all reusable types to `components/schemas` and `$ref` them everywhere - **Runbooks written during an incident** — runbooks drafted under pressure are incomplete and inaccurate; write them during calm periods with a junior engineer as the target reader - **Documentation in a wiki separate from the code** — wikis go stale because they're not in the PR; docs that live alongside code get updated with the feature or the PR doesn't merge - **ADRs without the rejected alternatives** — a decision without context will be relitigated; always record what was considered and why each option was rejected - **Tech spec signed off by a single engineer** — one reviewer misses concerns from other domains; require sign-off from security, ops, and data disciplines for anything touching shared infrastructure ## Checklist - [ ] README has prerequisites, copy-paste quickstart (≤ 3 commands), and config reference - [ ] All environment variables documented with type, required flag, and description - [ ] OpenAPI spec covers all public endpoints with request/response schemas - [ ] All `$ref` components defined in `components/` — no duplicated schemas - [ ] API error responses have consistent schema (`code` + `message` + optional `details`) - [ ] Runbooks written for every production alert — no tribal-knowledge steps - [ ] ADR written for every significant technology or architecture decision - [ ] Tech spec written and signed off before implementing features > 1 sprint - [ ] Docs live in-repo alongside code (not in a separate wiki that goes stale) - [ ] Docs auto-deploy to GitHub Pages on merge to main