One of the most common failure points in software projects isn't the code — it's the documentation next to it. It goes stale the week after it's written, lives in a wiki nobody remembers the login for, or gets rewritten from scratch because finding the original was harder than starting over.
Documentation-as-Code (Docs-as-Code) fixes this by treating docs like source code: version-controlled, reviewed in pull requests, and built automatically every time something changes. Below is what that actually looks like — not just the concept, but a working setup you can copy.
What Docs-as-Code actually means
Instead of keeping documentation in a separate platform—a wiki, a CMS, a shared drive—Docs-as-Code keeps it in the same repository as the code it describes, written in plain-text formats (usually Markdown), and publishes it through the same build pipeline that ships the software itself.
Most engineers already do a version of this instinctively: inline comments explaining a tricky decision, a README that gets updated alongside a new feature, a CHANGELOG that tracks each release. Docs-as-Code just takes that instinct and gives it real structure — a static site generator to turn those plain-text files into something readable, and a pipeline to publish them automatically.
Why it holds up better than the alternatives:
- Docs live with the code — same repo, same version history, same pull request review. There's no separate place to hunt for the current version, because there isn't one.
- Low-maintenance by construction — publishing is a build step, not a task someone has to remember. If the pipeline runs, the docs are current.
- Docs get the same scrutiny as code — a documentation change goes through the same review process as a code change, which catches drift before it ships instead of after.
Setting it up with Hugo
There are several static site generators built specifically for this type of system — Docusaurus (Node.js), Jekyll (Ruby), and Hugo (Go) are the three most common. This walkthrough uses Hugo because it compiles to a single binary with no runtime dependencies, and builds are close to instantaneous even on large doc sets — you're not waiting on a Node toolchain or a Ruby gem chain to preview a change. All three are good options; it really comes down to what you're most comfortable with and, more importantly, what fits your tech stack best.
1. Pick a theme built for documentation, not a generic blog theme
Two solid options depending on project size:
- Docsy — built by Google, used across most CNCF projects. Comes with auto-generated navigation, versioning, multi-language support, and built-in search (Algolia or local). Best fit once you're past roughly 20 pages or have multiple doc types (tutorials, reference, how-tos).
- Hugo Book — zero-config, tree-structured navigation generated straight from your folder structure, no JavaScript required for core features. Best fit for a smaller, single-product doc set where you want something running in minutes, not hours.
For a first doc site, Book is faster and simpler to implement, but Docsy is worth the extra setup once the docs outgrow a single section.
2. Organize content the way the theme expects
Both themes read documentation pages out of a content/docs/ folder, using front matter to control ordering and titles:
content/
docs/
getting-started/
_index.md
installation.md
quickstart.md
reference/
_index.md
api.md
_index.md
---
title: "Installation"
weight: 10
---
Install the CLI with:
```bash
brew install yourtool
```
The weight field controls menu order — no separate navigation config to maintain by hand.
3. Wire up the build and deploy pipeline
This is the piece most Docs-as-Code explainers skip. Here's a working GitHub Actions workflow that builds the site with Hugo and deploys it to GitHub Pages on every push to main:
name: Build and deploy docs
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Setup Pages
id: pages
uses: actions/configure-pages@v6
- name: Install Hugo
run: |
curl -sfL -O https://github.com/gohugoio/hugo/releases/download/v0.166.0/hugo_0.166.0_linux-amd64.tar.gz
tar -xf hugo_0.166.0_linux-amd64.tar.gz
sudo mv hugo /usr/local/bin/
- name: Build
run: hugo build --gc --minify --baseURL "${{ steps.pages.outputs.base_url }}/"
- uses: actions/upload-pages-artifact@v5
with:
path: ./public
deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v5
id: deployment
(Simplified from Hugo's official GitHub Pages guide — the full version also handles Sass/Node asset pipelines and module dependencies, worth using once a project needs them.)
Once this is in place, it operates like any other pipeline: a docs change goes through a pull request, merges to main, and is live within a couple of minutes — no one has to remember to "publish" anything.
What this doesn't solve
Docs-as-Code isn't a fix for every documentation problem. It does tend to support an engineering-focused technical writing system more than a traditional one. For non-technical contributors, it adds a small amount of Git/Markdown literacy as a required skill set. Unless carefully designed and planned for, it can also fragment documentation across multiple repos rather than keeping it in a single location. Where those limitations show up in practice — and what the alternatives look like — is worth its own deep dive.