Diagram-as-Code: Mermaid, PlantUML & Structurizr Guide
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 --> FSequence 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
@endumlPlantUML 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
| Feature | Mermaid | PlantUML | Structurizr |
|---|---|---|---|
| Syntax | Simple | Medium | DSL-based |
| UML support | Basic | Full | C4 only |
| CI/CD friendly | Yes | Yes | Yes |
| GitHub native | Yes | No | No |
| Architecture focus | General | UML | C4 model |
| Learning curve | Low | Medium | Medium |
| Best for | Flowcharts, sequences | UML diagrams | Software 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/**/*.mmdCommon 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
What’s Next
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro