TS-25: Technical Documentation
Documentation is a love letter to your future self.
– Julio Biason
This technical standard covers what documentation a software project should have, where it should live, who it is for, and how it stays trustworthy over time.
This technical standard is concerned with the informational architecture and lifecycle of documentation, not with sentence-level writing style. For how to write – voice, formatting, terminology, citations, and other prose-level conventions that apply within any individual document – see TS-26: Technical Writing Style Guide.
- Location
- Types of documentation
- Audience
- README conventions
- API documentation
- Diagrams
- Changelogs
- Descriptive versus prescriptive
- Process documentation
- Ownership and staleness
- When not to document
- Scope
- Principles
- Docs as code
- Discoverability and addressability
- Ordering and completeness
- Accessibility
- UX writing
- Support-driven documentation
- Documentation tooling
- References
Location
Out-of-band documentation tends to become stale by the time you need it. Code-level documentation — inline comments, API specifications generated from code, and READMEs maintained alongside the source — tends to stay accurate because it lives close to the code. When the code changes, this kind of documentation is naturally updated alongside it. Therefore, prefer communicative code with inline documentation wherever practical.
Literate programming is an approach in which code and explanatory prose are woven together, so that a program reads as a narrative that explains what the code does and why. Rather than adding occasional comments to annotate code, the intent is for the code and its documentation to form a single, coherent artifact.
In practice, this philosophy encourages rich, meaningful inline comments that go beyond restating what the code does, and instead explain context, rationale, and intent.
See TS-7: Code Design for more detailed guidance on code comments.
Types of documentation
"Documentation" is not one artifact but several, each with a different audience, lifespan, and update trigger. Conflating them leads to READMEs that try to be architecture docs, or architecture docs that go stale because nobody realized they were supposed to be living alongside a specific piece of code.
At minimum, distinguish between:
- Reference documentation. Describes what the system is: READMEs, API references, configuration options. Kept in sync with code, updated on every change that affects the described surface.
- Architecture and design documentation. Explains how major components fit together and why. Updated when the architecture changes, not on every commit.
- Process documentation. Records point-in-time decisions (ADRs, RFCs, design docs). Immutable once written.
- Operational documentation. Runbooks, incident playbooks, deployment guides. Written for on-call engineers under time pressure. Prioritize scan-ability over prose.
- Onboarding documentation. Oriented at newcomers who lack context that existing contributors take for granted. Higher tolerance for explaining "obvious" things.
- Historical documentation. Changelogs and release notes.
Each type SHOULD live in a predictable, discoverable location, and it SHOULD be obvious from its location and format which type it is, since that signals to the reader how current and authoritative it is.
Audience
Documentation SHOULD be written for a specific reader, not for readers in general. Before writing, identify who the document is for:
- Maintainers. Contributors who work on the codebase. They need enough context to change it safely: architecture, invariants, gotchas. They tolerate technical depth and internal jargon.
- Consumers. Developers using the software as a dependency, library, or API. They need to know the public surface and how to use it correctly. They should not need to understand internals.
- Operators. People running or supporting the software in production. They need operational procedures, not implementation detail.
- Newcomers. Readers who lack the shared context that existing contributors take for granted. Onboarding material should make fewer assumptions than reference documentation aimed at maintainers.
Mixing audiences in one document tends to under-serve all of them. A README that documents both public usage and internal implementation forces consumers to wade through detail they don’t need, and hides the usage information operators are actually looking for.
Where a document must serve more than one audience, structure it so each audience can find its section without reading the rest.
README conventions
The README is usually the first, and often the only, document a reader will open. It SHOULD orient a new reader quickly rather than attempt to be a complete reference.
At minimum, a README SHOULD cover:
- Purpose. What the project is and what problem it solves, in one or two sentences.
- Status. Whether the project is actively maintained, experimental, or deprecated, if that isn’t obvious from context.
- Setup. The minimum steps to get the project running locally.
- Usage. The most common operations a reader will want to perform, with runnable examples. See TS-26: Technical Writing Style Guide for conventions on formatting commands and code blocks.
- Links to deeper documentation. Architecture docs, API references, contribution guides – rather than inlining that material into the README itself.
A README SHOULD NOT duplicate content that is better maintained elsewhere, such as full API documentation or a complete changelog. Link to those instead. Duplication creates two places that can drift out of sync, and a README that grows too long stops serving its purpose as a quick orientation point.
API documentation
Where practical, API documentation SHOULD be generated from the code itself. For example, an OpenAPI specification generated from route and type definitions, or reference docs generated from typed function signatures and docstrings, rather than hand-written and maintained separately.
This is the literate programming principle applied to interfaces. Documentation generated from the source cannot drift from the source, because it is the source, rendered.
Where generation isn’t practical, eg. documenting a third-party API, or a protocol rather than a code interface, hand-written API documentation SHOULD still describe the interface as it currently behaves, not as it was designed to behave.
At minimum, API documentation SHOULD specify, per operation: inputs (including required versus optional, and types), outputs, error conditions, and any side effects that aren’t obvious from the operation’s name.
Diagrams
A diagram is warranted when a structure or flow is easier to understand visually than as prose: component boundaries, data flow, state machines, sequence of calls across systems. A diagram is not warranted merely to break up a wall of text, and it should not be the only place a piece of information is recorded. Accompany it with prose for readers who need to search the text or who consume the document with assistive technology.
Prefer diagrams defined as code (for example, Mermaid or PlantUML) over opaque image files (PNG, JPEG exported from a drawing tool). Text-based diagrams:
- Live alongside the code and are versioned in the same commits.
- Can be reviewed as a diff, so changes to the diagram are visible in code review.
- Don’t require proprietary or specialized software to edit.
Where an opaque image format is unavoidable (for example, a screenshot), keep the source file that generated it, if one exists, so the image can be regenerated after a UI change rather than manually re-captured and re-cropped.
Changelogs
A changelog is the one form of documentation that is explicitly historical rather than descriptive of the current state. It exists to tell a reader what changed between versions, not what the system currently does.
Where a project maintains a changelog, it SHOULD follow the Keep a Changelog conventions: entries grouped by release, releases in reverse-chronological order, changes categorized as Added, Changed, Deprecated, Removed, Fixed, or Security.
Changelog entries SHOULD be written for the consumer of the software, not for the contributor who made the change. Describe the user-visible effect of a change, not the implementation. Prefer "the API now returns 429 on rate-limit" over "add rate limiting middleware."
Where commit history and pull request titles are already structured and user-legible (for example, via Conventional Commits), a changelog MAY be generated automatically rather than hand-maintained.
Descriptive versus prescriptive
Documentation SHOULD describe the current state of the software, not future aspirations or intentions. Documentation written before implementation quickly drifts from reality as plans change and code evolves.
To stay accurate, documentation SHOULD follow implementation rather than precede it – though there will be plenty of valid exceptions to this rule, such as proposals for software requirements specifications.
Process documentation
Architectural decision records (ADRs), RFCs, design docs, and similar artifacts can provide useful context about why certain technical decisions were made.
However, they describe a point-in-time understanding of the system and should be treated as historical records rather than current documentation. They are not authoritative sources of truth about how the system currently works — only the source code is.
Ownership and staleness
Documentation without an owner tends to rot silently, because no one notices when it drifts from the system it describes and no one is accountable for fixing it.
Reference documentation (READMEs, API docs, architecture docs) SHOULD be owned by whoever owns the code it describes, and updated in the same change that changes the described behavior. A pull request that changes an API’s behavior without updating its documentation SHOULD be treated as incomplete, in the same way a pull request that changes behavior without updating its tests would be.
Where documentation cannot reasonably be kept current – because it describes a system no one maintains, or a decision that predates the current team – mark it explicitly as historical rather than leaving readers to guess.
Prefer documentation whose staleness is self-evident (generated from code, or dated and clearly historical) over documentation whose staleness is silent (hand-maintained prose with no indication of when it was last true).
When not to document
Not everything needs a separate document. A document that merely restates what the code already makes obvious adds a second thing to keep in sync for no reader benefit.
Before creating a new document, consider whether the same information would be better expressed as:
- Self-documenting code (clear naming, small functions, obvious structure) requiring no separate explanation.
- A code comment, if the context is local to a single function or module.
- A type signature or schema, if the information is structural (shape of data, valid states).
- A test, if the information is a worked example of expected behavior – tests are documentation that is verified to stay correct.
Create a standalone document when the information is broader than any single piece of code, needs to be read before the code is (onboarding, architecture overview), or needs to persist independently of the current implementation (process documentation, changelogs).
Scope
Each document MUST be focused on a single, narrow, specific topic.
A document that tries to cover multiple topics becomes harder to navigate, harder to keep accurate, and harder to link to. Readers arriving via a search result or a cross-reference want the answer to one question, not a document they must skim in full to extract the relevant section. Narrow documents can be read in one sitting, updated in isolation without touching unrelated content, and referenced precisely — as a link to a specific file rather than a link to a heading buried partway down a long page.
Signs that a document has outgrown its scope include:
- The title includes the words "and" or "or".
- You need to write a list in the introduction to describe what it covers.
- Sections within it could each stand alone as a useful search result.
- Updating one part of the document regularly requires re-reading or re-validating unrelated parts, to check they are still consistent with the change.
- Contributors are unsure which section to update for a given change, or add new information to whichever section happens to be nearby, rather than to the section it logically belongs to.
When a document grows to cover more than one topic, split it. Extract each distinct topic into its own file, and link between them, rather than nesting increasingly specific subsections inside a single, ever-growing page.
This mirrors how this technical standards collection is itself organized. Each standard is a directory of small, single-topic files included into one index, rather than one large file per standard.
A narrow document is not the same as a short one. A single narrow topic may still require considerable depth and length to document thoroughly. The constraint is on breadth of subject matter, not word count.
Principles
The following principles describe what makes documentation good, independent of what it documents or where it lives. They apply to content, to the sources that content is stored in, and to the publications that deliver it to readers.
Content
Content — the conceptual information within documentation — SHOULD be:
- ARID — Accept (some) Repetition In Documentation. The DRY principle does not transfer cleanly from code to prose. Some business logic described by the code MUST be described again in the documentation, because the best documentation is hand-written rather than generated. Minimize repetition, but accept that some is inevitable.
- Skimmable. Structure content so readers can identify and skip concepts they already understand or that are irrelevant to their immediate question. Use descriptive headings, link text that describes its target (never "click here" or "this page"), and paragraphs and list items that lead with the key concept.
- Exemplary. Include examples and tutorials for the most common use cases. Many readers look at examples first. But do not attempt to example everything — too many examples reduce skimmability, and tutorials and reference material SHOULD be separated so each can be scanned independently.
- Consistent. Use consistent language and formatting. The more editors a body of documentation has, the more a style guide matters for maintaining consistency. See TS-26: Technical Writing Style Guide.
- Current. Incorrect documentation is worse than missing documentation, because it misleads with authority. Keep documentation up to date with the software it describes. Prefer version-agnostic content that needs less maintenance, and accommodate readers who remain on older versions of the software.
Sources
A source is a system used to store and edit content — text files in a version control repository, content in a CMS database, help text in application strings, code comments assembled into generated docs. Sources SHOULD be:
- Nearby. Store sources as close as possible to the code they document, so that documentation changes can be made alongside code changes in the same workflow. This is the foundation of docs-as-code.
- Unique. Eliminate content overlap between separate sources. Storing content in different sources is acceptable provided the scope of each source is clearly defined and disjoint. The goal is to prevent parallel maintenance — or worse, lack of maintenance — of the same information across multiple sources.
Publications
A publication is a single, cohesive artifact that readers use to consume
documentation — an API reference, a man page, --help output, an online
tutorial, an internal engineering manual. Multiple publications may be produced
from a single source. Each publication SHOULD be:
- Discoverable. Funnel users towards the documentation through all the likely pathways they might take to look for it. Documentation need not exist in every place a reader might look, but pointers to it should.
- Addressable. Provide addresses that link directly to content at a granular level, so that readers can bookmark, share, and reference specific sections. The more granular and easier to access, the better.
- Cumulative. Order content so prerequisite concepts come first. A reader who arrives with partial knowledge and begins reading partway through should be able to rewind to earlier content to fill gaps, not hit unexplained terms.
- Complete. Within each publication, cover the concepts it describes in full, or not at all. A map that shows fifty of one hundred fire hydrants is worse than one that shows none. If partial coverage is unavoidable, state it explicitly up front so readers are not misled.
- Beautiful. Visual style should be intentional and aesthetically pleasing. Even text-only documentation has visual style in its spacing and capitalization. Aesthetics are not important to every reader, but some will struggle to find comfort in documentation that ignores them.
Body
A body is the collection of all the publications within a software project and its sub-projects. A documentation body SHOULD be:
- Comprehensive. Together, all the publications in the body SHOULD be able to answer all the questions a user is likely to have. Satisfying every obscure question is unattainable, but a body that answers unlikely questions while failing to answer likely ones is out of balance.
Docs as code
Docs as code is the practice of treating documentation with the same tools and workflows as source code: authoring in plain-text markup, storing in version control, reviewing through pull requests, and building and publishing through CI. The goal is to merge the workflows for development and documentation so that documentation changes are made alongside the code changes they describe, by the same people, in the same review loop.
Docs as code is the methodology behind the Nearby source principle (see Principles). It is RECOMMENDED for any project where the documentation and the software it describes change together.
A docs-as-code workflow typically includes:
- Documentation authored in a lightweight markup language — Markdown, AsciiDoc, or reStructuredText — rather than a binary format or a proprietary CMS. See TS-27: Markdown and TS-28: AsciiDoc.
- Documentation stored in the same version control repository as the source code, or in a repository that shares the same review and release workflow.
- Documentation changes reviewed through the same pull-request process as code changes, so that documentation is subject to the same scrutiny and the same approval gates.
- Documentation built and published automatically by CI on merge, so that the published documentation always reflects the current state of the repository.
- Documentation tested where practical — link checking, linting, and validation of markup and cross-references — as part of the CI pipeline, so that broken documentation fails the build just as broken code does.
DocOps extends docs as code further by applying DevOps practices — automation, monitoring, and continuous delivery — to the documentation pipeline. The distinction is one of degree: docs as code brings documentation into the development workflow; DocOps brings it into the operations workflow too.
Discoverability and addressability
Documentation that cannot be found might as well not exist, and documentation that cannot be pointed at precisely cannot be discussed. These two properties are concerns of the publication, not the prose.
Discoverability
Documentation SHOULD be discoverable from every place a reader is likely to look for it:
- The project’s README SHOULD link to the main documentation entry point.
- The project’s website, package registry page, and repository description SHOULD link to the documentation.
- CLI tools SHOULD print a pointer to their documentation in
--helpoutput. - API surfaces SHOULD link from generated reference to narrative documentation and vice versa.
- Error messages and logs MAY link directly to the relevant troubleshooting page.
The documentation need not live in all of these places. The goal is that no matter where a reader starts, they find a pointer to the documentation within one or two steps.
Addressability
Documentation SHOULD be addressable at a granular level, so that readers can link to a specific section rather than a top-level page. This means:
- Every section heading SHOULD be a link target.
- Published documentation SHOULD provide stable URLs that do not break when content is reorganized.
- Deep links SHOULD survive version changes where possible, so that old links resolve to the current equivalent rather than 404.
Granular addressability lets readers bookmark, share, and reference exact passages — in bug reports, pull requests, support tickets, and conversations — which in turn keeps the documentation at the center of the work rather than beside it.
Ordering and completeness
Cumulative ordering
Content within a publication SHOULD be ordered so that prerequisite concepts come before the concepts that depend on them. A reader who follows the documentation linearly from start to finish SHOULD not encounter a term or concept that has not yet been introduced.
Perfect cumulative ordering is not always possible, especially in reference documentation that is consulted non-linearly. But it SHOULD be the goal in tutorials, onboarding material, and any content a reader is expected to read in sequence. Where tutorials and reference are separated, tutorials come first.
The goal is not to force linear consumption — most readers skip around — but to help a reader who arrives with partial knowledge narrow their search. A reader who starts at the 25% mark and gets confused should be able to rewind to earlier content, not find that the prerequisites were never written down.
Completeness
Within each publication, the concepts it covers SHOULD be covered in full, or not at all. A document that describes fifty of one hundred configuration options is worse than one that describes none, because a reader will assume the missing fifty do not exist.
Completeness is scoped to what the document sets out to cover. A man page for
iconv that documents all the command-line options but none of the supported
character encodings — instead pointing the reader to iconv -l for the list —
is complete, because the encodings are a separate publication.
Where partial coverage is unavoidable, the document MUST state it explicitly and up front, so that readers are not misled into treating the absence of information as the absence of the thing itself.
Accessibility
Documentation SHOULD be accessible to readers with disabilities, including readers who use screen readers, readers who need magnification or high-contrast color schemes, and readers who navigate by keyboard rather than a pointing device. Accessibility is a property of the publication, not just the prose.
Markup and structure
Use semantic markup so that assistive technology can navigate the document’s structure:
- Use heading levels in order (
h1,h2,h3) to convey the document outline. Do not skip levels for visual effect. - Use lists and tables for list-like and tabular content, not as layout tools.
- In AsciiDoc and Markdown, prefer the structural syntax (headings, list markers, table syntax) over raw HTML, so that the published output inherits the correct semantics.
Images and diagrams
- Every image and diagram MUST have alternative text that conveys the same
information a sighted reader would get. For simple images, a short
altattribute is enough. For complex diagrams, provide a longer text equivalent alongside the image. - Do not rely on color alone to convey meaning in diagrams. Use labels, patterns, or shapes as well, so that the diagram is legible to readers who cannot distinguish the colors.
- See Diagrams for diagram-specific guidance.
Links and navigation
- Link text SHOULD describe its target. Avoid "click here" or "this page" — these are inaccessible to screen-reader users who navigate by link lists.
- Provide a skip-to-content link or equivalent where the publication has a repeated navigation header.
Readability
- Ensure sufficient color contrast between text and background. Dark gray on light gray may look elegant and fail WCAG contrast minimums.
- Do not set fixed font sizes that override the reader’s preferences. Let the reader scale the text.
- Avoid justified text, which can create large inter-word gaps that are difficult for some readers to track.
UX writing
UX writing is the discipline of writing the words that appear inside a user interface — button labels, menu items, error messages, empty states, tooltips, onboarding flows. It is documentation that the reader encounters in situ, while using the product, rather than in a separate document they seek out.
Clarity over cleverness
UI text MUST be clear before it is clever. A witty error message that the reader has to decode is worse than a plain one that tells them what happened and what to do next. Wordplay, brand voice, and personality are welcome where they do not obscure meaning, but clarity always wins when the two conflict.
Action-oriented labels
Button and link labels SHOULD describe the action the control performs, in the reader’s voice rather than the system’s. Prefer "Delete file" to "OK" or "Submit." A reader scanning a dialog SHOULD be able to understand what each button does from its label alone, without reading the surrounding text.
Error messages
Error messages SHOULD:
- State what happened, in plain language. Avoid raw error codes as the only message.
- State what the reader can do about it, if anything. If the error is recoverable, the message SHOULD point to the recovery action.
- Avoid blaming the reader. "Invalid email" is better than "You entered an invalid email," and "Email address not recognized" is better still.
Consistency
The same action SHOULD be labeled the same way everywhere it appears. If the primary action is "Save" on one screen, it SHOULD not be "Submit" on the next. Inconsistent UI text forces the reader to re-parse familiar actions and erodes trust.
See TS-15: User Interfaces, TS-17: Graphical User Interfaces (GUIs), and TS-18: Web GUIs for the structural and interaction conventions that surround the words.
Support-driven documentation
Support channels — help desks, issue trackers, chat, mailing lists — are where the gap between what the documentation says and what users actually need becomes visible. Every support interaction is a signal: a question that keeps recurring is a sign the documentation does not answer it, and a question that is asked once but takes a long time to answer is a sign the answer is hard to find.
Feed support back into the documentation
Support SHOULD feed back into the documentation rather than remaining trapped in tickets and chat logs:
- When the same question recurs, the documentation SHOULD be updated to answer it, so that the next reader does not need to ask.
- When a support answer is long or nuanced, it SHOULD be promoted to a documentation page, with the support reply linking to it, rather than repeated from memory each time the question comes up.
- When a user reports that the documentation was misleading, the documentation SHOULD be corrected, not just the individual user’s understanding.
Support as a documentation source
Support agents who are not technical writers still produce documentation every time they write a reply. Treating those replies as a source — to be mined for recurring questions, common confusions, and the language users actually use to describe the product — keeps the documentation honest about what users need.
The reverse is also true: technical writers who spend time in support gain a clearer picture of what the documentation fails to explain. Rotating writers through support, or keeping a feedback channel from support to documentation, is RECOMMENDED.
Documentation tooling
The choice of documentation tooling — the markup language, the static site generator or CMS, the build pipeline, the hosting platform — shapes what the documentation can do and how easily it stays current. Tooling is a means, not an end: the goal is documentation that is accurate, discoverable, and maintainable, and the tooling SHOULD serve that goal rather than dictate it.
Choosing a toolchain
When evaluating documentation tooling, consider:
- Authoring experience. Can the people who need to write documentation do so without fighting the tool? A tool that requires a specialist to author content creates a bottleneck and a silo.
- Review workflow. Does the tool support review through the same pull-request workflow the code uses? Docs-as-code (see Docs as code) depends on this.
- Build and publishing. Can the documentation be built and published automatically, on every change, without manual intervention?
- Versioning. Can the tool publish and maintain multiple versions of the documentation, for readers who remain on older versions of the software?
- Search. Does the tool provide search? Documentation that cannot be searched is documentation that cannot be found by the reader who does not already know where to look.
- Extensibility. Can the tool be extended — custom blocks, includes, plugins — without locking the content into a proprietary format that cannot be migrated?
- Hosting. Where will the published documentation live? A tool that only publishes to a proprietary platform limits portability.
Markup languages
Prefer a lightweight, plain-text markup language so that documentation can be authored in the same editor and reviewed in the same workflow as code. See TS-27: Markdown and TS-28: AsciiDoc for guidance on the two most common choices.
Avoid binary formats (word processor documents, proprietary help-authoring formats) for documentation that is maintained alongside code. They resist diffing, reviewing, and automation, and they tie the content to a specific tool.
Generated vs. hand-written
Documentation generators — tools that extract API reference from source code comments — are useful for reference material that must mirror the code exactly. But generated documentation is rarely good documentation on its own. It SHOULD be supplemented with hand-written narrative that explains why and how, not just what. See the ARID principle in Principles.
References
- Write the Docs. — Community effort to document best practices for creating software documentation.