✍️
✍️Technical Writing

Docs as Code in 2025: The Complete Guide to Modern Documentation

Treat your documentation like software: version control, CI/CD, automated testing, and pull requests. Here's how the best teams are doing it.

By Taresh•December 27, 2025•11 min read

I've worked with documentation stored in a wiki that nobody updated, out of sync with the actual product, with half the pages dating from years earlier and a search box that never returned the page you needed. New hires would spend their first week just figuring out which of the three conflicting setup guides was current. If that sounds like your documentation, I don't think the fix is a new tool or a big rewrite project. It's a philosophy shift: treat your docs exactly like you treat your code.

That's the whole idea behind Docs as Code, and it's the one documentation practice I'd tell any engineering team to adopt before anything fancier.

What Docs as Code Actually Changes

In a traditional setup, docs live in a wiki or a shared drive, get edited in place with no review process, and get published by someone copy-pasting into a CMS. Nobody can tell you who changed a page or why, and version history is a filename: "Final_v3_REAL.docx."

Docs as Code replaces all of that with the same tooling your engineers already use. Content is written in Markdown (or AsciiDoc, or reStructuredText) and stored in a Git repository, right alongside — or in the same repo as — the code it describes. Changes go through a branch, get reviewed in a pull request, and get published automatically by a CI/CD pipeline once merged. The docs get the same testing rigor as code: link checks, spell checks, linting.

The reason this works isn't really about the tooling, though. It's that it makes documentation everyone's responsibility instead of one writer's backlog. When docs live in the same repo as the code, a developer changing an API can update the relevant doc page in the same pull request. When docs live in a separate wiki, that same developer has no reason to even think about it, and the docs drift.

Picking a Stack

For source format, plain Markdown covers the large majority of documentation needs — it's simple, universal, and every editor supports it. Reach for MDX only if you actually need interactive React components embedded in docs pages; otherwise it's unnecessary complexity. AsciiDoc is worth considering for long, structured technical documents or books where Markdown's limited semantics start to hurt. reStructuredText mostly matters if you're already in the Python/Sphinx ecosystem.

For the static site generator, I'd narrow it down like this: Docusaurus if you want strong versioning support and don't mind a React dependency (this is what most developer-docs-as-a-product teams reach for). MkDocs if your team is Python-first and wants something simpler to configure. Astro Starlight if performance is the priority and you don't need Docusaurus's plugin ecosystem. GitBook if the audience includes non-technical stakeholders who need a friendlier authoring UI than raw Markdown in a PR — though you give up some of the "real" docs-as-code rigor in exchange. I'd skip Sphinx unless you're documenting a Python library, since its authoring experience is rougher than the alternatives for general use.

Hosting is the easy part now — Vercel, Netlify, Cloudflare Pages, and GitHub Pages all have workable free tiers for a documentation site, and any of them will do. Pick whichever one matches your existing deployment habits rather than treating this as a real decision.

Repository Structure

docs/
├── README.md                 # Docs contribution guide
├── docs/                     # All documentation content
│   ├── getting-started/
│   │   ├── installation.md
│   │   ├── quickstart.md
│   │   └── configuration.md
│   ├── guides/
│   │   ├── authentication.md
│   │   └── deployment.md
│   ├── api-reference/
│   │   ├── endpoints.md
│   │   └── errors.md
│   └── contributing.md
├── static/                   # Images, downloads
│   └── images/
├── docusaurus.config.js      # Site configuration
├── sidebars.js               # Navigation structure
└── package.json              # Dependencies

The Actual Workflow

It's the same branch-write-review-merge loop your engineers already run for code: create a branch, write in Markdown, preview locally with something like npm run start, commit, push, and open a pull request. Someone reviews it, you iterate on the feedback, it gets merged (squash merge keeps history clean), and CI/CD deploys it automatically. There's no separate "publishing" step to remember, which is exactly the point.

The part teams skip, and shouldn't, is the review checklist. When I look at a docs PR, I'm checking whether the technical content is actually correct, whether someone unfamiliar with the feature could follow it, whether any steps are missing, whether it matches the existing style, whether the links resolve, and — if there's a code sample — whether it actually runs. That last one catches more embarrassing bugs than anything else on the list, because it's the easiest thing to skip when you're in a hurry.

Automated Testing for Docs

The tests that matter most are the boring ones: link checking (linkinator or markdown-link-check will catch broken internal and external links before they ship), spell checking (cspell or aspell), and Markdown linting (markdownlint or remark) for formatting consistency. If you want to enforce voice and terminology automatically, vale is worth setting up, though I'd treat it as a nice-to-have rather than a first step — get link checking and linting working first, since those catch the failures that actually embarrass you in front of users.

Sample GitHub Actions Workflow

name: Docs CI
on:
  pull_request:
    paths:
      - 'docs/**'
      - '*.md'

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Lint Markdown
        uses: DavidAnson/markdownlint-cli2-action@v14
      - name: Check spelling
        uses: streetsidesoftware/cspell-action@v5
      - name: Check links
        uses: lycheeverse/lychee-action@v1

  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - run: npm ci
      - run: npm run build

Writing Standards Worth Setting Early

A few conventions save a lot of pain later: kebab-case filenames (getting-started.md), an index.md for section landing pages, and consistent frontmatter. A minimal frontmatter block looks like this:

---
title: Getting Started with Authentication
description: Learn how to implement OAuth2 authentication
sidebar_position: 1
tags: [auth, oauth, security]
---

Beyond that, the content structure that holds up across most doc types is: a title, a short paragraph on what the page covers and why, prerequisites the reader needs before starting, numbered steps under H2s (with H3s for details inside a step where needed), and code blocks for anything the reader is meant to copy. Resist the urge to add more structural ceremony than that — the more rigid the template, the more pages end up with awkward empty sections just to satisfy it.

What I'd Actually Prioritize

If I had to rank the practices, keeping docs in the same repo as the code they describe is the one that matters most — it's the difference between docs that get updated as a byproduct of shipping and docs that quietly rot because updating them means opening a different tool entirely. After that: require PR review (even a lightweight one), automate the deployment so publishing is never a manual step, and run link/spelling checks on every PR so broken links don't accumulate silently.

The things I'd actively avoid: docs living in a separate repo from the code (guaranteed drift), direct commits to the main branch with no review, and manual publishing steps that depend on one person remembering to do them. All three of these are how documentation quietly stops being trustworthy.

For measuring whether any of this is working, I care about a fairly small set of signals: whether new users can get to a first success in under 15 minutes, whether support tickets referencing "the docs weren't clear" are trending down, and whether the broken-link count from automated scans stays at zero. Docs contribution counts (how many people outside the writing team open PRs against docs) is a good proxy for whether the "everyone owns docs" culture is actually taking hold, versus just being a phrase in a wiki page nobody reads.

Migrating from a Wiki

If you're moving off a wiki, don't try to migrate everything at once — audit what you have, figure out which pages actually get read (analytics or support-ticket references are the fastest way to find out), and move the high-value pages first. Get the CI/CD and testing pipeline working while that's happening rather than after, redirect the old wiki once the new docs are live, and treat the whole thing as an ongoing practice rather than a project with an end date. Teams that try to convert everything before switching over usually stall out somewhere in month two.

Documentation isn't a side project — it's a product, and it holds up better when it gets the same version control, review, and continuous deployment that the codebase gets. The hardest part of any of this is starting: pick one repo, one folder, one page, and go from there.

Tags

Technical WritingDocs as CodeDocumentationDevOpsGitMarkdown

Comments

Nothing here yet.