Mastering Architecture Documentation: Docs as Code for Living Systems

Software Architecture

Unlock the power of 'Docs as Code' for software architecture. Learn to keep diagrams and ADRs in sync with code using tools like Structurizr, PlantUML, Mermaid, and Docusaurus for living documentation.

If your software architecture exists only on a slide deck, it's destined to become obsolete within a few sprints. I've seen it countless times: a pristine diagram on day one quickly devolves into an inaccurate representation by day thirty. The solution isn't a complex, one-time diagram, but rather a meticulously designed documentation workflow. Leveraging the appropriate software architecture documentation tools enables rapid diagramming, rigorous reviews similar to code assessments, and continuous synchronization with your code repository. This is the vision we aim to achieve.

What is "Docs as Code," and Why is it Transformative?

"Docs as Code" treats documentation with the same rigor as source code. This involves writing documentation in plain text formats (like Markdown, AsciiDoc, or a Domain-Specific Language), storing it in Git, reviewing changes through pull requests, and publishing it via Continuous Integration (CI) pipelines. This approach offers significant advantages: enhanced traceability, a clear blame history, automated previews, and fosters a crucial team habit—documentation must be updated alongside code changes, or the build fails. In my experience, it's the most effective method for maintaining architectural integrity amidst continuous evolution.

My standing rule for teams is simple: no architectural change should merge without an accompanying updated diagram or Architecture Decision Record (ADR) within the same pull request. This practice enforces clarity upfront and prevents weeks of 'but I thought...' misunderstandings down the line.

Essential Software Architecture Documentation Tools

Here's a concise guide to tools I recommend for teams:

  • Structurizr (with DSL): Ideal for C4 Model diagrams at scale, offering robust 'diagrams as code' ergonomics.
  • PlantUML + C4-PlantUML: Provides expressive, text-first diagrams with extensive IDE and CI support.
  • Mermaid: Perfect for lightweight diagrams directly embedded in Markdown, rendering natively on platforms like GitHub and GitLab.
  • Lucidchart: A visual editor for rapid, collaborative diagramming, producing polished outputs suitable for stakeholders.
  • Docusaurus (or MkDocs): Excellent for publishing 'docs as code' sites, complete with versioning and preview capabilities.

Software Architecture Documentation Tools Comparison

ToolCategoryC4 Model SupportEditing ModeCollaborationVersion-Control FitNotes
Structurizr (DSL/Cloud/Lite)Diagrams as codeFirst-classDSL text + auto-layoutWorkspace sharing; export to PNG/SVG/PlantUML/MermaidExcellent (files in Git; CLI export; CI-friendly)Great for system-wide C4 views, styling, and consistent layouts.
PlantUML + C4-PlantUMLDiagrams as codeVia C4-PlantUML macrosText with macrosWorks via Git workflows; Confluence/VS Code integrationsExcellent (plain text; easy diffs)Powerful and scriptable; requires a rendering step (local, CI, or server).
MermaidDiagrams in MarkdownNo native C4Text in fenced code blocksNative rendering on GitHub/GitLab/Azure DevOpsExcellent (lives next to docs)Fantastic for sequence/flow/class/timeline; can emulate C4 with constraints.
LucidchartVisual editor (SaaS)Manual (stencils/templates)Drag-and-dropReal-time cursors, comments, @mentions, version historyGood (export assets to Git)Stakeholder-friendly polish; lock styles; export SVG/PNG for repositories.
DocusaurusDocs site generatorVia plugins/embedsMarkdown/MDXPR previews via Netlify/Vercel; search; versioningExcellentGreat front-end for docs-as-code; supports Mermaid via plugin.

Example: Code-Generated Diagram (PlantUML + C4)

Below is a minimal C4 Container diagram defined as code. This can be rendered locally (using PlantUML and Graphviz), within your CI pipeline, or via a PlantUML server like Kroki. Storing the .puml file in your repository allows for code-like review of changes.

@startuml C4_Container
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml

title Payment Platform - Container Diagram
Person(customer, "Customer", "Initiates payments")
System_Boundary(s1, "Payment Platform") {
  Container(web, "Web App", "React", "Allows customers to pay")
  Container(api, "API", "Spring Boot", "Handles payment workflows")
  ContainerDb(db, "Payments DB", "PostgreSQL", "Stores transactions")
}
Rel(customer, web, "Uses", "HTTPS")
Rel(web, api, "Calls", "JSON/REST")
Rel(api, db, "Reads/Writes", "JDBC")
@enduml

These diagrams are concise, readable, and easily reviewable. Any modification to a relationship or component is visible in the Git diff and the CI-rendered preview, providing invaluable visibility during design reviews.

Example: Visual-Tool Diagram (Lucidchart)

Visual editors excel in scenarios involving brainstorming with non-developers or when aesthetic presentation and layout are paramount. With such tools, you drag, align, apply themes, and then export. Below is a textual representation of a simple, illustrative Lucidchart-style container view that you might export to your repository as an .svg or .png file:

Payment Platform — Container Diagram Web App React Customer UI • SSR/CSR as needed • Auth & session • Input validation ↓ API Spring Boot Payment logic • REST/JSON • Idempotency keys • Retry & DLQ ↓ Payments DB PostgreSQL Transactions • ACID • Indexes • Backups

This represents a visual-tool diagram created in Lucidchart, which would then be exported as SVG/PNG for inclusion in your repository.

