How to Create a Flowchart with Mermaid.js — Complete Guide
Step-by-step guide to creating flowcharts with Mermaid.js. Learn node shapes, edge types, styling, subgraphs, and best practices with copy-paste examples.
Introduction to Mermaid Flowcharts
Flowcharts are the most popular diagram type in Mermaid.js, and for good reason. They're versatile enough to represent everything from simple processes to complex decision trees, and Mermaid makes them incredibly easy to create with just a few lines of text.
In this guide, you'll learn every aspect of Mermaid flowcharts — from basic syntax to advanced features like subgraphs, styling, and interaction.
Basic Flowchart Syntax
Every Mermaid flowchart starts with a direction declaration:
graph TD
A[Start] --> B[Process]
B --> C[End]Try in Editor →The direction keyword controls layout:
- TD or TB — Top to Bottom (default, most common)
- LR — Left to Right (great for pipelines)
- BT — Bottom to Top
- RL — Right to Left
You can also use flowchart instead of graph for the newer syntax with more features:
flowchart LR
A[Start] --> B[Process] --> C[End]Try in Editor →Node Shapes
Mermaid provides many node shapes to convey meaning visually:
flowchart TD
A[Rectangle - Default]
B(Rounded Rectangle)
C([Stadium Shape])
D[[Subroutine]]
E[(Database / Cylinder)]
F((Circle))
G{Diamond / Decision}
H{{"Hexagon"}}
I>Asymmetric / Flag]
J[/Parallelogram/]
K[\Parallelogram Alt\]
L[/Trapezoid\]
M[\Trapezoid Alt/]Try in Editor →When to Use Each Shape
- Rectangle (
[text]): Standard process steps - Rounded (
(text)): Start/end terminals - Diamond (
{text}): Decision points (yes/no, true/false) - Cylinder (
[(text)]): Databases or storage - Circle (
((text))): Connectors or junction points - Stadium (
([text])): Terminal events - Parallelogram (
[/text/]): Input/output operations
Edge Types — Connecting Nodes
Edges (arrows and lines) are how you connect nodes. Mermaid offers many styles:
flowchart LR
A -->|Arrow| B
C ---|Line| D
E -.->|Dotted arrow| F
G ==>|Thick arrow| H
I --o|Circle end| J
K --x|Cross end| LTry in Editor →Edge Length
You can control edge length by adding extra dashes:
flowchart TD
A --> B
A ----> C
A -------> DTry in Editor →Longer edges push nodes further apart, which helps with layout.
Labeled Edges
Add labels to describe the relationship:
flowchart TD
A{Is it raining?}
A -->|Yes| B[Take umbrella]
A -->|No| C[Enjoy the sun]Try in Editor →You can also use this syntax: A -- "label text" --> B
Practical Example: CI/CD Pipeline
Let's build a real-world flowchart — a CI/CD deployment pipeline:
flowchart LR
A([Developer pushes code]) --> B[Run Linter]
B --> C[Run Unit Tests]
C --> D{Tests pass?}
D -->|Yes| E[Build Docker Image]
D -->|No| F[Notify Developer]
F --> A
E --> G[Push to Registry]
G --> H{Environment?}
H -->|Staging| I[Deploy to Staging]
H -->|Production| J[Manual Approval]
J --> K[Deploy to Production]
I --> L[Run E2E Tests]
L --> M{E2E pass?}
M -->|Yes| J
M -->|No| FTry in Editor →This single text block produces a complete CI/CD visualization that's easy to update when the process changes.
Subgraphs — Grouping Related Nodes
Subgraphs let you group nodes into labeled sections:
flowchart TB
subgraph Frontend
A[React App] --> B[API Client]
end
subgraph Backend
C[Express Server] --> D[Business Logic]
D --> E[(PostgreSQL)]
end
B --> CTry in Editor →Nested Subgraphs
You can nest subgraphs for complex architectures:
flowchart TB
subgraph Cloud["AWS Cloud"]
subgraph VPC["VPC"]
subgraph Public["Public Subnet"]
ALB[Load Balancer]
end
subgraph Private["Private Subnet"]
ECS[ECS Service]
RDS[(RDS Database)]
end
end
end
User([User]) --> ALB --> ECS --> RDSTry in Editor →Subgraph Direction
Each subgraph can have its own direction:
flowchart LR
subgraph TOP
direction TB
A --> B
end
subgraph BOTTOM
direction TB
C --> D
end
TOP --> BOTTOMTry in Editor →Styling Your Flowcharts
Inline Styles
Apply CSS-like styles directly to nodes:
flowchart LR
A[Critical]:::critical --> B[Normal] --> C[Success]:::success
classDef critical fill:#ff6b6b,stroke:#c0392b,color:white
classDef success fill:#51cf66,stroke:#2f9e44,color:whiteTry in Editor →Style by Node ID
flowchart TD
A[Important Node]
style A fill:#f9f,stroke:#333,stroke-width:4pxTry in Editor →Common Style Patterns
Here's a reusable set of class definitions:
flowchart TD
A[Start]:::start --> B[Process]:::process --> C{Decision}:::decision
C -->|Yes| D[Success]:::success
C -->|No| E[Error]:::error
classDef start fill:#667eea,stroke:#5a67d8,color:white
classDef process fill:#f7fafc,stroke:#cbd5e0
classDef decision fill:#faf089,stroke:#d69e2e
classDef success fill:#c6f6d5,stroke:#38a169
classDef error fill:#fed7d7,stroke:#e53e3eTry in Editor →Advanced Techniques
Multiple Links from One Node
flowchart TD
A[Router] --> B[Handler 1]
A --> C[Handler 2]
A --> D[Handler 3]
B & C & D --> E[Response]Try in Editor →The & operator connects multiple nodes at once.
Special Characters in Labels
Use quotes for special characters:
flowchart LR
A["Node with (parentheses)"] --> B["Contains {braces}"]
B --> C["Has #quot;quotes#quot;"]Try in Editor →Comments
Add comments with %%:
flowchart TD
%% This is a comment
A --> B
%% Another comment
B --> CTry in Editor →Best Practices for Flowcharts
- Choose direction wisely. Use LR for processes/pipelines, TD for hierarchies and decision trees.
- Use meaningful node IDs. Instead of
A,B,C, trystart,validate,deploy. It makes the source readable.
- Label your edges. Decision diamonds should always have labeled outputs (Yes/No, True/False, Success/Error).
- Keep it focused. A flowchart with more than 15-20 nodes becomes hard to read. Split complex flows into multiple diagrams.
- Use subgraphs for logical grouping. They make large diagrams scannable.
- Apply consistent styling. Define class definitions once and reuse them. Color-code by category (errors = red, success = green, etc.).
- Test incrementally. Build your flowchart step by step, rendering after each addition. This makes it easy to catch syntax errors.
Common Mistakes and Fixes
Problem: Nodes not connecting properly.
Fix: Make sure node IDs are consistent. A and a are different nodes.
Problem: Text with special characters breaks rendering.
Fix: Wrap text in double quotes: A["My (special) text"]
Problem: Layout is messy with too many crossing lines.
Fix: Rearrange node order in the source. Mermaid renders top-to-bottom in the order nodes appear. Also try changing direction (LR vs TD).
Problem: Subgraph edges look wrong.
Fix: Connect to specific nodes inside subgraphs, not the subgraph itself.
Conclusion
Mermaid flowcharts are powerful enough for real-world documentation yet simple enough to create in seconds. Start with basic nodes and arrows, then progressively add shapes, styles, and subgraphs as needed. The key advantage is maintainability — when your process changes, updating a few lines of text is infinitely easier than rearranging boxes in a drawing tool.