Chapter 07 of 10
API Docs as Code
Markdown in the repository against an editor in the portal, what each arrangement buys, what keeping both in step actually costs, and where the contract itself should live.
Documentation either lives where the code lives or where the writing happens, and almost every team eventually wants both. This chapter is about what each side is actually good at and what the bridge between them costs.
Why put documentation in the repository
The argument is proximity. A change to the API and the change to its documentation belong to the same pull request, so the second one is visible while the first is still being reviewed.
That buys four things. Documentation changes get reviewed by the people who know whether they are true. They ship on the same branch as the code, so a feature behind a flag does not get documented early. They are versioned with the code, so the documentation for an old release is recoverable. And they are editable in whatever the author already uses.
The cost is the audience. A support engineer who noticed that a page is wrong will not open a pull request to fix a sentence. A technical writer who has to learn a branching model before their first edit will write somewhere else.
Why put documentation in an editor
The argument on the other side is contribution. An editor with a preview lets anybody who knows the product fix a page, which is where most documentation improvements actually come from.
It also handles the things plain files handle badly, meaning images, embedded diagrams, reusable snippets and a preview that matches what the reader will see.
The cost is that nothing in the code review asks whether a page still holds. Documentation in an editor goes stale in exactly the way the keeping it up to date chapter describes, because the prompt to change it is gone.
What a bridge between the two costs
Pulling pages into files and pushing them back is straightforward to describe and has three places where it gets interesting.
Identity. Something has to decide which local file corresponds to which remote page. A slug is the usual answer, which means renaming a file moves a page rather than editing it, and a moved page breaks links that were published against the old address.
Concurrency. Somebody may have edited a page in the editor since you pulled. A sync that overwrites their change quietly is worse than one that stops and tells you, so the version token that detects it matters more than the convenience of a force flag.
Deletion. A page that exists remotely with no local counterpart is ambiguous. It might be a page somebody added in the editor, or a file you deleted on purpose. Treating that case as a deletion means a mistyped directory can empty a documentation version in one command, which is why the safe default is to report it and change nothing.
Where the contract itself lives
The same question applies to the OpenAPI document, and the answer follows how your team works rather than a principle.
A code-first team generates the contract from annotations, so it belongs in the repository where those annotations are. A design-first team writes the contract before the implementation, so it belongs in the tool where that design happens and is published from there.
The arrangement to avoid is the third location, where the contract sits in a place neither the implementers nor the designers open.
In Routebase
Routebase supports both directions, and the CLI is the repository side of it. routebase docs pull writes a documentation version into a folder of Markdown files with YAML frontmatter, and routebase docs push writes local changes back.
routebase docs pull --project <project-id> --dir docs
routebase docs push --project <project-id> --dir docs --dry-runThe three hard parts above are settled explicitly. Pages are matched by slug within their parent folder. The frontmatter carries a concurrency token from the moment you pulled, so a page edited in the app is rejected rather than overwritten. And push never deletes, because a --dir pointed one level too deep would otherwise clear a version in one command. The dry run prints the whole diff without writing anything, which is the cheapest way to catch a rename before it becomes a moved page.
Meanwhile the Doc Hub in the app stays usable, because the two are views of the same pages rather than competing copies. Generated API references are skipped by the pull, since they come from your specifications and there is no Markdown to edit.
Our own product documentation runs this way. The pages live as Markdown next to the code, a merge to the main branch pushes them into the portal's draft version, and publishing stays a separate step that somebody triggers. The Docs as Code guide covers the commands, the frontmatter and the conflict behaviour in full.
Frequently asked questions
What does docs as code mean?
It means treating documentation like source code. The pages are plain text files in the repository, changes arrive as pull requests, review happens in the same place code review happens, and a merge deploys them. The point is not the file format but the workflow, since a documentation change that goes through review alongside the code change it describes is far harder to forget.
Is docs as code better than a documentation editor?
They fail in different places. A repository workflow keeps documentation close to the change that made it necessary and locks out anybody who does not work in git. An editor lets the whole team contribute and drifts from the code because nothing in the pull request asks for it. Which one costs you more depends on who writes your documentation.
Can you use both a repository and a portal editor?
Yes, and the question to settle first is which side wins a conflict. Pulling pages into files, editing them and pushing them back works as long as edits made in the portal in the meantime are detected rather than overwritten. Silently discarding a colleague's change is worse than a failed command.
Where should the OpenAPI file live?
Wherever the change to it happens at the same moment as the change to the API. For a code-first team that is the repository, and for a design-first team it is the design tool that publishes versions. What is worth avoiding is the arrangement where the contract lives in a third place that neither side updates.
Last reviewed by The Routebase Team.