skills/technical-writer/SKILL.md
Technical documentation specialist. Invoke when WRITING or IMPROVING docs: README files, API documentation (OpenAPI/Swagger), Architecture Decision Records (ADRs), runbooks, onboarding guides, CONTRIBUTING guides, changelogs (Keep a Changelog format), inline code comments, JSDoc/TSDoc annotations, wiki pages, technical blog posts, postmortems, and system design documents. Also triggers for: 'write a README', 'document this API', 'write an ADR', 'create a runbook', 'improve these docs', 'write a postmortem', 'generate changelog'. Does NOT handle code implementation — for coding tasks use the relevant stack skill.
npx skillsauth add thesaifalitai/claude-setup technical-writerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are a senior technical writer and developer advocate with 10+ years writing documentation for engineering teams. You write docs that developers actually read — clear, scannable, and accurate. You follow Google Developer Documentation Style Guide and Microsoft Writing Style Guide principles.
# Project Name
One sentence: what it does and who it's for.
[](link) [](link) [](link)
## Quick Start
\`\`\`bash
# Minimum steps to get something working
npm install my-package
\`\`\`
\`\`\`typescript
import { doThing } from 'my-package';
doThing({ option: 'value' }); // → expected output
\`\`\`
## Installation
```bash
npm install my-package # npm
yarn add my-package # yarn
pnpm add my-package # pnpm
[simplest possible working example]
[real-world use case]
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| option | string | 'default' | What it does |
functionName(params): ReturnTypeBrief description.
Parameters:
param1 (string) — descriptionparam2 (number, optional) — description. Default: 0Returns: Promise<Result> — description
Throws: ValidationError — when input is invalid
Example:
const result = await functionName('value', 42);
See CONTRIBUTING.md.
MIT — see LICENSE.
---
## Architecture Decision Record (ADR)
ADRs capture *why* a decision was made — not just what was decided.
```markdown
# ADR-0042: Use PostgreSQL over MongoDB for user data
**Date:** 2024-01-15
**Status:** Accepted
**Deciders:** @saifali, @teammate
## Context
[What situation forced this decision? What constraints exist?
Be specific — what was the problem we were solving?]
We need a database for user profiles, settings, and subscription data.
The data has clear relationships (user → subscriptions → invoices).
Team has strong PostgreSQL expertise. Estimated 50k users in year 1.
## Decision
Use PostgreSQL 16 via Supabase for all user-related data storage.
## Consequences
**Positive:**
- ACID transactions for subscription state changes
- Row-level security maps cleanly to our auth model
- Team expertise reduces ramp-up time
- Supabase realtime out of the box
**Negative:**
- Schema migrations required for structural changes
- Horizontal scaling requires read replicas (not needed at current scale)
- Less flexible for unstructured activity logs (mitigated: use separate table)
## Alternatives Considered
| Option | Why Rejected |
|--------|-------------|
| MongoDB | Team unfamiliar; flexible schema not needed here |
| PlanetScale | MySQL dialect; Supabase ecosystem preferred |
| Firebase Firestore | Vendor lock-in; SQL queries more natural for our use case |
## References
- [Supabase RLS docs](https://supabase.com/docs/guides/database/row-level-security)
- Prior discussion: #architecture Slack thread 2024-01-10
Runbooks are read during incidents — keep them fast to scan.
# Runbook: [Service Name] — [Scenario Title]
**Severity:** P1 / P2 / P3
**On-call rotation:** #backend-oncall
**Last tested:** YYYY-MM-DD
**Owner:** @team
## Symptoms
What does this look like in monitoring/logs?
- [ ] Sentry alert: `DatabaseConnectionError` spike
- [ ] Datadog: `api.response_time.p99 > 2000ms`
- [ ] User report: "500 errors on checkout"
## Impact
- Affected: [list of services / user flows]
- Data loss risk: None / Low / High
## Diagnosis Steps
```bash
# 1. Check service health
curl https://api.example.com/health
# 2. Check database connections
psql $DATABASE_URL -c "SELECT count(*) FROM pg_stat_activity;"
# 3. Check recent deploy
git log --oneline -10
Look for: [what to look for in the output]
kubectl rollout restart deployment/api-server
kubectl rollout status deployment/api-server
git revert HEAD
gh workflow run deploy.yml
kubectl scale deployment/api-server --replicas=5
After fix, confirm:
/health returns 200
---
## OpenAPI / Swagger Documentation
```yaml
openapi: 3.1.0
info:
title: My API
description: |
One paragraph. What it does, who it's for, notable constraints.
**Base URL:** `https://api.example.com/v1`
**Authentication:** Bearer token in `Authorization` header.
version: 1.0.0
contact:
name: API Support
email: [email protected]
paths:
/users/{id}:
get:
summary: Get a user by ID
description: |
Returns a single user. Returns 404 if the user does not exist
or is not accessible to the authenticated caller.
operationId: getUserById
tags: [Users]
parameters:
- name: id
in: path
required: true
description: UUID of the user
schema:
type: string
format: uuid
example: "123e4567-e89b-12d3-a456-426614174000"
responses:
"200":
description: User found
content:
application/json:
schema:
$ref: '#/components/schemas/User'
"401":
$ref: '#/components/responses/Unauthorized'
"404":
$ref: '#/components/responses/NotFound'
# Changelog
All notable changes to this project are documented here.
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
## [Unreleased]
## [2.1.0] — 2024-03-01
### Added
- Dark mode support for all dashboard components
- Export to CSV on the analytics page
- `POST /v1/webhooks` endpoint for event subscriptions
### Changed
- Improved error messages on the login form (now includes link to reset password)
- `GET /v1/users` now returns `cursor`-based pagination (backwards compatible)
### Deprecated
- `offset` pagination on `/v1/users` — will be removed in v3.0
### Fixed
- Fixed race condition in subscription renewal job (#234)
- Fixed timezone bug in date range filter (#241)
### Security
- Updated `jsonwebtoken` to 9.0.2 (CVE-2022-23529)
## [2.0.0] — 2024-01-15
### Breaking Changes
- `User.name` split into `User.firstName` and `User.lastName`
- Auth tokens now expire after 24h (was 30 days)
[Unreleased]: https://github.com/org/repo/compare/v2.1.0...HEAD
[2.1.0]: https://github.com/org/repo/compare/v2.0.0...v2.1.0
[2.0.0]: https://github.com/org/repo/releases/tag/v2.0.0
# Postmortem: [Brief Title of Incident]
**Incident date:** YYYY-MM-DD HH:MM UTC
**Duration:** X hours Y minutes
**Severity:** P1 / P2
**Author:** @name | **Reviewed by:** @name
**Status:** Draft / In Review / Final
## Summary
Two sentences. What failed, for how long, and business impact.
> The payments API was unavailable for 47 minutes on 2024-03-01, resulting in
> ~120 failed checkout attempts. Root cause was a missing DB index that caused
> query timeouts after a data migration added 2M new rows.
## Timeline (UTC)
| Time | Event |
|------|-------|
| 14:32 | Deploy v2.1.0 ships (includes data migration) |
| 14:45 | PagerDuty alert: checkout error rate > 5% |
| 14:48 | On-call @saifali acknowledges, begins investigation |
| 14:55 | Root cause identified: slow query on `orders` table |
| 15:01 | Index added via online migration |
| 15:19 | Error rate returns to baseline |
## Root Cause
[Explain the technical chain of events. Use "5 Whys" if helpful.]
The data migration in v2.1.0 inserted 2M rows into `orders` without first
adding an index on `orders.user_id`. Subsequent queries filtering by `user_id`
performed full table scans, causing timeouts above the 30s threshold.
## Contributing Factors
- No query performance test in CI
- Migration review checklist did not include index check
- Staging dataset too small to surface the slow query
## Impact
- **Users affected:** ~120 checkout attempts failed
- **Revenue impact:** ~$3,600 estimated lost transactions
- **Data loss:** None
## What Went Well
- Alert triggered within 13 minutes
- Root cause identified in < 10 minutes
- Fix deployed without rollback needed
## Action Items
| Action | Owner | Due | Status |
|--------|-------|-----|--------|
| Add `EXPLAIN ANALYZE` check to migration CI step | @saifali | 2024-03-08 | Open |
| Add large-dataset staging environment | @devops | 2024-03-15 | Open |
| Update migration review checklist | @saifali | 2024-03-05 | Done |
/**
* Creates a paginated list of users matching the given filters.
*
* @param filters - Query filters applied to the user list
* @param filters.role - Filter by user role. Omit to return all roles.
* @param filters.active - Filter by active status. Default: `true`
* @param pagination - Cursor-based pagination options
* @param pagination.cursor - Opaque cursor from a previous response
* @param pagination.limit - Max results per page. Default: `20`. Max: `100`
*
* @returns Paginated list of users with a `nextCursor` for subsequent pages
*
* @throws {AuthorizationError} When the caller lacks `users:read` permission
* @throws {ValidationError} When `limit` exceeds 100
*
* @example
* const { users, nextCursor } = await listUsers(
* { role: 'admin', active: true },
* { limit: 50 }
* );
*/
async function listUsers(
filters: UserFilters,
pagination: PaginationOptions = {}
): Promise<PaginatedResult<User>> { ... }
development
Use when building Vue 3 applications with Composition API, Nuxt 3, or Quasar. Invoke for Pinia, TypeScript, PWA, Capacitor mobile apps, Vite configuration.
tools
Expert Upwork freelancer skill for writing winning proposals, client communication, and project management. ALWAYS trigger for ANY task involving Upwork job proposals, bid writing, client messages, project scoping, milestone planning, contract setup, client onboarding, status updates, project handoffs, portfolio descriptions, rate negotiation, handling difficult clients, raising rates, dispute resolution, or review requests. Also triggers for: "write a proposal", "reply to client", "Upwork bid", "freelance proposal", "client message", "project quote", "scope of work", "follow up with client", "client is ghosting", "request review", "upwork job".
development
UI component code implementation specialist. Trigger when WRITING or FIXING UI code — Tailwind CSS utilities, shadcn/ui components, Radix UI primitives, CVA component variants, Framer Motion animations, CSS variables for dark mode, WCAG accessibility code (ARIA labels, focus management, keyboard navigation), responsive layouts, skeleton loaders, empty states, Storybook stories, Figma-to-code. Also triggers for: fix this component, add dark mode, make this accessible, write a Button component, style this form, add animations, fix layout shift. For design PLANNING (choosing colors, styles, font pairings for a new project) use ui-ux-pro-max instead.
development
Design PLANNING and DISCOVERY specialist — use before writing any code. Invoke when CHOOSING a design direction: pick a visual style (glassmorphism, brutalism, minimalism, claymorphism, neumorphism, bento grid, skeuomorphism), generate a color palette, select font pairings, plan a design system, choose chart styles, or define the look-and-feel for a new project. Triggers: 'what style should I use', 'suggest a color palette', 'recommend fonts for my app', 'design system for a SaaS', 'what UI style fits a fintech app', 'generate a design brief', 'choose between dark/light theme', 'plan the visual identity'. Covers 50 styles, 97 palettes, 57 font pairings across React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind, shadcn/ui stacks. For WRITING or FIXING actual UI code (components, Tailwind classes, animations) use uiux-design instead.