Vanya Agnesandra

Perfect Documentation

This page is a work in progress. I might change it up. We shall see.


Perfect documentation:

  1. Answers exactly the question that I came to ask of it
  2. Answers it with perfect accuracy
  3. Answers it instantly
  4. Never goes out of date

Understandably, checking all these boxes is somewhat rare - but I posit that perfect docs do exist.

The key to finding them lies in the word “instantly”. These aren’t docs you dig for, can google, can open with a command, or are even already open (npm readme’s) - They’re already in your head.

  1. Your understanding of a project guides your thought process. We don’t think of these thoughts as questions, because we already know the answers.
  2. Not everything you know has perfect accuracy - but at least some things are correct.
  3. You don’t even have to open your eyes to “read” it.
  4. Not going out of date is trickier, but still applies:
    • There are things you know that won’t go out of date
    • There are things you know about $project@v1 that won’t go out of date - breaking changes would necessarily create an @v2

There is one giant caveat here - humans are squishy. It can be difficult to distinguish things that I know from things that I “kinda know”. As humans, we tend to have some confidence in our knowledge. There might be things we are absolutely sure of, and things we are shaky on.

If I am uncertain of some fact, then that knowledge is no longer “perfect documentation” (and arguably never was), and so I will go find some docs to “refresh”.

Perfect documentation is a mental model that you build in your user’s minds.

Writing perfect documentation

You cannot write perfect documentation. It is, by definition, not written. You must build it.

Building Perfect Documentation

The first step to any writing (or in this case, building) project is to Know your Target Audience.

It’s so important that I’m going to make it a header.

Know your Target Audience

What can we say about your user?

If you are writing a networking library for rust, then you can assume your user wants to do some networking, knows at least some rust, and they probably have the rust toolchain installed. (I have seen too many npm packages tell me to install node).

If your user is reading your file, they are either on a package library or your repo source, and probably want to do one of four things:

  1. Evaluate your package to see if it does what they need (they need a list of features, or a description of capabilities)
  2. Install your package (they need installation instructions)
  3. Start using your package (they need a getting started guide)
  4. Solve a problem they ran into, and this was the first google result (they need links to more docs)

You will see the pattern above over and over and over again in popular projects. Let me re-iterate the 4 goals:

  1. Description of capabilities (Does it do what I want?)
  2. Installation (It does what I want - how do I get it?)
  3. Getting Started (I got it - how do I use it?)
  4. Reference Docs / Advanced Usage Guides

Let’s look at Rust’s serialize-deserialize (serde) package:

Serde uses the 4 goals

Serde has all 4 goals on their homepage - without even needing to scroll. You will see this everywhere, because large, successful projects know their target audience.

When you know your target audience - not just for your project, but for each page you create, you can anticipate what information they are likely looking for.

Now, because perfect docs are hard to build, we must decide where to make an attempt, and where to stick with traditional methods.

Concepts vs Reference Material

The second step to building perfect docs is deciding when to give up - and you should give up early. Don’t rely on your users memories too much - remember, humans are squishy.

Things your users would have to memorize should not be memorized. They won’t do it. Give them a reference sheet instead. If the do manage to memorize it, it’s tribal knowledge / institutional knowledge.

Things your users can understand are much more likely to be general, un-changing concepts, and are better candidates for perfect documentation.


When you learn a list of things - say you’re looking at a list of function signatures - we call that memorization. This is hard. I might memorize the operators of a data query language; but it takes a while - I’ll learn one or two operators a day, as I need them.

I don’t want to memorize things. I would much rather remember how to get to a reference sheet - then I only have to remember one thing.

Without dozens of hours of work or years of exposure, things that would need to be memorized can’t be perfect documentation. Your users are going to forget it. This is reference material.


When you learn a system of things - how assorted parts work together - we call that understanding. It’s typically pretty easy. Wastewater goes to the sewer, then (hopefully) to the wastewater treatment plant, which takes in dirty water and outputs clean water. We don’t know all the intricate details of this process, but we do understand a “high-level” (or “low-resolution”) overview of what’s going on.

It’s easy because the pieces are connected. We are building a model, and integrating new knowledge into what already exists. Sometimes this is even fun. This can be perfect documentation - but it is also reference material.

Everything is Reference Material

This is where you should start - publish reference material for everything. Make process flow diagrams, lists of module members, and render tables of contents. The only problem is that, no matter how well this is done, I might not know what I’m looking for. That’s what understanding is for.

Writing for Understanding is Writing for Perfect Documentation

When you’re ready, take the overarching concepts and explain them in clear language. Optimize for clarity and understanding. It doesn’t need to be concise - it needs to be clear.

