Write the README first
The oldest trick in the book, still the best design tool available, and almost nobody does it.
Before you write the code, write the README. Not a stub. The real one — the one you would ship, with the install instructions, the first example, and the section explaining what it does not do.
You will throw most of it away. That is fine. The value is in what happens while you write it.
what it forces#
A name for the thing. If you cannot name it in one sentence, you do not know what it is. "A library for X" where X is three clauses joined by "and" is three libraries.
A first example that fits on a screen. This is the brutal one. Write the code a new user types first. If it needs eleven lines of setup before anything happens, your API is wrong, and you found out before you built it rather than after.
# if this is your example, stop and redesign
client = Client(config=Config(
auth=AuthProvider(strategy=Strategy.OAUTH, ...),
transport=Transport(pool=Pool(size=10), retry=RetryPolicy(...)),
serializer=JsonSerializer(...),
))
result = client.get_resource(ResourceRequest(id=ResourceId("x")))# if this is your example, you are probably fine
client = Client(api_key=key)
result = client.get("x")An explicit list of non-goals. Every project has them and most only discover them in a GitHub issue eighteen months later when someone asks for a feature that would break the design. Writing them down early is the cheapest scope control that exists.
Error cases described in prose. "If the token is expired, X happens." Writing that sentence often reveals that you have not decided what X is, and the decision is much cheaper now.
why it works better than a design doc#
Design documents are written for reviewers. READMEs are written for users. The audience difference changes everything.
A design doc rewards completeness, so it grows sections about alternatives considered and migration strategies and rollout phases, and by page six nobody including the author is thinking about the interface anymore.
A README rewards clarity from the outside. It cannot contain your internal rationale, because users do not care. It can only contain what the thing does and how to use it, which is exactly the part that is expensive to change later.
the internal-service version#
This works for services too, and possibly better.
Write the endpoint documentation before the endpoint. Write the example request and the example response. Write the error codes and what each one means.
Then send it to the team that will consume it — before you build anything. The feedback you get in that thread is worth more than any amount of code review after the fact, because at that point changing the interface is free.
Half the API design mistakes I have watched happen were mistakes that the consuming team would have caught in ninety seconds if anyone had shown them the shape first.
the objection#
"I do not know what it does yet, that is why I am building it."
Sometimes true. Exploratory work where the shape is genuinely unknown should be exploratory, and forcing a README onto it is cargo cult.
But be honest about which mode you are in. Most of the time you do know roughly what it does, and "I will figure out the interface as I go" means "I will discover the interface from whatever was convenient to implement," which is how you end up with a function that takes eleven positional booleans.
the actual test#
When you finish, read the README as if you had never seen the project.
If your reaction is "I do not understand what problem this solves," you have learned something enormously valuable for the cost of twenty minutes and no code.
That is the best exchange rate in software.
— Dom, July 5, 2025