You can write brilliant code that nobody can use because the documentation is impenetrable. Or you can write average code with excellent docs that becomes everyone’s go-to solution.

Documentation is a multiplier. These principles help you write docs that work.

Know Your Audience

Different readers need different docs:

Tutorials (learning-oriented): “Follow these steps to build X”

  • For newcomers
  • Hand-holding is okay
  • Complete, working examples
  • Progressive complexity

How-to Guides (task-oriented): “How to do X”

  • For users with specific goals
  • Assume basic familiarity
  • Direct and practical
  • Problem → solution format

Reference (information-oriented): “X works like this”

  • For experienced users
  • Complete and accurate
  • Consistent structure
  • Searchable

Explanation (understanding-oriented): “Why X works this way”

  • For curious users
  • Background and context
  • Design decisions
  • Trade-offs discussed

Start with the Problem

Don’t start with your solution. Start with what the reader is trying to do:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
❌ Bad:
# MyLib API

MyLib uses a functional composition pattern with monadic 
error handling to provide type-safe data transformations.

✅ Good:
# MyLib: Transform Data Without the Boilerplate

Transform arrays, objects, and async data with a simple, 
chainable API. No more nested loops or try-catch blocks.

```javascript
// Before: 15 lines of error-prone code
// After:
const result = transform(data)
  .filter(isValid)
  .map(normalize)
  .get();
#E`TT`c}aa#v`hh`o)wwe`BeGe`nc};aaSrmaojsaFiSihyad`o`atctmitetor:cdcvhtarcwcka:aacelxscoc,odccsl::StlnlnohhciiidiDcweere{3zceeoen``in6eancnnppt0:ltat'toot0l.l.tpp=,'glgntt1heeJeiin0itrtueooe0t(e(sdnnwms't'tsb/u/eeA'turuTannP,hsnseaaIeeselcbb(rrloll{AscsdeeP'a'essCMI)c)aa;h;errcxexeehidassemmppurpoofm2e2lnno0smessrc0ps:eeamo1csncchsaaheeccohhusiirinnzgge:withconfigurableTTL.
#E``c#x``oa`B`nCmmajIsopadantplr:viyekatc-sdsilPocaiaswrleshniintopzteutel=RdtehnaweedowyrcklMiyweChnletinencto(pYiOeUdR_dAiPrIe_cKtElYy):;

✅ Good:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import { MyClient } from 'mylib';

const client = new MyClient({
  apiKey: process.env.MY_API_KEY,
  // Optional: customize timeout
  timeout: 5000,
});

// Verify connection
const status = await client.ping();
console.log(status); // { ok: true, latency: 42 }
I#D`#G`nn#o`#e`pcn`t`mlP'mQburtauraidoriusnegkcnhsrvdkntieeoiamsrwSnlpswntgloiharverimteltnysml.D.3ii0bUsSsctselaeorcrstoeunarsdleisim:sptliec,vaadlduecso.mpSlheoxwiteyx:pectedoutput.
1
2
import { process } from 'mylib';
const result = process(data);

Configuration

Customize behavior with options:

1
2
3
4
const result = process(data, {
  strict: true,
  format: 'json',
});

Advanced Usage

For complex scenarios, use the streaming API…

#D`##T`t}}#o`##h`rc`#r`yaci}EumEojwafrmarAwa{atcrerrunvic(oonkotathenrtdrhwsrRsosehcc(reoDwwnerleoflohntniirrrecaipere.utcttnoisemahtrnhregte.)srnoictyoteoAo{aorasnPnnu(tEIncr'iwreeIorrkcoAnnooetfPvnry(Iag)Al,i;ukistednhyoieAtnnaPvttIjaiulcdksiaaetdtsyih:woob'hrno,aEaterrexrdrgpo.roireoer)xrsea.d{mmr.peilsgesh.atcg:oem);

Common causes:

  • API key copied incorrectly (check for trailing spaces)
  • Key expired (keys expire after 90 days)
  • Wrong environment (staging key used in production)
#D`#`n#e`#`pv``mSemIbtlanairorssnupkthscedattrolauswllrnalestcimfaoyonnlr,ibStchaenynidnogn'treadlinearly:

Basic Usage

1
2
import { MyLib } from 'mylib';
const lib = new MyLib();

API Reference

process(data, options)

Transform input data according to rules.

Parameters:

NameTypeRequiredDescription
dataObjectYesInput data to process
options.strictbooleanNoEnable strict validation

Returns: ProcessedData

Throws: ValidationError if data is invalid

U#O`d}s#u`e)et`si};KdjIct)heaanr(ce;eetvi'oxapeaybQnpddsoeuCseeEcu(iotcrxdrr'cptsaoiDkyr(,mcpto-erpstecSpsetlsutausaeatmaslubsrerttllesnteteUut=)spwiaef.,dottxrptareiaoroctsommoBoeenpceddldeDeteeosehxcsfbaaws(ilnmodnopraecnlktdkoesa(ss')),d',;;o,acanssd:ynb=cu>ll{et=>po{ints.Wallsoftextgetskipped.

Test your examples in CI. Broken examples break trust.

People find docs through search. Include terms they’ll search for:

1
2
3
4
# Handling Timeouts

When requests take too long (timeout errors, ETIMEDOUT, 
request timeout), use the `timeout` option:

Think: “What would I search for if I had this problem?”

Version Your Docs

Docs for v2 shouldn’t confuse v1 users:

docs/vvl12a//teggseetttttiinnggv--2ssttaarrtteedd..mmdd

Or use version selectors in your doc site.

The README Formula

A good README follows this pattern:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Project Name

One-sentence description of what it does.

## Features

- Feature 1
- Feature 2
- Feature 3

## Installation

```bash
npm install project-name

Quick Start

1
// Minimal working example

Documentation

Link to full docs.

Contributing

How to contribute.

License

MIT

##DW##orciW*****T*****utrASPSAoMDJVMmeicerhvoaoSaeettceoolrcDlrntiiosriskuoemthnvnetddscaaegednoa*ittsjwuT:didSpeanry*ootoetnr*upP*ncyiretg*ser:slcsneo:/DoieeosnnVosDsy*nec*Uiceio***e*nt*aau:**s:ie*lg::*vP:irpw"*OernariT"":rreAtmoshYTssPisdheohBdasInuuirel*gacefsef,*dstxucai:o.inacknvccscnreeFsoItteurodteicapisrfedoottirhnnecodoawfsownomshrimh-ceegapecucuntulnomosurfenedeyreixytneron.lortsus.eeuoa."xlt(wX"pmlide"nlueoernoasdnvenotnteotasllt"tuioe"Tistpa"UhoeeerXsinsrnessisiirt)nssw,gi.rcliealtFtnuucstrcrounoelrenavedfteiesdbgeyuapvrretefolh.iboe.llp.eeef""mrussnc(itunincodlneu"rdsitnagndfiuntguryeouyroucowdiel)l,baendgriattenfeueld.smaintenance(updateswithcodechanges).