Documentation as Code

Documentation as Code (or Documentation-as-Code) is an approach that treats project documentation in the same way as source code. Instead of creating static documents in separate tools (such as text editors or wikis), documentation is written in versioned files, typically in human-readable and machine-processable formats (Markdown, AsciiDoc, etc.), and stored in the same repository as the code.

Main Features

Feature How it works in practice
Versioning Each change to documentation generates a commit, allowing you to track who changed what and when, just like with code.
PR Reviews Documentation changes undergo code reviews (PRs/MRs). This ensures quality and consistency, and allows developers to review the content before merging.
CI/CD Integration Automated pipelines can validate syntax, generate documentation builds (HTML, PDF), and even publish to hosting sites (GitHub Pages, GitLab Pages, Read the Docs).
Automation Scripts can extract information directly from the code (e.g., docstrings, comments, OpenAPI specs) and insert it into the documentation, reducing duplication and errors.
Collaboration Anyone with access to the repository can contribute, use the same development tools (IDE, linters, formatters), and follow the same style conventions.

Benefits

  1. Consistency – Documentation evolves alongside the code; API or behavior changes are reflected immediately.
  2. Quality – Code reviews enforce writing standards, spelling, and clarity, as do implementation reviews.
  3. Transparency – A complete change history facilitates audits and understanding of past decisions. 4. Scalability – Automation (generating diagrams, tables from real data) keeps documentation up-to-date without manual effort.
  4. Process Unification – Teams don’t need to manage two different tool stacks (one for code, another for docs).
  • Hugo & Docsy1 – Static site generation that supports UML, OpenAPI, and other documentation.
  • MkDocs (with Material theme) – Converts Markdown into static sites; integrates well with GitHub Actions.
  • Sphinx – Uses reStructuredText (or MyST Markdown) and supports extensions to generate documentation for Python, C++, and other APIs.
  • Docusaurus – React framework for documentation sites; accepts MDX (Markdown + JSX).
  • Read the Docs – Service that hosts automatic builds of Sphinx/MkDocs from repositories. - GitBook, Docsify, Hugo – Other options for static website generation.

Hugo & Docsy

“Docsy is a pre-configured Hugo theme that provides the main features and behaviors needed to create a technical documentation website.”

Access the following link to see a more complete demo of Documentation as Code: https://adrianovieira.gitlab.io/plantuml-demo/

Typical Workflow

  1. Write – The author creates/edits .md (or .rst) files in the repository.
  2. Lint/Format – A linter (e.g., markdownlint, vale) checks style and spelling.
  3. Pull Request – The change is submitted for review; reviewers check for clarity and correctness.
  4. CI Build – The pipeline runs build tests (e.g., mkdocs build). If it fails, the PR cannot be merged.
  5. Deploy – After merging, the pipeline publishes the new version of the documentation (GitHub Pages, Netlify, etc.).

When to adopt?

  • Projects with rapid evolution or public APIs that require synchronized documentation.
  • Teams that already use CI/CD and want to centralize the entire delivery flow.
  • Organizations that value transparency and auditability of changes.

In short, documentation as code brings the discipline of software engineering to the creation and maintenance of documents, ensuring that they remain accurate, revisable, and easily distributed as the project grows.

Software Artifacts

An artifact is one of many types of tangible byproducts produced during software development.

Some artifacts (e.g., use cases, class diagrams, requirements, and design documents) help describe the function, architecture, and design of the software. Other artifacts are related to the development process itself—such as project plans, business cases, risk assessments, and software diagrams.

And this is where PlantUML comes in…

PlantUML

“PlantUML is used to draw UML diagrams, using a simple and human-readable text description. Be careful, because it does not prevent you from drawing inconsistent diagrams (such as having two classes inheriting from each other, for example). So it’s more a drawing tool than a modelling tool.” - PlantUML.org

Diagrams

C4 Model

The C4 model is a lean graphical notation technique for modeling the architecture of software systems. It is based on a structural decomposition (a hierarchical tree structure) of a system into containers and components and relies on existing modelling techniques such as Unified Modeling Language (UML) or entity–relationship diagrams (ERDs) for the more detailed decomposition of the architectural building blocks.

Source code
@startuml
   skinparam dpi 300
   !include <C4/C4_Container>

   AddElementTag("v1.0", $borderColor="#d73027")
   AddElementTag("v1.1", $fontColor="#d73027")
   AddElementTag("backup", $fontColor="orange")

   AddRelTag("backup", $textColor="orange", $lineColor="orange", $lineStyle = DashedLine())

   Person(user, "Customer", "People that need products")
   Person(admin, "Administrator", "People that administrates the products via the new v1.1 components", $tags="v1.1")
   Container(spa, "SPA", "angular", "The main interface that the customer interacts with via v1.0", $tags="v1.0")
   Container(spaAdmin, "Admin SPA", "angular", "The administrator interface that the customer interacts with via new v1.1", $tags="v1.1")
   Container(api, "API", "java", "Handles all business logic (incl. new v1.1 extensions)", $tags="v1.0+v1.1")
   ContainerDb(db, "Database", "Microsoft SQL", "Holds product, order and invoice information")
   Container(archive, "Archive", "Audit logging", "Stores 5 years", $tags="backup")

   Rel(user, spa, "Uses", "https")
   Rel(spa, api, "Uses", "https")
   Rel_R(api, db, "Reads/Writes")
   Rel(admin, spaAdmin, "Uses", "https")
   Rel(spaAdmin, api, "Uses", "https")
   Rel_L(api, archive, "Writes", "messages", $tags="backup")

   SHOW_LEGEND()
@enduml
Diagram

References