Mermaid Diagrams from Real Code: The 5-Minute Setup Guide
Stop hand-drawing architecture diagrams that rot the moment your code changes. Here's how to render Mermaid diagrams straight from your source in under five minutes.
DocPilot Team
AI documentation research and engineering from Onzira Labs.
Why your diagrams are already out of date
Open your repository's architecture diagram. Now look at the src/ folder. If you're like most teams, those two views stopped agreeing weeks ago. Someone added a service, a route moved, a dependency got deprecated, and the pretty boxes-and-arrows in your wiki are now fiction.
The fix isn't discipline. It's automation. Mermaid is a JavaScript-based diagramming tool that renders from text, and GitHub, GitLab, and most static-site generators render it natively. That means your diagrams can live in .md files next to the code they describe, and they can be generated from the code itself.
This guide walks through a five-minute setup that takes you from "stale Confluence page" to "diagrams that update with every commit." No plugins, no build pipeline rewrites, no diagramming licenses.
What Mermaid actually is (and isn't)
Mermaid is a markdown-like syntax that compiles to SVG or PNG. You write a few lines of text, and a renderer produces a flowchart, sequence diagram, class diagram, ER diagram, Gantt chart, or state diagram. The syntax is intentionally minimal so non-designers can ship a usable diagram in under a minute.
What it isn't: a pixel-perfect illustration tool. You won't get hand-crafted infographic aesthetics. You will get a correct, version-controllable, diff-friendly diagram that renders identically for every reader.
Supported diagram types cover most engineering documentation needs:
| Diagram Type | Use Case |
|---|---|
| Flowchart | Request flow, business logic, decision trees |
| Sequence | API calls, service-to-service messaging |
| Class | Object models, module relationships |
| ER | Database schemas |
| State | Lifecycle, status machines |
| Gantt | Project timelines, release planning |
| Gitgraph | Branching strategy documentation |
The 5-minute setup
You don't need a new tool. You need a .md file and one CLI command.
Step 1: Install the Mermaid CLI (1 minute)
The official mermaid-cli wraps headless Chrome and renders .mmd or code-fenced markdown to images. Install it globally:
npm install -g @mermaid-js/mermaid-cli
Verify with mmdc --version. If you hit a Puppeteer error on Linux, install the required Chrome dependencies listed in the official troubleshooting guide.
Step 2: Author your first diagram (2 minutes)
Create a file called auth-flow.mmd:
sequenceDiagram
participant U as User
participant A as Auth Service
participant D as Database
U->>A: POST /login (email, password)
A->>D: SELECT user WHERE email=?
D-->>A: user record
A->>A: bcrypt.compare(password, hash)
alt valid credentials
A->>A: generate JWT (15min)
A-->>U: 200 OK + token
else invalid credentials
A-->>U: 401 Unauthorized
end
Render it:
mmdc -i auth-flow.mmd -o auth-flow.svg
Open the SVG in any browser. You now have a version-controlled, diff-friendly sequence diagram.
Step 3: Embed in your README (1 minute)
GitHub renders Mermaid code fences natively. Drop the same block into your README, no rendering step required:
```mermaid
sequenceDiagram
participant U as User
participant A as Auth Service
participant D as Database
U->>A: POST /login
A->>D: SELECT user
```
For GitLab, Bitbucket, and most docs frameworks, the same syntax works. If your static-site generator uses a different renderer (Docusaurus, MkDocs, Hugo), install the corresponding Mermaid plugin and the result is identical.
Step 4: Automate regeneration (1 minute)
Hand-rendering is fine for a single diagram. For a living architecture document, add an npm script:
{
"scripts": {
"docs:diagrams": "find ./diagrams -name '*.mmd' -exec mmdc -i {} -o {}.svg \;"
}
}
Run npm run docs:diagrams before committing, or wire it into your CI pipeline. A typical GitHub Actions step:
- name: Render diagrams
run: |
npm install -g @mermaid-js/mermaid-cli
find ./diagrams -name '*.mmd' -exec mmdc -i {} -o {}.svg \;
- name: Commit rendered diagrams
run: |
git config user.name "docs-bot"
git config user.email "docs@example.com"
git add diagrams/*.svg
git commit -m "docs: regenerate diagrams" || exit 0
git push
That's the whole loop: code changes, diagram regenerates, README stays accurate.
Generating diagrams from real code
Hand-writing Mermaid works, but it has the same drift problem as hand-drawing. The real win is extraction: read the code, emit the diagram.
Class diagrams from TypeScript
For a class diagram, you need three pieces per class: name, properties, methods. A 30-line Node script with the TypeScript compiler API is enough:
import * as ts from 'typescript';
import * as fs from 'fs';
function emit(sourcePath: string): string {
const source = fs.readFileSync(sourcePath, 'utf8');
const ast = ts.createSourceFile(sourcePath, source, ts.ScriptTarget.Latest, true);
const classes: string[] = [];
function visit(node: ts.Node) {
if (ts.isClassDeclaration(node) && node.name) {
const name = node.name.text;
const props = node.members
.filter(ts.isPropertyDeclaration)
.map(p => ` +${p.name?.getText()} ${(p.type as any)?.getText() ?? 'any'}`);
const methods = node.members
.filter(ts.isMethodDeclaration)
.map(m => ` +${m.name?.getText()}(${m.parameters.map(p => p.name.getText()).join(', ')})`);
classes.push(` class ${name} {\n${[...props, ...methods].join('\n')}\n }`);
}
ts.forEachChild(node, visit);
}
visit(ast);
return `classDiagram\n${classes.join('\n')}`;
}
console.log(emit(process.argv[2]));
Run it on any TS file and pipe the output to a .mmd file. The same pattern works for Python with ast, Go with go/parser, and Java with the JavaParser library. The extraction is mechanical; the rendering is free.
Flowcharts from route definitions
For an Express or FastAPI app, iterate over the route registrations and emit a flowchart node per endpoint:
import { Express } from 'express';
const routes: Array<{ method: string; path: string }> = [];
export function track(app: Express) {
['get', 'post', 'put', 'delete'].forEach(method => {
const original = app[method as keyof Express] as any;
app[method as keyof Express] = function (path: string, ...handlers: any[]) {
routes.push({ method: method.toUpperCase(), path });
return original.call(this, path, ...handlers);
};
});
}
export function emitRoutes(): string {
const lines = routes.map(r => ` ${r.path.replace(/[:*]/g, m => m === ':' ? 'id_' : '*')} -->|${r.method}| handler`);
return `flowchart LR\n Client --> Router\n Router -->|\"GET /\" | Root\n${lines.join('\n')}`;
}
Wire track(app) into your bootstrap, and your route diagram updates whenever a developer adds an endpoint.
Sequence diagrams from logs or traces
If you already export OpenTelemetry traces, a sequence diagram is just a transformation: list the spans, group by parent-child, and emit a sequenceDiagram block with one participant per service. A 50-line script against a Jaeger export gives you a real call graph for free.
Keeping diagrams in sync without manual effort
Three patterns work in production:
- Generated-on-CI, committed-to-repo. Simplest. CI regenerates SVGs and commits them. Reviewers see diagram diffs in pull requests.
- Generated-on-CI, served from CDN. No repo bloat. Docs site pulls the latest SVG from an artifact store. Loses git diff visibility.
- Generated-on-demand, rendered in-browser. Pure markdown. The Mermaid JS library renders in the reader's browser. Lightest setup, slowest initial paint, no diagram in README previews on GitHub.
For most teams, option 1 is the right starting point. It is what most of the popular open-source projects use, including the Kubernetes and ArgoCD ecosystems.
A note on complexity
Mermaid scales surprisingly well, but a single diagram with more than roughly 30 nodes starts to hurt readability. If your generated architecture diagram is unprintable, you are documenting the wrong abstraction. Split it. One diagram per bounded context, per service tier, or per request flow. The same extraction script can emit multiple .mmd files filtered by package, namespace, or tag.
Where to go from here
You now have a working setup: Mermaid CLI installed, a script that extracts diagrams from your codebase, and a CI step that keeps the rendered output fresh. The next bottleneck is usually authoring speed: writing the extraction logic for every diagram type you care about takes time, and the syntax for each Mermaid diagram type is a small but real learning curve.
DocPilot handles the generation layer for you. Connect a GitHub repository, point it at the folders or files you want documented, and it produces setup guides, architecture overviews, and API reference docs with embedded Mermaid diagrams that regenerate on every push. The extraction rules for class diagrams, sequence diagrams, and route flowcharts are built in, so you skip the scripting step entirely and get version-controlled, always-current documentation in the time it would have taken to draw a single flowchart by hand. Start with the free tier and wire it into a single repo to see the output for your own codebase.
Read next
ai-chat
How to Add AI Chat to Your Product Documentation in an Afternoon
Your users are searching your docs with the wrong keywords. Here's how to ship an AI chat layer over them before lunch.
Read
migration
Migrate to AI Documentation in 30 Days: A Complete Plan
Most documentation migrations die in week three. Here is the 30-day plan that survives contact with reality — week-by-week tasks, scripts, and rollout tactics that turn AI docs from a side project into your team's default.
Read
tutorials
Live Coding: Setting Up DocPilot on a Real Repository
A live-coding walkthrough that connects DocPilot to a real GitHub repository, generates the first README and API docs, and wires up webhook sync — all in one sitting.
Read