Skip to content
All articles

The Documentation That Replaces the Handover Call

8 min read

Most project documentation is written for the wrong reader. It explains what the system does, which the code already says, and skips why it does it that way, which the code cannot say. The result is a README that answers questions nobody has and leaves every question a new developer actually asks unanswered.

The reader you're writing for is specific: someone competent who has never seen this codebase, on their first day, with nobody available to ask. That constraint is what makes it possible to know when you're finished. If that person can get it running, deploy a change, and understand why the weird part is weird, the document works. Everything else is optional.

I care about this more than most people because I've been on both ends of it as a contractor, and because "there's nobody to ask" is not hypothetical when the person who wrote the system left, or is twelve hours ahead, or is me a year later having forgotten all of it.

1. Running it, with the real commands

Start here, because if this fails nothing else gets read.

The exact commands, in order, copy-pasteable. Not "install dependencies and start the dev server" — the actual lines. Include the versions that matter: if it breaks on Node 20, say so, because the alternative is someone spending a morning on a stack trace that has nothing to do with the code.

Then the environment variables, and this is where most setup docs quietly fail. A list of names is not enough. Each one needs what it's for, where to get a value, and whether the app works without it. "RESEND_API_KEY — sending contact form mail. Get one from the Resend dashboard. Without it the form returns an error and logs a warning; everything else runs." Now someone can get started without a working key, and knows exactly which behaviour is missing.

Say what a successful start looks like, too. Which URL, and what should be on the screen. Otherwise the first uncertainty is "is it broken or is that it?"

2. Deploying, including how to undo it

How does code get to production. Is it a push to a branch, a manual step, a pipeline with an approval? What runs on the way — tests, migrations, a build? How long does it take, so someone knows when to start worrying?

Then the part that's almost always missing: how to roll back. Whoever needs that is having a bad day, under pressure, possibly at night, and reading carefully is not available to them. It should be findable in seconds and it should be explicit about what rolling back does not undo — a reverted deploy does not revert a database migration, and that sentence in the docs has saved projects.

3. The decisions that look wrong

This is the highest-value section and the one that only you can write.

Every codebase has parts that look like mistakes. A weird workaround, a library chosen over the obvious one, a function that does something in a roundabout way. Each is either a real mistake or a solution to a problem that isn't visible in the code — and a new developer cannot tell which.

So they do one of two things, both expensive. They "clean it up" and reintroduce the bug it was working around. Or they treat it as sacred, copy the pattern, and spread it.

A short register fixes this: what looks wrong, why it's like that, and what would have to change for it to be reconsidered. Three sentences each. "The order sync runs every fifteen minutes rather than on a webhook because the vendor's webhooks were dropping events in 2024. If they've fixed that, this can go."

The last clause is what makes it a living document instead of a monument. Without it, every documented oddity becomes permanent, because nobody feels authorised to remove something that was deliberately explained.

4. What breaks, and what to do

You already know the failure modes. Which integration flakes, which job backs up, what "the site is slow" usually turns out to mean.

Write down the three or four most common, each with the symptom as it will be reported — in the words a non-technical person will use — and the first thing to check. The symptom matters as much as the fix: someone searching your docs for "checkout is broken" should land on the entry, and they will not search for "Redis connection pool exhaustion".

This is the section that converts a two-hour investigation into a five-minute one, and it costs you an afternoon while the knowledge is still free.

5. Where things live

Not credentials — never credentials — but the map. Which hosting account, which DNS registrar, which email provider, which error tracker. Who administers each, and how someone gets access.

This is the section whose absence causes genuine emergencies. A project where nobody can work out who controls the DNS is a project one expiry away from being down with no path to fixing it.

Keep it in the repository

Documentation in a wiki, a shared drive or a ticketing system dies, reliably, because it's updated in a different place from the code and so it isn't.

In the repo it's part of the diff. A pull request that adds an environment variable can update the setup section in the same commit, a reviewer can see that it didn't, and the docs get read by whoever is already in the file. That proximity is doing most of the work — not discipline, just the fact that it's right there.

The same argument applies to comments explaining why a piece of code is unusual: put them next to the code, not in a document describing the code, because only one of those two things will still be true in a year.

Test it by watching someone use it

The only real test is to hand it to someone who hasn't seen the project and watch them follow it, in silence, without helping.

This is uncomfortable and it is the entire value of the exercise. Every point where they hesitate is a gap you cannot see yourself, because you know the answer and your eyes skip the step. Do not answer their questions during the run — write them down, let them get stuck, and fix the document afterwards.

Asking "is this clear?" instead does not work. They will say yes. They will say yes whether or not it's true, because they don't know what they don't know yet, and because you wrote it.

Why it's worth the time

The selfish version: everything you write down is a question you won't be interrupted by. If you work across time zones, an interruption isn't five minutes — it's a day of someone else's progress waiting on your morning.

The professional version: a system only one person can operate is a liability everywhere except in that person's job security, and clients notice which one you've optimised for. Being straightforward to replace is, counterintuitively, a strong reason to be kept.

And the honest version: the developer this actually saves is usually you, eighteen months later, looking at your own code with no memory of writing it and no idea why it's like that.