Every project needs a README
Eight months away makes you a stranger to your own repo. Day one is the only day you can still see what's confusing.
In September a client I built a site for two years ago emailed to ask if I could change a phone number in the footer. 15 minutes of work, obviously, and I said yes without checking anything, because it’s a phone number.
It took a day.
Not the phone number. The phone number took 90 seconds once I got there. The day was: which repo is this, which branch is live, why does the build fail, what version of Node did this want, why is the grunt task erroring, is there a build step at all or do I edit the compiled file, where is this hosted, is there a deploy script or did I FTP it, and is the thing currently on the server even the thing in this repo.
Every one of those questions had a short answer. I knew all of them in 2015. I knew none of them in September, and the person best placed to have written them down was me, and I hadn’t.
The gap makes you a stranger
The thing I’ve come round to is that a README isn’t for other people, or it isn’t mainly. Other people are a bonus.
It’s for you, after a gap long enough that the project has left your head. And that gap is much shorter than anyone thinks. Mine seems to be about eight weeks for the details and six months for anything structural, and agency work is practically designed to produce those gaps, because you finish, you go and do four other things, and then a retainer ticket arrives.
A README isn't for other people. It's for you, after a gap long enough that the project has left your head, and that gap is much shorter than anyone thinks.
So the audience is a specific, real person who is competent, has built this exact thing, and remembers nothing. That’s a much easier person to write for than “a developer,” and it changes what you put in.
Commands first, prose later
The order matters more than the content, because the file gets skimmed and never read. Commands first, prose later. I’ve settled on this shape and it fits on one screen for most projects.
How to run it. The literal commands, in order, copy-pasteable, starting from a clean clone. Not “install dependencies,” but the actual line. If it needs a specific version of something, say the version, and if the tooling can pin it then pin it and mention the file.
## Running it locally
nvm use # reads .nvmrc, this project is on 6.x and will not build on 8
npm install
npm start # localhost:3000, watches scss and js
Requires PHP 5.6 and MySQL locally. There's a Vagrantfile if you'd rather.
How to deploy it, and where it goes. Which branch is production, what the deploy actually is, and where the site lives. This is the one that cost me the most in September. “It’s on the client’s own hosting, deploy is a push to master and the hook pulls” is one sentence and would have saved me two hours of poking at a server.
Where the content comes from. Which CMS, where the admin is, and which parts of the site are editable versus hardcoded. Every client site has a line somewhere between those two and nobody can ever remember where it is.
The weird bit. Every project has one. The thing that will make you say “what on earth” when you find it. Write it down and it stops being a landmine.
Who to call. The client’s technical contact, the hosting company, whoever owns the domain, and the person who has the DNS login. That last one has held up more launches for me than any code.
What it is, in two sentences. Last, because you don’t need it and the next person only needs it once.
The section nobody writes
The above is all mechanics and it’s the easy half. The half I keep failing to write is why anything is the way it is.
Why the CSS build has that odd extra step. Why the contact form posts to a different endpoint than everything else. Why there’s a hardcoded redirect for one URL that looks like a mistake but is actually super important because the client printed it on 50,000 leaflets in 2014.
Those are the decisions that look like bugs to a stranger, and the stranger is you, and the cost of not writing them down isn’t confusion, it’s that you fix them. You remove the weird redirect because it’s obviously wrong, and six months later somebody notices the leaflets.
I’ve started keeping a “decisions” heading at the bottom with dated one-liners under it. Not a document, not a process, just a list I append to when I do something that will look wrong later. It takes 20 seconds and it’s the only part of the file that has ever made me feel clever.
Day one is the only day you can see it
Here’s the part I’d most like to convince someone of.
The README has to be written at the start, before you understand the project, because that’s the only time you can see what’s confusing about it. On day one every awkward step is visible, because you’re stubbing your toe on all of them. By week three you’ve absorbed them. You no longer notice that the build needs an env var that isn’t in any example file, because you set it once and your shell remembers.
Expertise is exactly the thing that makes you unable to write this. So write it while you’re still ignorant, badly, and add to it as you go.
What doesn’t belong
Anything that duplicates the code, because it will drift and then it’s worse than nothing. A list of every function, a directory tree, a description of what each Sass partial contains. The code already says that and the README will be wrong within a month.
A changelog, unless something actually generates it.
And anything aspirational. “We plan to move this to a static build.” No you don’t. That sentence has been in three READMEs I’ve inherited and none of those sites were ever moved.
Twenty minutes, again
20 minutes at the start of a project, at the point where you’re enthusiastic and nothing has gone wrong yet. Which is the same 20 minutes I asked for at the start of the year for the browser support matrix, and it’s the same argument, and I notice I keep writing versions of this post.
The version of you who needs it will not thank you, because they won’t know they were about to lose a day. That’s the deal, unfortunately 🥲