Skip to content

Mermaid Diagram Syntax Reference

Vorno renders Mermaid diagrams natively as beautiful themed SVGs. Use this reference for syntax details.

Mermaid code blocks may start with YAML frontmatter. Vorno accepts the frontmatter for compatibility and renders the diagram syntax that follows it. For visible chart titles, prefer diagram-level title syntax (for example, title "Monthly Revenue" in xychart-beta).

---
title: Example Diagram
---
graph LR
A --> B

Header: graph LR (left-right, preferred) or graph TD (top-down) Directions: LR (preferred), RL, TD, TB, BT

Syntax Shape
A[text] Rectangle
A(text) Rounded rectangle
A{text} Diamond (decision)
A([text]) Stadium
A((text)) Circle
A[[text]] Subroutine
A[(text)] Cylinder (database)
A{{text}} Hexagon
A>text] Asymmetric flag
A[/text\] Trapezoid
A[\text/] Trapezoid (alt)
A(((text))) Double circle
Syntax Style
--> Solid arrow
--- Solid line (no arrow)
-.-> Dotted arrow
-.- Dotted line
==> Thick arrow
=== Thick line
<--> Bidirectional solid
<-.-> Bidirectional dotted
<==> Bidirectional thick
graph LR
A -->|label text| B
C -- label text --> D
graph LR
subgraph Backend
API --> DB
end
subgraph Frontend
UI --> API
end
Client --> UI
graph TD
subgraph backend-services [Backend Services]
direction LR
API --> Cache
API --> DB
end
graph LR
A[Start]:::highlight --> B[End]
classDef highlight fill:#f9f,stroke:#333
style B fill:#bbf,stroke:#333
graph LR
A --> B --> C --> D
graph LR
A & B --> C & D

Header: stateDiagram-v2

stateDiagram-v2
[*] --> Idle
Idle --> Processing: start
Processing --> Complete: done
Processing --> Error: fail
Complete --> [*]
Error --> Idle: retry
stateDiagram-v2
state "Waiting for input" as Waiting
Waiting --> Processing
stateDiagram-v2
state "Active" as Active {
Running --> Paused: pause
Paused --> Running: resume
}
[*] --> Active
Active --> [*]: complete
stateDiagram-v2
direction LR
[*] --> A --> B --> [*]

Header: sequenceDiagram

Syntax Meaning
->> Solid line, solid arrowhead
-->> Dotted line, solid arrowhead
-) Solid line, open arrowhead (async)
--) Dotted line, open arrowhead
-x Solid line with X (lost message)
--x Dotted line with X
sequenceDiagram
participant C as Client
participant S as Server
participant DB as Database
C->>S: POST /api/users
S->>DB: INSERT user
DB-->>S: OK
S-->>C: 201 Created
sequenceDiagram
Client->>+Server: Request
Server->>+Database: Query
Database-->>-Server: Results
Server-->>-Client: Response
sequenceDiagram
Alice->>Bob: Hello
Note right of Bob: Bob thinks
Bob-->>Alice: Hi!
Note over Alice,Bob: Conversation complete
sequenceDiagram
loop Every minute
Client->>Server: Heartbeat
Server-->>Client: ACK
end
sequenceDiagram
Client->>Server: Request
alt Success
Server-->>Client: 200 OK
else Failure
Server-->>Client: 500 Error
end
sequenceDiagram
opt If cached
Server-->>Client: Cached response
end
sequenceDiagram
par Parallel requests
Client->>ServiceA: Request A
and
Client->>ServiceB: Request B
end

Header: classDiagram

classDiagram
class Animal {
+String name
+int age
+makeSound() void
+move(distance) void
}
Symbol Meaning
+ Public
- Private
# Protected
~ Package/Internal
Syntax Meaning
<|-- Inheritance (extends)
*-- Composition (contains)
o-- Aggregation (has)
--> Association
..> Dependency
..|> Realization (implements)
-- Link (solid)
.. Link (dashed)
classDiagram
Customer "1" --> "*" Order : places
Order "1" *-- "1..*" LineItem : contains
classDiagram
class Animal {
<<abstract>>
+String name
+int age
+makeSound()* void
}
class Dog {
+String breed
+bark() void
}
class Cat {
+bool indoor
+meow() void
}
Animal <|-- Dog
Animal <|-- Cat
classDiagram
class Service {
<<interface>>
+start() void
+stop() void
}
class Logger {
<<singleton>>
-instance Logger
+log(msg) void
}

Header: erDiagram

