Practical diagram guide
Share URL API: build mermaid.tools links from your own data
Updated
Generate a mermaid.tools link from org chart records or any diagram data. URL format, state payload fields, JavaScript and Python examples, and read-only embeds.
How a share link carries a diagram
Every diagram in mermaid.tools can travel inside its own URL. There is no API key, no account and no server-side document: the editor reads the diagram out of the address bar when the page loads.
A link has three parts.
https://www.mermaid.tools/#state=N4IgbiBcCMA0IGMD2ATAplEAzANkg7g...
<------ editor ------><- key -><--------- payload --------->The payload is a JSON object describing the editor state, compressed with LZ-String through compressToEncodedURIComponent. That function emits only characters that are already URL-safe, so the result needs no further encoding. Because the payload sits in the URL fragment, after the #, browsers never send it to the server.
Reading a link back is the same two steps in reverse: take everything after #state=, run decompressFromEncodedURIComponent, then parse the JSON.
The state payload
Only code is required. Anything you leave out keeps the editor default, so the smallest useful payload is {"v":1,"code":"flowchart TB\n A --> B"}. Unknown keys are ignored, and a value of the wrong type falls back to the default instead of failing the load.
| Key | Type | What it sets |
|---|---|---|
v | number | Payload version. Send 1. |
code | string | The Mermaid source. This is the diagram. |
type | string | Diagram keyword for the toolbar picker, such as flowchart, sequenceDiagram, erDiagram or gantt. |
theme | string | One of default, dark, forest, neutral, base, high-contrast, sepia, monokai, solarized-light, solarized-dark, dracula, nord. |
dir | string | Layout direction override: TB, BT, LR, RL or TD. |
eng | string | Layout engine, dagre or elk. |
sp | object | Spacing in pixels, with the keys rank, node, edge, subgraph, padding and margin. |
cv | string | Edge curve, such as basis, linear or step. |
ct | object | Custom Mermaid theme variables, for example {"primaryColor":"#dbeafe"}. Overrides theme. |
cn | object | Canvas background: bg (grid, lines, blueprint, solid or none), plus bgColor and gridSize. |
ve | boolean | Open with visual edit mode already on. |
hl | boolean | Open with the hybrid org layout on. |
hd | number | Manager depth used by the hybrid layout. |
Turn your records into org chart source
An org chart is a flowchart whose arrows run from a manager to a report. Two passes over your employee table are enough: declare every person, then draw every reporting line.
Derive each node identifier from a stable primary key rather than from the display name. Renaming someone then leaves the chart wired the same way, and two people who share a name stay separate. An identifier may contain only letters, digits and underscores.
flowchart TB
n1["Dana Whitfield<br/>Chief Executive"]
n2["Sam Okafor<br/>VP Engineering"]
n3["Lena Bright<br/>VP Finance"]
n1 --> n2
n1 --> n3Labels sit inside double quotes, so a quotation mark in someone's name has to be written as ". A <br/> starts a second line, which is how a job title goes under a name. The same shape covers any hierarchy: a category tree, a bill of materials, a folder listing.
Build a link in JavaScript
Install lz-string from npm. This code runs unchanged in Node and in the browser.
import LZString from 'lz-string';
const EDITOR = 'https://www.mermaid.tools/';
const nodeId = key => 'n' + String(key).replace(/[^A-Za-z0-9_]/g, '_');
const label = text => String(text).replace(/&/g, '&').replace(/"/g, '"');
function orgChartSource(people, dir = 'TB') {
const lines = [`flowchart ${dir}`];
for (const p of people) lines.push(` ${nodeId(p.id)}["${label(p.name)}<br/>${label(p.title)}"]`);
for (const p of people) if (p.managerId) lines.push(` ${nodeId(p.managerId)} --> ${nodeId(p.id)}`);
return lines.join('\n');
}
function shareUrl(code, options = {}) {
const payload = { v: 1, code, type: 'flowchart', ...options };
return EDITOR + '#state=' + LZString.compressToEncodedURIComponent(JSON.stringify(payload));
}
const people = [
{ id: 'e1', name: 'Dana Whitfield', title: 'Chief Executive', managerId: null },
{ id: 'e2', name: 'Sam Okafor', title: 'VP Engineering', managerId: 'e1' },
{ id: 'e3', name: 'Lena Bright', title: 'VP Finance', managerId: 'e1' },
];
console.log(shareUrl(orgChartSource(people), { theme: 'forest' }));To read a link your platform received, reverse the two steps.
const payload = new URL(link).hash.replace(/^#state=/, '');
const state = JSON.parse(LZString.decompressFromEncodedURIComponent(payload));
console.log(state.code);Build a link in Python
Install the lzstring package, a port of the same algorithm. Use compact JSON separators so the payload stays short.
import json, re
from lzstring import LZString
EDITOR = "https://www.mermaid.tools/"
def node_id(key):
return "n" + re.sub(r"[^A-Za-z0-9_]", "_", str(key))
def label(text):
return str(text).replace("&", "&").replace('"', """)
def org_chart_source(people, direction="TB"):
lines = [f"flowchart {direction}"]
for p in people:
lines.append(f' {node_id(p["id"])}["{label(p["name"])}<br/>{label(p["title"])}"]')
for p in people:
if p.get("manager_id"):
lines.append(f" {node_id(p['manager_id'])} --> {node_id(p['id'])}")
return "\n".join(lines)
def share_url(code, **options):
payload = {"v": 1, "code": code, "type": "flowchart", **options}
body = json.dumps(payload, separators=(",", ":"), ensure_ascii=False)
return EDITOR + "#state=" + LZString().compressToEncodedURIComponent(body)
people = [
{"id": "e1", "name": "Dana Whitfield", "title": "Chief Executive", "manager_id": None},
{"id": "e2", "name": "Sam Okafor", "title": "VP Engineering", "manager_id": "e1"},
{"id": "e3", "name": "Lena Bright", "title": "VP Finance", "manager_id": "e1"},
]
print(share_url(org_chart_source(people), theme="forest"))Any language with an LZ-String implementation works the same way. The whole contract is: build the JSON, run compressToEncodedURIComponent, prefix #state=.
Embed a read-only diagram
Adding ?ro=1 before the fragment opens the editor in read-only mode. The source becomes uneditable, the diagram-type picker is disabled, the side panels stay collapsed and autosave is off. Panning and zooming still work.
https://www.mermaid.tools/?ro=1#state=N4IgbiBcCMA0IGMD2ATAplEAzANkg7g...That is the form to put in an iframe when a diagram should appear inside your own product.
<iframe src="https://www.mermaid.tools/?ro=1#state=N4IgbiBcCMA0..."
width="800" height="600" frameborder="0"
title="Reporting structure"></iframe>Regenerate the src whenever the underlying data changes and the embed follows along. If you need a static image rather than a live editor, open the link and export SVG or PNG, or render the same Mermaid source with the Mermaid library on your own side.
Limits, escaping and privacy
Length. The payload grows with the diagram. Repetitive Mermaid source compresses well, but the editor warns above roughly 8,000 characters because some browsers, proxies and chat clients truncate long URLs. For a very large chart, send the .mmd source instead and let the recipient open it with File then Open.
Escaping. Escape & and " inside labels, as the examples above do. Keep node identifiers to letters, digits and underscores. Avoid a bare lowercase end as a label, because Mermaid reads it as a keyword.
Validate before you send. A payload that produces invalid Mermaid still builds a link; the error appears only when someone opens it. Render the source once on your side, or open one generated link yourself, before wiring the generator into a production flow.
Privacy. The fragment is not sent to the mermaid.tools server, but the link itself is the diagram. Anyone who receives it can read the contents, and a link pasted into a chat or a ticket keeps working for as long as it exists. Keep confidential org data out of links shared outside your organisation.
Stability. The v field marks the payload version. Send 1. If a future version changes the shape, links that declare version 1 keep working.
Try it in the editor
Edit this small team reporting structure in Mermaid, inspect the rendered result, and adapt the working source for your own documentation.
flowchart TB
Lead[Team lead] --> Engineering[Engineering]
Lead --> Design[Design]
Lead --> Operations[Operations]
Engineering --> Frontend[Frontend]
Engineering --> Backend[Backend]Opening the example lets you review it before replacing your current diagram.
Syntax reference: official Mermaid documentation.