This is an advanced guide to building mermaid diagrams
You should test any mermaid diagrams you draw: 1. extract just the mermaid diagram from the markdown file, 2. call mermaid-cli to convert it to a png file 3. check for any syntax errors returned 4. read the png file to see if it looks like what was wanted 5. delete the png file if all is OK
There are two ways to call mermaid-cli - (1) specify -
as the filename and pipe the contents in:
cat << EOF | npx -p @mermaid-js/mermaid-cli mmdc -s 3 -i - -o tmp.png
graph TD
A[Client] --> B[Load Balancer]
EOF
or (2) write the output to a temporary file, then pass the name as a parameter:
npx -p @mermaid-js/mermaid-cli mmdc -s 3 -i tmp.md -o tmp.png
Input can be:
.mmd
with just mermaid content.md
with embedded mermaid diagrams - note if you specify output as tmp.png
it will make a file per diagram, tmp-1.png
, tmp-2.png
and so onYou can get more help for mermaid-cli with
npx -p @mermaid-js/mermaid-cli mmdc -h
npx -p @mermaid-js/mermaid-cli mmdc -i tmp.mmd -o tmp.png
then read the PNGconfig: look: handDrawn
in frontmatterclassDef invisible fill:#0000,stroke:#0000;
NodeName@{shape: diamond, label: "Decision"}
If you need to configure a mermaid diagram - standalone or embedded in a markdown file - you can do it with YAML frontmatter:
---
config:
look: handDrawn
theme: forest
---
graph LR
A --> B
You can set a theme in the frontmatter as above - unless instructed otherwise you should probably leave this as the default, or use base
which then allows you to customize things like the main colour scheme:
---
config:
theme: base
themeVariables:
primaryColor: 'red'
primaryTextColor: 'white'
fontSize: 32px
lineColor: 'green'
---
graph TD
A --> B
Theme variables if you need them are at https://mermaid.js.org/config/theming.html#theme-variables
Use NodeName@{shape: shapeName, label: "Label"}
for custom shapes:
flowchart TB
decision@{shape: diamond, label: "Decision"}
database@{shape: cyl, label: "Database"}
document@{shape: doc, label: "Document"}
input@{shape: lean-r, label: "Input/Output"}
A powerful technique for grouping related nodes without visual borders:
flowchart LR
%% Define invisible style
classDef invisible fill:#0000, stroke:#0000;
%% Group related components invisibly
subgraph api_layer[" "]
api1[API Gateway]
api2[Auth Service]
api3[Rate Limiter]
end
subgraph services[" "]
svc1[User Service]
svc2[Order Service]
svc3[Payment Service]
end
%% Apply invisible style
class api_layer,services invisible;
%% Connections
api1 --> svc1
api1 --> svc2
api2 --> svc1
api3 --> api1
This technique:
[" "]
to hide subgraph titlesDefine reusable styles:
flowchart TB
classDef primary fill:#1e40af,stroke:#1e3a8a,color:#fff;
classDef danger fill:#dc2626,stroke:#b91c1c,color:#fff;
start[Start]:::primary
error[Error]:::danger
start --> error
sequenceDiagram
actor User
participant API
participant DB as Database
%% Grouping with boxes
box rgba(100,100,255,0.1) Frontend
participant UI
participant Cache
end
%% Parallel execution
par Process A
API->>DB: Query users
and Process B
API->>Cache: Check cache
end
%% Conditional flow
alt Cache hit
Cache-->>API: Return cached data
else Cache miss
DB-->>API: Return fresh data
end
Use linkStyle to style specific edges (numbered in order of definition):
flowchart LR
A[Start] --> B[Process]
B --> C[End]
linkStyle 0 stroke:#ff3,stroke-width:4px
linkStyle 1 stroke:#f9f,stroke-width:2px,stroke-dasharray: 5 5
classDef
at the top rather than inline stylesclassDef
with semantic names (primary, error)