Markdown Diagrams Tutorial: Drawing Flowcharts, Sequence Diagrams, and Gantt Charts with Mermaid
Wait, Markdown Can Draw Diagrams? A Mermaid Primer
When writing technical docs, you often need diagrams — flowcharts, architecture diagrams, sequence diagrams, that kind of thing. The traditional approach is to fire up draw.io or Visio, create the diagram, export it as an image, and embed it. But this creates a real problem: the diagram lives separately from the text. Update the docs, and you have to go back into the diagramming tool and update the graphic too. Over time, they drift out of sync.
Mermaid solves exactly this problem. It lets you write diagram definitions as plain text right inside your Markdown, and the renderer draws the diagram for you automatically. The code sits alongside your documentation, version control is a breeze, and changing a node is as simple as editing a line of text.
Put simply, Mermaid is a JavaScript-based diagramming library that uses a Markdown-like text syntax to define all sorts of charts and diagrams. GitHub has natively supported Mermaid since 2022, and nowadays tools like Typora, Obsidian, GitLab, and VS Code can all render Mermaid diagrams out of the box.
Basic Syntax: The mermaid Code Block
Using Mermaid in Markdown is straightforward — just write a code block tagged with mermaid:
```mermaid
flowchart TD
A[Start] --> B{Continue?}
B -->|Yes| C[Process]
B -->|No| D[End]
C --> D
When rendered, this produces a top-to-bottom flowchart with a decision node and two branches. The core workflow is just three steps:
1. Open a code block with ` ```mermaid `
2. Define your diagram using Mermaid syntax inside it
3. Save the file — the renderer generates an SVG chart automatically
One thing worth knowing: Mermaid uses `%%` for comments, similar to the double-slash comments in many programming languages:
```markdown
```mermaid
flowchart TD
%% This is a comment, it won't appear in the diagram
A --> B
## Flowcharts — The Most Common Diagram Type
Flowcharts are the most frequently used diagram type in Mermaid. To define one, start with the `flowchart` keyword followed by a direction:
| Direction | Keyword | Description |
|-----------|---------|-------------|
| Top to bottom | `TD` or `TB` | Top-Down / Top-Bottom |
| Bottom to top | `BT` | Bottom-Top |
| Left to right | `LR` | Left-Right |
| Right to left | `RL` | Right-Left |
### Node Shapes
The shape of a node is determined by the symbols wrapping its text — a detail many tutorials gloss over:
```markdown
```mermaid
flowchart LR
A[Rectangle] --> B(Rounded rectangle)
B --> C{Diamond decision}
C --> D[(Database)]
D --> E[[Subroutine]]
E --> F>Asymmetric shape]
- `[]` — Standard rectangle
- `()` — Rounded rectangle
- `{}` — Diamond (typically used for decisions)
- `[()]` — Cylinder (database)
- `[[]]` — Subroutine
- `>` — Asymmetric shape
Honestly, the ones you will use most of the time are `[]`, `()`, and `{}`. The rest are there when you need them.
### Connection Lines
There are several ways to write connection lines, each corresponding to a different line style and arrowhead:
```markdown
```mermaid
flowchart LR
A --> B %% Solid line with arrow
C --- D %% Solid line, no arrow
E -->|text| F %% Solid arrow with label
G -.-> H %% Dashed line with arrow
I ==> J %% Thick line with arrow
| Syntax | Result |
|--------|--------|
| `-->` | Solid line + arrow |
| `---` | Solid line, no arrow |
| `-->\|text\|` | Solid line + arrow + label text |
| `-.->` | Dashed line + arrow |
| `==>` | Thick line + arrow |
### Subgraphs
When a flowchart gets complex, you can use `subgraph` to group related nodes together:
```markdown
```mermaid
flowchart TB
subgraph Client
A[Open page] --> B[Fill form]
end
subgraph Server
C[Receive request] --> D[Validate data]
D --> E[Write to database]
end
B --> C
E --> F[Return result]
My personal rule of thumb: once a flowchart exceeds 8 nodes, I start thinking about using subgraphs to partition it. Otherwise the chart becomes a tangled mess and readability tanks.
### `flowchart` vs `graph` — What's the Difference?
You might come across older articles that use `graph` instead of `flowchart`. That is because early versions of Mermaid only had the `graph` keyword, and `flowchart` was added later as a replacement. The key differences:
- `flowchart` supports more connection line types (like bidirectional arrows `<-->`)
- `flowchart` allows direct connections between subgraphs
- `graph` is the legacy syntax — it still works but is not recommended for new projects
If you are just getting started, go straight for `flowchart`. No need to overthink it.
## Sequence Diagrams — Interaction Flows
Sequence diagrams are great for describing the order of interactions between multiple actors — think request-response flows between a client and server, or the step-by-step operations between a user and a system.
```markdown
```mermaid
sequenceDiagram
participant User
participant Frontend
participant Backend
participant Database
User->>Frontend: Enter username and password
Frontend->>Backend: Send login request
Backend->>Database: Query user info
Database-->>Backend: Return user data
Backend-->>Frontend: Return login result
Frontend-->>User: Display login success
### Arrow Types in Sequence Diagrams
| Syntax | Meaning |
|--------|---------|
| `->>` | Solid arrow (request) |
| `-->>` | Dashed arrow (response/return) |
| `--)` | Solid open arrow |
| `--)` | Dashed open arrow |
| `-x` | Solid arrow with X (async) |
### Advanced Usage: Loops and Conditionals
You can use keywords like `loop`, `alt`, and `opt` inside sequence diagrams to represent loops and conditional branches:
```markdown
```mermaid
sequenceDiagram
loop Every 5 seconds
Client->>Server: Heartbeat check
Server-->>Client: Confirm alive
end
alt Auth succeeded
Server-->>Client: Return Token
else Auth failed
Server-->>Client: Return error
end
The `note` keyword lets you add annotations in sequence diagrams, positioned above or to the right of a participant:
```markdown
```mermaid
sequenceDiagram
participant A as Alice
participant B as Bob
Note over A,B: This note spans both participants
A->>B: Hello
Note right of B: This note appears to the right of Bob
## Gantt Charts — Project Scheduling
Gantt charts are extremely useful for project management and task scheduling. Mermaid's Gantt chart syntax is fairly intuitive:
```markdown
```mermaid
gantt
title Project Development Plan
dateFormat YYYY-MM-DD
axisFormat %m/%d
section Requirements
Requirements research :done, req1, 2024-01-01, 10d
Requirements review :active, req2, after req1, 3d
section Development
Frontend development :dev1, after req2, 15d
Backend development :dev2, after req2, 12d
section Testing & Launch
Integration testing :test1, after dev1, 7d
Official launch :milestone, launch, after test1, 0d
Key syntax points:
- `dateFormat` — Sets the date format
- `section` — Task grouping
- `done` / `active` — Task status (completed / in progress)
- `crit` — Critical task (highlighted in red)
- `milestone` — Milestone (diamond marker)
- `after taskID` — Indicates a task starts after another one finishes
One gotcha I ran into: `dateFormat` must match the actual date format you write. If you set `YYYY-MM-DD` but write a date like `01/15/2024`, the chart will simply fail to render. And the error message is not exactly helpful, so tracking it down can be frustrating.
## Class Diagrams — Code Structure
Class diagrams are ideal for describing class relationships in object-oriented design. If you are writing technical docs for a Java, C#, or TypeScript project, these come in handy.
```markdown
```mermaid
classDiagram
class Animal {
+String name
+int age
+makeSound() void
}
class Dog {
+String breed
+fetch() void
}
class Cat {
+bool isIndoor
+purr() void
}
Animal <|-- Dog
Animal <|-- Cat
How to represent relationships between classes:
| Syntax | Relationship |
|--------|-------------|
| `<\|--` | Inheritance |
| `*--` | Composition |
| `o--` | Aggregation |
| `-->` | Association |
| `--\|>` | Implementation |
| `..>` | Dependency |
Class member access modifiers: `+` is public, `-` is private, `#` is protected.
## State Diagrams
State diagrams describe how an object transitions between different states. They are common in embedded development, game logic, and workflow design.
```markdown
```mermaid
stateDiagram-v2
[*] --> Draft
Draft --> UnderReview: Submit application
UnderReview --> Approved: Review passed
UnderReview --> Rejected: Review rejected
Rejected --> Draft: Edit and resubmit
Approved --> [*]
`[*]` represents the start and end states. `stateDiagram-v2` is the newer keyword, supporting more features than the older `stateDiagram` (such as nested states and notes).
You can also use `note` to add explanatory text to state diagrams:
```markdown
```mermaid
stateDiagram-v2
state "Loading" as loading
[*] --> loading
loading --> Success: Request completed
loading --> Failed: Request error
note right of loading
Display loading animation
Waiting for server response
end note
## Pie Charts
Pie charts are the simplest Mermaid diagram type, perfect for showing proportional distributions:
```markdown
```mermaid
pie title Frontend Framework Usage Share
"React" : 40
"Vue" : 30
"Angular" : 15
"Other" : 15
The syntax is just a few lines: start with the `pie` keyword, write your title after `title`, then add one `"name" : value` pair per line. The value can be a percentage or a raw number — Mermaid calculates the proportions automatically.
## ER Diagrams (Entity-Relationship Diagrams)
ER diagrams describe relationships between entities in a database. If you do backend development or database design, you will reach for these often:
```markdown
```mermaid
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER {
string name
string email
int age
}
ORDER {
int id
string status
date created_at
}
LINE-ITEM {
string product_name
int quantity
float price
}
Relationship notation:
| Symbol | Meaning |
|--------|---------|
| `\|\|--\|\|` | One-to-one (required) |
| `\|\|--o{` | One-to-many (optional) |
| `\|\|--\|{` | One-to-many (required) |
| `}o--o{` | Many-to-many |
## Which Diagram Should You Use? A Quick Decision Guide
| Scenario | Recommended Diagram | Keyword |
|----------|---------------------|---------|
| Business process / Approval flow | Flowchart | `flowchart` |
| System interaction / API calls | Sequence diagram | `sequenceDiagram` |
| Project scheduling / Task planning | Gantt chart | `gantt` |
| Code architecture / Inheritance | Class diagram | `classDiagram` |
| State machine / Workflow | State diagram | `stateDiagram-v2` |
| Proportional distribution | Pie chart | `pie` |
| Database design | ER diagram | `erDiagram` |
If you are not sure which one to pick, a flowchart covers most scenarios. Sequence diagrams come in second, especially when you are writing web development or microservices documentation.
## Platform Support for Mermaid
How Mermaid renders depends on the tool you are using, and support varies quite a bit across platforms:
| Platform | Support | Notes |
|----------|---------|-------|
| **GitHub** | Native | Auto-renders in README, Issues, and PRs |
| **GitLab** | Native | Similar to GitHub |
| **Typora** | Native | Live preview, best rendering quality |
| **Obsidian** | Native | Make sure Mermaid is enabled in settings |
| **VS Code** | Plugin required | Recommend "Markdown Preview Mermaid Support" extension |
| **Notion** | Limited | Needs to be embedded via a code block |
| **Feishu Docs** | Not supported | Export as image and insert manually |
I have run into this issue in practice: the same Mermaid code rendered fine in Typora, but after pushing to GitHub, a connection line between subgraphs simply vanished. After investigating, it turned out GitHub's Mermaid version was older than Typora's, and some newer syntax was not yet supported. So if your docs will be used across platforms, it is worth previewing on the target platform first.
I recommend using the [Mermaid Live Editor](https://mermaid.live) to test syntax online — write code on the left, see a live preview on the right, and export to SVG or PNG. Very convenient.
## Troubleshooting Common Issues
### Diagram not showing up?
The most common causes:
1. **Wrong code block marker** — Make sure it is ` ```mermaid `, not ` ```markdown ` or ` ```text `
2. **Syntax typos** — Mermaid is case-insensitive for keywords, but any spelling mistake will cause rendering to fail silently
3. **Indentation issues** — While Mermaid is not as indentation-strict as Python, nodes inside a subgraph do need to be aligned
### Special characters rendering incorrectly?
If your node text contains symbols like `()`, `{}`, or `[]`, wrap the text in quotes:
```markdown
```mermaid
flowchart TD
A["Process data(x, y)"] --> B
### Diagram too large or too small?
Mermaid automatically adjusts the size based on content. If it feels too large, try reducing the number of nodes. If you need precise control over styling, Mermaid supports `classDef` for custom node styles — though that falls into advanced territory.
## References
- [Mermaid Official Docs — Introduction](https://mermaid.js.org/intro/): Mermaid syntax reference and getting started guide
- [GitHub Blog — Include Diagrams in Markdown Files with Mermaid](https://github.blog/developer-skills/github/include-diagrams-markdown-files-mermaid/): GitHub's official Mermaid support announcement
- [GitHub Docs — Creating Diagrams](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-diagrams): Mermaid usage documentation on the GitHub platform