DocsGENERALSTAGE-SPECIFICILLUSTRATIVE

Reading Documentation With a Goal

Documentation is consulted, not read. Start from the goal, find the concept that owns it, read the smallest section that answers it, run the example, change the example until it breaks, then apply it to your problem — and stop reading the moment the next step is obvious.

The moveWorked exampleNext questions

The situation, the reflex, and why it stalls

Every lesson starts where being stuck starts: someone has a problem, and the first move that comes to mind feels like progress.

The question

The library you need has three hundred pages of documentation and you need one thing from it. How do you read enough — and only enough — to get that thing working in your own code?

The situation

The store needs to send an order confirmation email. The email provider's documentation has a Getting Started, an API reference, a guides section, a section on templates, one on webhooks and one on deliverability. You have read for an hour, you know what a "sending domain" is, and you still have not sent one email from your backend.

The reflex

Start at the top and read down. It feels responsible — you do not want to miss the part that matters — and the docs are organised in an order someone chose, so following it feels like the safe route to a complete picture before touching code.

Why it stalls

The hour produces vocabulary and no email. Reading in the author's order means reading about templates and deliverability before the one call that sends a message, because the author had to cover the general case and you have a specific one.

What the reflex produces — and fails to produce
  • The hour produces vocabulary and no email. Reading in the author's order means reading about templates and deliverability before the one call that sends a message, because the author had to cover the general case and you have a specific one.
  • Nothing read was tested, so nothing read was confirmed. Documentation describes what the library does under its assumptions; your environment, version and use case are not in the text, and the only way to find the gap is to run something.
  • The reading has no stopping rule. Without a goal that says "done", the docs are done when they end — and by then the section that mattered has been forgotten among the sections that did not.
  • The pull to switch to a tutorial grows every minute, and the tutorial that finally gets copied encodes its own decisions — its own error handling, its own retry policy — in place of yours.
ProblemUnderstandRequirementsConstraintsUnknownsDecompositionSmallest StepModelExperimentObserveDebugLearnIterate

The move

Precisely enough to apply it to a problem you have never seen — not a slogan.

  • Write the goal as a sentence about your system before opening the documentation: "when an order becomes paid, my backend sends one confirmation email to the customer, and I can tell whether it was accepted." The goal is the stopping rule; you are finished reading when that sentence is true in your code.
  • Find the concept the documentation uses for your goal. Every library has a vocabulary — message, transactional send, template, event — and the goal maps onto one or two of those words. Find them in the table of contents or the reference index, not by reading from page one.
  • Read the minimal section that owns that concept: the one page or reference entry that says what to call, what it needs and what it returns. Skip the sections whose titles do not appear in your goal; they are answers to questions you have not asked yet.
  • Run the example exactly as given, then modify it — change one input, remove one field, pass something wrong — until you can predict what it will do. Only then apply it to your problem. The example proves the docs match your environment; the modification proves you understand it rather than copied it (Explain It Back).

The loop, as a loop

The move is a small loop with a stopping rule, and the stopping rule is the difference between reading and consulting. Each step fails in a characteristic way, and the failure names the step that was skipped: an hour of reading with no email means the goal was never written; an example that works and code that does not means the example was never modified.

The steps are ordered by what they establish. The goal establishes what "done" means; the concept establishes where to look; the section establishes the contract; the example establishes that the contract holds in your environment; the modification establishes that you understand the contract; the application establishes that it solves your problem. Skipping a step means the later ones rest on an assumption.

Goal-driven reading
  1. 1
    Goal

    One sentence about your system with an observable result — the stopping rule.

    fails by Reading until the docs end, because nothing says when to stop.

  2. 2
    Concept

    The library's word for your goal, found in the index or table of contents.

    fails by Reading page one, where the author had to cover the general case.

  3. 3
    Minimal section

    The reference entry or guide page that owns the concept: what to call, what it needs, what it returns, what it does on failure.

    fails by Reading adjacent sections "to be safe" and forgetting the one that mattered.

  4. 4
    Run the example

    Exactly as given, in an empty file, with nothing of yours around it.

    fails by Pasting it into the store first, so an environment problem looks like a store problem.

  5. 5
    Modify the example

    Change inputs, remove fields, pass something invalid; predict before each run.

    fails by Skipping it — the example "works" and the first real input that differs is a surprise.

  6. 6
    Apply

    The call inside your code, plus the unanswered questions written down as unknowns.

    fails by Treating each unanswered question as a reason to go back and read more.