A typical Lucidchart workflow involves:

  1. Creating a new document and selecting an appropriate template.
  2. Dragging and dropping container shapes onto the canvas.
  3. Applying a consistent style and color system to ensure uniformity across team diagrams.
  4. Sharing with stakeholders for comments and resolving feedback directly within the tool.
  5. Exporting the diagram as an .svg or .png file and committing it as an asset to your docs directory.

Version-Controlling Architecture Documentation Alongside Code

The key is consistency and simplicity. The following repository structure has proven highly effective:

repo/ ├─ docs/ │ ├─ architecture/ │ │ ├─ 01-context.puml │ │ ├─ 02-container.puml │ │ ├─ 03-component.puml │ │ ├─ exports/ (CI writes PNG/SVG here) │ │ └─ adr/ │ │ ├─ 0001-use-stripe.md │ │ └─ 0002-split-payments-service.md │ ├─ index.md │ └─ architecture.md ├─ docusaurus.config.js └─ .github/workflows/docs.yml

To prevent documentation from becoming stale, automate diagram rendering within your CI pipeline. This ensures that pull requests cannot merge with outdated diagrams.

Here’s an example GitHub Actions workflow:

name: docs
on: [push, pull_request]
jobs:
  build-docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install PlantUML and Graphviz
        run: sudo apt-get update && sudo apt-get install -y plantuml graphviz
      - name: Render PlantUML to SVG
        run: mkdir -p docs/architecture/exports && plantuml -tsvg -o exports docs/architecture/*.puml
      - name: Setup Node
        uses: actions/setup-node@v4
        with: { node-version: '20' }
      - name: Install and build Docusaurus
        run: npm ci && npm run build
      - name: Upload site as artifact (or deploy)
        uses: actions/upload-pages-artifact@v3
        with: { path: build }

For architectural decisions, maintain Architecture Decision Records (ADRs) alongside your diagrams. I prefer the MADR format due to its plain Markdown structure and PR-friendliness. Every significant architectural change should be documented with a concise ADR detailing its context, considered options, and the final outcome. This creates a valuable, living history of your engineering decisions.

Collaboration and Review Across Tools

Each tool offers unique strengths for collaboration and review:

  • Structurizr: Models and views are defined in text (DSL). Diagrams can be exported and committed to Git, and workspaces shared via Structurizr Cloud or Structurizr Lite. Integration with CI ensures consistent exports.
  • PlantUML + C4-PlantUML: Collaboration is Git-centric. Developers modify text definitions, create pull requests, and review diffs. VS Code extensions provide local previews, and CI renders final assets for documentation sites.
  • Mermaid: Diagrams are embedded directly within Markdown. Platforms like GitHub, GitLab, and Azure DevOps render these diagrams in pull requests and READMEs, facilitating rapid reviews for simpler flows and sequences.
  • Lucidchart: Features like real-time multi-cursor editing, comments, @mentions, and version history are invaluable for live design sessions. While editable sources reside in Lucidchart, exported diagrams are committed to the repository.
  • Docusaurus: Serves as the publishing layer. Utilizing preview URLs for each pull request allows reviewers to inspect the entire documentation site, including diagrams, prior to merging.

Effective reviews begin with focused, minimal changes that clearly convey the intent. Always update the relevant diagram, link to the corresponding ADR, and provide a preview. Clarity is paramount for successful feedback.

When to Choose Each Tool: A Quick Guide

This matrix offers a starting point for tool selection. Remember, you can often mix and match, but prioritize keeping your publishing workflow straightforward.

Team ContextPrimary StackWhy This WorksNotes
Small team, fast iterationsMermaid in Markdown + DocusaurusLowest friction; renders on GitHub; easy PR reviewsConsider PlantUML if stricter C4 semantics are required.
Product engineering at scaleStructurizr DSL + PlantUML export + DocusaurusStrong C4 modeling, consistent styles, CI exportsKeep DSL in the repository; export SVGs for the documentation site.
Enterprise with mixed audiencesStructurizr/PlantUML for devs + Lucidchart for stakeholdersText-first for developer workflows; polished visuals for executivesCommit exported diagrams; store Lucidchart sources in a governed workspace.
Hybrid monorepoPlantUML + C4-PlantUML + ADRs + DocusaurusEverything lives in Git; PRs gate changesGenerate diagrams in CI; configure builds to fail if exports are stale.

Practical Tips That Saved Me Hours

  • Create a consistent style guide: Define colors, fonts, border radii, and relationship labels once. Enforce this through Structurizr/PlantUML themes or Lucidchart templates.
  • Prefer SVG over PNG: SVG files offer superior diffing capabilities, scale perfectly, and load faster in repositories.
  • Co-locate diagrams with code: Store diagrams alongside the code they describe. For instance, a payment component's diagram should reside in close proximity to the payment service's code.
  • Automate staleness checks: Implement a small script to compare timestamps between .puml source files and their exported .svg counterparts, failing the build if exports are outdated.
  • Link ADRs to diagrams: Establish clear links between Architecture Decision Records and relevant diagrams. Your future self will appreciate this foresight.

Closing Reflection

Architecture is far more than a static image on a wall; it is a dynamic, ongoing dialogue among team members. The right tools don't just facilitate visual representation; they establish a framework that ensures architectural changes are both safe and effective. By tightly integrating architectural diagrams with the underlying codebase, the system evolves into a living map, providing real-time insights and adaptability. This synergy between design and implementation is a crucial goal every team should pursue.


Snehasish Konger

Developed at scientyficworld.org | Technical writer at Nected | Content Developer