When a user wants API schema docs, they don’t actually want API schema docs. They want to make an API call, and finding the docs is an obstacle; a necessary sidetrack, to enable their true goal. The docs need to be findable, fast, and readable / searchable, fast.

When a user wants to understand, that is the goal - they are reading for understanding. You don’t need to be fast - you need to help them understand, with whatever length that takes to accomplish.

I don’t have anything new to say when it comes to writing tips. Check out the wonderful Plain Language Guidelines - if you read that, you’re ready to write better than 90% of people.

Your writing can’t be perfect, but if it’s good enough, a users understanding can be.

“Now wait just a gosh-darn second - that’s only like 4% of my information that “can” be perfect, and only if the end user can get it through their thick skull (they can’t). What about the rest? Can’t we get almost perfect?” - you, probably

Almost-Perfect Documentation

Let’s re-visit the heuristics of documentation:

  1. Answers my question
  2. Answers accurately and completely
  3. Answers quickly

(I have removed “Never goes out of date” - this is a feature of perfect docs, but here falls under accuracy.)

All three of those points are important, but answering the question is the most important. The answer only needs to be good enough, and I only need to find it before I get impatient.

(That being said - answering incorrectly is worse than not at all, and if the answer isn’t discoverable, it might as well not exist. You do need all three features.)

If you have any interaction with your community at all, you know what questions often come up. You know what use-case you’re trying to solve (I hope. If you don’t, go fix that immediately, or your project will flounder and fail). What we tend to struggle with is access speed.

Access Trees

First, split your information by target audience.

Every Project has at least two Target Audiences

  1. Users, who will consume your project
    • Users may come with multiple different end goals. Think of the CSV format - do you want to parse it, or serialize to it?
  2. Contributors, who will work on your project.
    • This includes you!

This second group is often (completely) neglected. Think about your style guides, contributor guides, issue templates, pull request processes, enumerations of teams for different tasks - this all also needs to be written down and discoverable.

Second, split your information by the goal that audience might have. Ways to accomplish that goal can be sections on a page.

Let’s look at hypothetical example, from a project near and dear to my heart:

- How it Works
  - Nodes and RPC
  - Routing
  - DHT
  - Block Storage
  - Bootstrapping
- Use Veilid in Your App
  - Typescript / WASM
  - Python Bindings
- Contribute
  - Code of Conduct
  - Getting Started
  - Making a MR
- Run a Node
  - #Debian
  - #Arch
  - #$Distro

Veilid is a networking project, with 3 distinct target audiences.

  1. Application Developers want to use it as a library, to use its network in their app. (Use Veilid in Your App)
  2. Contributors want to contribute to the project, work on it, make it better. (Contribute)
  3. Network Contributors“ may or may not overlap with another group. These users just want to run the software standalone. (Run a Node)

Note the first (and most important) section - “How it Works” - comes first. It is the understanding layer, that is integral to the first two audiences (And hopefully at least interesting to the third). Because it is a common resource across audiences, (and is important, it doesn’t need this justification (but has it anyway)), it gets its own section.

Remember that writing for understanding optimizes for clarity and understanding; everything else is reference material that optimizes for efficiency. Remember too that everything is reference material - The “RPC” explainer from the “How it Works” section will also be represented as an “RPC Message” reference sheet and “RPC Message Schema” reference sheet. (Or more likely, links to the source code that define them.)

Users can classify themselves by audience and goal. By splitting information like this, any new (or longtime) user is two clicks away from highly-relevant content.

(There is irony talking about navigation and content organization here, as my blog has no navbar)

One last thing - we do need to be careful, because some of our heuristics can go negative.

Evil Documentation

Zero documentation is hard to come by. I can typically go read the code if I really have to, or experiment with the product and see what it does - but I would like to read docs first, if they exist.

Evil documentation is documentation that is wrong. It soaks up your time, makes you wonder where you went astray, and is infinitely frustrating. It’s worse than reading source code, because it takes away the time that could be spent reading said code.

This is why clarity, and building the correct understanding, is so important to perfect documentation - twists and turns could make it evil.

Any correct docs are better than no docs. Incorrect docs are much much worse.

This took me longer than I thought it would to write. I’ve barely done any editing. It’s gonna need a few passes. Let me know if I missed something / should restate something. Thanks!
- Vanya A

Feedback from Valued Readers

Email me! ${Your favorite chip dip} [at] (I get the catchall :P)

You fool, all you’ve done is re-invent learning things“ - Winston

“Write gooder, don’t write badder” how unfathomably wise“ - Marge

Write docs so your users understand them - isn’t that the whole fucking point?“ - drAke