The loop is short on purpose. If a step takes more than a few attempts, the goal is probably wrong — too wide, or naming a concept the library does not have.

What modifying the example finds

The example is the documentation's claim that the contract holds; modifying it is your check. The modifications worth making are the ones that map onto questions your system will ask: what if a field is missing, what if the input is malformed, what if the credentials are wrong, what if it is called twice. Each one either confirms the documented behaviour or finds the gap between the page and your version.

The experiment below is the whole of it, in a file that has nothing to do with the store. It is deliberately boring: the interesting part is the predictions in the comments, written before each run.

The example, then three modifications with predictions
1// scratch/email-probe.ts — no store, no framework, one call
2const client = new EmailClient(process.env.EMAIL_TEST_KEY!)
3
4// 1. As documented. Predict: returns { id }.
5console.log(await client.send({ from: 'shop@example.test', to: 'a@example.test', subject: 'Order', text: 'Thanks' }))
6
7// 2. Missing subject. Predict: rejected before sending, error names the field.
8await client.send({ from: 'shop@example.test', to: 'a@example.test', text: 'Thanks' } as any).catch((e) => console.log('2:', e.code, e.message))
9
10// 3. Malformed recipient. Predict: rejected, different code from (2).
11await client.send({ from: 'shop@example.test', to: 'not-an-address', subject: 'Order', text: 'Thanks' }).catch((e) => console.log('3:', e.code))
12
13// 4. Same call twice. Predict: two ids — the provider does NOT dedupe; idempotency is mine.
14

The fourth probe is the one that changes the design: if the provider does not deduplicate, the order service must remember that it already sent, and that is a column on the order — found by modifying an example, not by reading the webhooks section.

One order of reading, and the order that replaces it

Reference before guide, run before read-on, modify before apply: that is one defensible order for a utility library with a narrow goal. It is not the order for a framework you are building on, and the device says so.

The tell for which order applies is whether the goal fits in one sentence about one call. "Send one email" does; "render the product page with server-side data loading" names a composition of several concepts, and for that the guide's conceptual overview comes first, because no single reference entry explains how the pieces fit.

Reading order for a narrow goal
  1. 1
    Write the goal sentence

    because It is the stopping rule; everything after it is judged by whether it makes the sentence true.

  2. 2
    Index or table of contents → the concept

    because The library's vocabulary decides where the answer lives, and the index is the shortest path to it.

  3. 3
    Reference entry for the call

    because The contract — arguments, return, errors — is what your code depends on; the surrounding guide is context you may not need.

  4. 4
    Run the example in isolation

    because It separates "the docs are wrong for my version" from "my code is wrong", which are debugged differently.

  5. 5
    Modify with predictions

    because Understanding is the ability to predict; the example running proves only the environment.

  6. 6
    Apply, and board the unanswered questions

    because The call goes into the store; the questions it raised go onto the unknowns board rather than back into the docs tonight.

a different valid order Overview-first: when the goal is a composition — a framework's routing plus data loading plus rendering — read the conceptual overview before any reference entry, because the entries only make sense against the model. You would choose this when the library is the foundation of the system rather than a utility called from one place, and when your goal sentence cannot name a single call.

How to do it

Most important first.

  • Before opening the docs, write the goal in one sentence about your system, with a verb and an observable result. If you cannot, you are not ready to read; you are ready to frame (Problem Framing).
  • Search the documentation for the nouns in your goal. Note which section owns each one; those two or three sections are your reading list.
  • Read the reference entry for the one call you need first, then the guide that surrounds it only if the entry left a question. Reference tells you the contract; guides tell you the story.
  • Run the smallest example from the section in an empty file — no store around it. If it does not run, the gap between the docs and your environment is the first thing to fix, and it is easier to see with nothing else present (The Smallest Executable Thing).
  • Change the example: a different input, a missing required field, an invalid key. Predict the outcome before each change (Prediction Before Execution). When your predictions are right, apply the call inside your own code.
  • Write down the questions the section raised and did not answer — "what happens if the provider is down?" — as unknowns, not as a reason to keep reading (Unknown to Specific Question).

Worked on a concrete problem

