Skip to content
Diagram-as-Code: Mermaid, PlantUML & Structurizr Guide

Diagram-as-Code: Mermaid, PlantUML & Structurizr Guide

DodaTech Updated Jun 20, 2026 7 min read

Diagram-as-code means writing diagrams in text files using declarative syntax — then rendering them as images. Instead of dragging boxes in a GUI, you type A --> B in Markdown and get a flowchart. This approach keeps diagrams in version control, makes them reviewable in pull requests, and integrates with documentation pipelines.

In this tutorial, you’ll learn Mermaid, PlantUML, and Structurizr — the three main diagram-as-code tools — with practical examples you can use in your own docs.

Diagram-as-Code Workflow

    flowchart LR
  A[Write diagram syntax] --> B[Store in Git]
  B --> C[Review in PR]
  C --> D[CI renders diagram]
  D --> E[Embed in docs]
  E --> F[Update as code changes]
  F --> A
  A:::current

  classDef current fill:#f90,color:#fff,stroke:#333,stroke-width:2px
  

Why Diagram-as-Code?

Traditional diagram tools (draw.io, Lucidchart, Figma) have three problems:

  • Not versionable — Binary files don’t diff well. You can’t see what changed in a diagram review
  • Not reviewable — Pull requests can’t show diagram diffs
  • Not automated — Manual diagrams become outdated quickly

Diagram-as-code solves all three. Text files diff cleanly, render in CI, and update alongside code changes.

Mermaid

Mermaid is the most popular diagram-as-code tool, written in JavaScript and natively supported in GitHub Markdown, Notion, and many documentation tools.

Flowcharts

    flowchart TD
  A[Start] --> B{Is valid?}
  B -->|Yes| C[Process request]
  B -->|No| D[Return error]
  C --> E[Save to database]
  E --> F[Send response]
  D --> F
  
flowchart TD
  A[Start] --> B{Is valid?}
  B -->|Yes| C[Process request]
  B -->|No| D[Return error]
  C --> E[Save to database]
  E --> F[Send response]
  D --> F

Sequence Diagrams

    sequenceDiagram
  participant User
  participant API
  participant DB

  User->>API: POST /api/login
  API->>DB: SELECT user WHERE email
  DB-->>API: User found
  API->>API: Hash & compare password
  API-->>User: 200 { token: "jwt..." }
  Note over User,API: Token expires in 24 hours
  
sequenceDiagram
  participant User
  participant API
  participant DB

  User->>API: POST /api/login
  API->>DB: SELECT user WHERE email
  DB-->>API: User found
  API->>API: Hash & compare password
  API-->>User: 200 { token: "jwt..." }

Gantt Charts

    gantt
  title Project Timeline
  dateFormat  YYYY-MM-DD
  section Development
  API Design        :done, a1, 2026-06-01, 5d
  Backend Implementation :active, a2, after a1, 10d
  Frontend          :a3, after a2, 8d
  section Testing
  Integration Tests :b1, after a3, 5d
  UAT               :b2, after b1, 3d
  

Class Diagrams

    classDiagram
  class User {
    +String id
    +String email
    +String name
    +login(password) bool
    +updateProfile(data) void
  }
  class Post {
    +String id
    +String title
    +String content
    +publish() void
  }
  class Comment {
    +String id
    +String text
    +Date createdAt
  }
  User "1" --> "*" Post : writes
  Post "1" --> "*" Comment : has
  

PlantUML

PlantUML specializes in UML diagrams with a Java-based renderer:

@startuml
!theme plain

class User {
  + String id
  + String email
  + login(password: String): Boolean
}

class Post {
  + String title
  + String content
  + publish(): void
}

class Comment {
  + String text
}

User "1" --> "*" Post
Post "1" --> "*" Comment
@enduml

PlantUML supports: sequence diagrams, use case diagrams, activity diagrams, component diagrams, deployment diagrams, and more.

Structurizr (C4 Model)

Structurizr implements the C4 model for software architecture diagrams. You write in a DSL:

workspace {
  model {
    user = person "User" "A website visitor"
    webApp = softwareSystem "Web Application" "Allows users to browse content"
    database = softwareSystem "Database" "Stores user and content data"

    user -> webApp "Uses HTTPS"
    webApp -> database "Reads/Writes SQL"
  }

  views {
    systemContext webApp {
      include *
      autoLayout
    }
  }
}

This generates a system context diagram, container diagram, component diagram, and code diagram — four levels of detail from high-level to low-level.

Embedding in Documentation

In Hugo (Mermaid shortcode)

{{< mermaid >}}
flowchart LR
  A[Start] --> B[End]
{{< /mermaid >}}