erDiagram
USER ||--o{ ORDER : places
ORDER ||--|{ LINE_ITEM : contains
PRODUCT ||--o{ LINE_ITEM : "is in"
Left Right Meaning
|| || Exactly one to exactly one
|| o| Exactly one to zero or one
|| o{ Exactly one to zero or more
|| |{ Exactly one to one or more
o| o| Zero or one to zero or one
o| o{ Zero or one to zero or more
o{ o{ Zero or more to zero or more
erDiagram
USER {
int id PK
string email UK
string name
datetime created_at
}
ORDER {
int id PK
int user_id FK
decimal total
date created_at
}
USER ||--o{ ORDER : places

Common attribute markers:

  • PK - Primary Key
  • FK - Foreign Key
  • UK - Unique Key
erDiagram
CUSTOMER {
int id PK
string email UK
string name
string phone
}
ORDER {
int id PK
int customer_id FK
date order_date
string status
}
PRODUCT {
int id PK
string name
decimal price
int stock
}
LINE_ITEM {
int id PK
int order_id FK
int product_id FK
int quantity
decimal unit_price
}
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE_ITEM : contains
PRODUCT ||--o{ LINE_ITEM : "included in"

Header: xychart-beta (vertical charts) or xychart-beta horizontal (horizontal charts)

Use XY charts for metrics, trends, comparisons, and simple bar/line visualizations.

Syntax Meaning
title "Chart Title" Optional chart title
x-axis [A, B, C] Categorical X axis
x-axis "Label" [A, B, C] Categorical X axis with title
x-axis 0 --> 100 Numeric X axis range
x-axis "Label" 0 --> 100 Numeric X axis with title
y-axis "Label" 0 --> 100 Numeric Y axis with title/range
bar [10, 20, 30] Bar series
line [12, 18, 28] Line series
xychart-beta
title "Monthly Revenue"
x-axis [Jan, Feb, Mar, Apr]
y-axis "Revenue ($k)" 0 --> 100
bar [25, 45, 60, 80]
xychart-beta
title "Latency Trend"
x-axis [Mon, Tue, Wed, Thu, Fri]
y-axis "Latency (ms)" 0 --> 500
line [320, 280, 240, 210, 180]
xychart-beta
title "Signups vs Activations"
x-axis [Week 1, Week 2, Week 3, Week 4]
y-axis "Users" 0 --> 1000
bar [420, 560, 690, 820]
line [210, 330, 520, 700]
xychart-beta horizontal
title "Issue Counts by Severity"
x-axis [Low, Medium, High, Critical]
y-axis "Issues" 0 --> 50
bar [42, 28, 12, 4]

Prefer Horizontal (Landscape) Orientations

Section titled “Prefer Horizontal (Landscape) Orientations”

IMPORTANT: Use horizontal layouts (LR, RL) whenever possible. Horizontal diagrams are much easier to view and navigate in the UI.

  • Flowcharts: Use graph LR (left-right) instead of graph TD (top-down)
  • State Diagrams: Add direction LR after the header
  • Sequence Diagrams: Naturally horizontal, no changes needed
  • Class Diagrams: For wide hierarchies, consider splitting into multiple horizontal diagrams
  • ER Diagrams: Naturally horizontal, no changes needed

Only use vertical layouts (TD, BT) when:

  • The diagram is inherently hierarchical (org charts, tree structures)
  • The vertical layout is significantly clearer than horizontal
  • The diagram has very few nodes (3-4 max)

One concept per diagram. If a diagram gets complex, split it into multiple diagrams.

graph LR
A[User submits form] --> B{Validation}
B -->|Valid| C[Save to database]
B -->|Invalid| D[Show errors]

Horizontal (preferred):

  • LR (left-right): DEFAULT - Use for flows, pipelines, state machines, processes, and most diagrams
  • RL (right-left): Reverse flows (when semantically meaningful)

Vertical (use sparingly):

  • TD (top-down): Only for hierarchies, inheritance, org charts where vertical structure is essential
  • BT (bottom-top): Only for dependencies pointing upward

Use the mermaid_validate tool to check syntax before outputting complex diagrams:

mermaid_validate({ code: "graph TD\n A --> B" })
  1. Missing direction: Always include direction in flowcharts (graph TD, not just graph)
  2. Unbalanced brackets: Ensure all [, (, { are properly closed
  3. Special characters in labels: Use quotes for labels with special characters
  4. Invalid arrow syntax: Check the arrow type table above

For labels with special characters, wrap in quotes:

graph LR
A["Label with (parentheses)"] --> B["Label with [brackets]"]