The move has to produce something. This is what it produced.

  • Goal: "when an order becomes paid, the backend sends one confirmation email and records whether the provider accepted it." Nouns: send, email, accepted. The docs call it a "transactional message"; the reference entry for the send call is one page. Templates, deliverability and webhooks are not in the goal, so they are not in the reading list.
  • The example sends a message with a from, a to, a subject and a body, and returns an id. Run in an empty file with the test API key: it returns an id. Modify: remove the subject — the call rejects it with a field name. Send to a malformed address — rejected before sending. Send with a wrong key — a different error class. Three predictions, three confirmations, and the error shapes are now known rather than assumed.
  • Apply: the order service calls send after the payment is confirmed and stores the returned id on the order. The unknown that surfaced — "the docs say accepted, not delivered; how would I know it was delivered?" — goes on the board as a question with an experiment (subscribe to one delivery event and log it), not as a reason to read the webhooks section tonight.
  • The same move on the payment provider's docs: the goal is "create a test-mode payment and learn who tells me it succeeded"; the concepts are payment intent and webhook; the reference entries are two pages; the example is run, broken and applied. The rest of the payment docs stay unread until a goal names them.

How you know it worked

What now exists that did not before, and what question you can now ask.

  • You can say, before opening the docs, what sentence about your system will be true when you close them.
  • The example ran in an empty file, and you broke it on purpose at least once and predicted the breakage.
  • The call exists in your code and you can explain each argument without the docs open.
  • A short list of unread sections exists, each attached to a question you might have later, rather than a feeling that you should have read more.

The questions you can now ask

The field this whole domain exists for. After this lesson, these are the questions to put to an unfamiliar problem.

Next questions
  • ?What sentence about my system will be true when I have finished reading?
  • ?What does this library call the thing I need, and which section owns that word?
  • ?What is the smallest example I can run with nothing else around it?
  • ?What would I change in the example to find out whether I understand it rather than copied it?
  • ?Which questions did the section raise that I am choosing not to answer today, and where have I written them down?

What can go wrong

How the move itself fails
  • The goal is written too narrowly and the reading stops too early: the send call works, but the docs' one warning — that the provider rate-limits and returns a retry hint — was in the paragraph after the example. The minimal section includes the notes attached to the call, not only the signature.
  • The example is run and never modified, so the first real input that differs from the example fails and the failure is a surprise. Running the example proves the environment; modifying it proves the understanding, and only the second one transfers.
  • The move is applied to a library that is the core of the system rather than a utility. If the store is being built *on* a framework, its mental model — routing, rendering, data loading — has to be understood as a whole, and goal-driven reading of a single call misses how the calls compose (Framework Independence).
  • Under-applied: the docs are skipped entirely in favour of an example found elsewhere, and the contract — what the call promises, what it does on failure — is never read at all (Before You Copy Code).
What the move costs
  • Goal-driven reading gives you exactly what you needed and nothing adjacent. The section you skipped may have held the constraint that shapes your design — you will meet it later, when it is more expensive.
  • Running and modifying the example costs time that reading does not; on a library you will use once for one call, reading the signature may be enough.
  • Reading the reference before the guide gives you the contract without the author's reasoning, and some libraries only make sense once the reasoning is known.
Misreads
  • "So never read the whole documentation." Read the whole thing when the library is the foundation of the system, or when you have used it for a month and want to find out what you have been doing wrong. The move is about the first contact, where the goal is narrow and the docs are wide.
  • "The example ran, so I understand it." The example running proves the environment matches the docs. Understanding is proven by predicting what a changed example does, and by being able to explain the call without the page open.
  • "Documentation is always the authoritative source." It is the authoritative statement of intent. The library's actual behaviour in your version is authoritative for what happens, and the example run is how you check the two agree (Evaluating What the Search Returned).

Where this applies

Problem-solving advice is stated as universal far more often than it is. These labels say what each method is specific to — and where CONTESTED appears, the note gives the strongest form of the opposing view.

  • GENERALGoal, concept, minimal section, run, modify, apply works for any library, API or tool whose documentation is organised by concept; it also works for a language's standard library and for a cloud service's reference.
  • STAGE-SPECIFICOn first contact the goal is narrow and the reading is minimal. Once the library is load-bearing in production, the reading list changes to the whole conceptual model, the limits page and the changelog, because the goal is now "know what this thing can do to me".
  • ILLUSTRATIVEThe email provider, its section names, the transactional-message vocabulary and the errors observed are invented to show the shape of the move; no real provider's documentation is being described.

Where the depth lives

This domain asks the question and hands the answer off by name.

Further
  • The manifesto's "What Are You Delegating?" cards at /manifesto/delegating: an email SDK handles the transport and the auth; whether a message was sent twice stays yours, and the docs will not say so unless you go looking.