In Docusaurus

import Mermaid from '@theme/Mermaid';

<Mermaid chart={`
  flowchart LR
    A[Start] --> B[End]
`} />

In GitHub Markdown

```mermaid
flowchart LR
  A[Start] --> B[End]

Rendering in CI

Automate diagram rendering so generated images stay in sync:

- name: Render Mermaid diagrams
  uses: mermaid-js/mermaid-cli@v10
  with:
    files: 'docs/**/*.mmd'
    output: 'static/diagrams/'
- name: Render PlantUML diagrams
  run: |
    java -jar plantuml.jar -tsvg docs/diagrams/*.puml
    mv docs/diagrams/*.svg static/diagrams/

Tool Comparison

FeatureMermaidPlantUMLStructurizr
SyntaxSimpleMediumDSL-based
UML supportBasicFullC4 only
CI/CD friendlyYesYesYes
GitHub nativeYesNoNo
Architecture focusGeneralUMLC4 model
Learning curveLowMediumMedium
Best forFlowcharts, sequencesUML diagramsSoftware architecture

Version Control for Diagrams

Store diagram sources next to the code they describe:

project/
├── docs/
│   ├── architecture/
│   │   └── system-context.dsl  # Structurizr DSL
│   ├── api/
│   │   └── auth-flow.mmd       # Mermaid
│   └── deployment/
│       └── infrastructure.puml # PlantUML
└── src/

Review diagram changes in pull requests. Add a CI step that validates syntax:

npx @mermaid-js/mermaid-cli validate docs/**/*.mmd

Common Mistakes

1. Overcomplicating Diagrams

Trying to show everything on one diagram. A complex diagram helps no one. Split into multiple focused diagrams.

2. No Diagram at All

Pages about architecture or workflows without a single diagram. If a concept is visual, diagram it.

3. Binary Diagram Files in Git

PNG or SVG files that can’t be diffed. Always store the source text and regenerate images in CI.

4. Forgetting Mermaid Syntax Validation

Mermaid syntax errors silently produce blank diagrams. Add a CI validation step.

5. Inconsistent Diagram Style

Some diagrams use flowchart TD, others use graph LR. Pick one direction and layout style per project.

6. No alt Text for Diagrams

Screen readers can’t parse Mermaid output. Add descriptive alt text to every rendered diagram.

7. Diagrams That Never Update

Outdated architecture diagrams mislead more than they inform. Update diagrams alongside code changes.

Practice Questions

1. What are the three main benefits of diagram-as-code over GUI-based diagram tools?

Version control (text files diff cleanly), PR reviewability (changes are visible), and CI automation (renders and validates automatically).

2. What’s the syntax for creating a simple flowchart in Mermaid?

flowchart LR
  A[Start] --> B{Decision}
  B -->|Yes| C[Outcome]

3. When would you choose Structurizr over Mermaid?

For software architecture diagrams using the C4 model — system context, containers, components, and code. Mermaid is better for simpler flowcharts and sequences.

4. How do you validate Mermaid syntax in CI?

Use npx @mermaid-js/mermaid-cli validate docs/**/*.mmd or the Mermaid CLI to check syntax before rendering.

5. Challenge: Take a feature or system you’ve built. Create three diagrams for it: a Mermaid flowchart showing the process flow, a sequence diagram showing an API interaction, and a Structurizr C4 context diagram showing system architecture. Embed them in a documentation page.

Real-World Task

Audit an existing project’s documentation. Identify two places where a diagram would improve understanding. Create both diagrams using Mermaid and add them to the documentation. Verify they render correctly and add alt text.

FAQ

Which diagram tool should I learn first?
Mermaid. It’s the most widely supported (GitHub, GitLab, Notion, many SSGs), simplest syntax, and sufficient for 80% of diagram needs.
Can I use Mermaid in any documentation tool?
Most modern documentation tools support Mermaid natively: GitHub, GitLab, Notion, Obsidian, Hugo (via shortcode), Docusaurus (via plugin). Check your tool’s documentation.
How do I make Mermaid diagrams accessible?
Add descriptive alt text to every diagram. For Hugo: wrap the mermaid shortcode with a figure shortcode that includes alt text. Some projects generate a text description alongside the diagram.
What’s the downside of diagram-as-code?
Complex diagrams become hard to read in raw syntax. For highly complex UML, PlantUML or a visual editor may be better. Diagram-as-code excels at simple to moderately complex diagrams.
How do I ensure diagrams stay current?
Store diagram source alongside code. Add a CI check that fails if diagram source is older than the code it describes. Review diagrams as part of code review.

What’s Next

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro