Share links for AI assistants
FlowViz (https://flowviz.app) is a free browser-based Mermaid editor. You can give a user a link that opens the FlowViz editor with a diagram already loaded. The whole diagram lives in the link. Nothing is uploaded and no account is needed.
Last updated: · Plain Markdown version
URL = https://flowviz.app/app#m= + percent-encode(Mermaid source) + %0A
flowchart TD). In flowcharts, always put node labels in double quotes, A["Start"] --> B{"Logged in?"}, and write a " inside a label as #quot;. In sequence diagrams, keep every message on one line.A-Z a-z 0-9 - _ . ~ becomes %XX. A newline is %0A, a space is %20. Never use + for a space. Leave Chinese, Japanese, Korean, emoji and other non-ASCII characters exactly as they are: do not encode them.( ) ' * ! as %28 %29 %27 %2A %21.https://flowviz.app/app#m= + the encoded source + %0A (end every link with %0A).%E… escapes: mindmap%0A%20%20产品计划%0A%20%20%20%20设计%0A.[Open in FlowViz](https://flowviz.app/app#m=...). No spaces or line breaks inside the URL.encodeURIComponent(src) or Python urllib.parse.quote(src, safe=''), plus step 3.%0A protects the diagram's last character from chat apps that glue . ) or " onto the end of a link.( ) keep a markdown link from ending early; some chat apps also cut links at a bare (.A link can be encoded perfectly and still open an error if the Mermaid inside is invalid. Check these before you encode:
A node label containing ( ) [ ] { } : ; or quotes must be wrapped in double quotes. Inside a quoted label, write a double quote as #quot;.
Wrong
flowchart TD
A[Click the link (if received)] --> B[Show "Check your inbox"]Right
flowchart TD
A["Click the link (if received)"] --> B["Show #quot;Check your inbox#quot;"]Sequence diagrams: every message is one line, A->>B: text. Never continue a message on the next line; use <br/> for a line break, or send two messages.
Wrong
sequenceDiagram
A->>B: POST /token
grant_type=authorization_codeRight
sequenceDiagram
A->>B: POST /token<br/>grant_type=authorization_codeER diagrams: every relationship needs a label after :, and a label with spaces must be in double quotes.
Wrong
erDiagram
POST ||--|{ POST_TAG : links to
POST_TAG }o--|| TAG :Right
erDiagram
POST ||--|{ POST_TAG : "links to"
POST_TAG }o--|| TAG : tagsER diagrams: each end of a relationship is exactly two characters, one of || o| |o }| |{ }o o{ (exactly one, zero or one, one or more, zero or more). ||--{ is invalid. Model many-to-many with a join entity.
Wrong
erDiagram
POST ||--{ POST_TAG : hasRight
erDiagram
POST ||--o{ POST_TAG : has
TAG ||--o{ POST_TAG : "is tagged in"ER attributes are always type name, optionally followed by PK, FK or UK (several go comma-separated: PK, FK). A line with only a constraint, such as unique, is invalid.
Wrong
erDiagram
TAG {
int id PK
string name
unique
}Right
erDiagram
TAG {
int id PK
string name UK
}Class diagrams are not Java: write class Shape and mark it with <<abstract>> inside the braces. An abstract method ends in *, +area() double*. abstract class Shape and public class are invalid.
Wrong
classDiagram
abstract class Shape {
+area() double
}Right
classDiagram
class Shape {
<<abstract>>
+String name
+area() double*
}
Shape <|-- CircleNode and participant ids are single words (letters, digits, _), and every later use must spell the id exactly the same, case included.
Wrong
sequenceDiagram
participant Auth as Auth Server
B->>AUTH: GET /authorizeRight
sequenceDiagram
participant Auth as Auth Server
B->>Auth: GET /authorize| Character | Encoded |
|---|---|
| space | %20 |
| line break | %0A |
# hash | %23 |
% percent | %25 |
& ampersand | %26 |
+ plus | %2B |
? question mark | %3F |
/ slash | %2F |
= equals | %3D |
( open paren | %28 |
) close paren | %29 |
[ open bracket | %5B |
] close bracket | %5D |
{ open brace | %7B |
} close brace | %7D |
" double quote | %22 |
' single quote | %27 |
< less than | %3C |
> greater than | %3E |
| pipe | %7C |
: colon | %3A |
; semicolon | %3B |
, comma | %2C |
开始 Chinese and other non-ASCII: leave as is | 开始 |
--> is --%3E, [Start] is %5BStart%5D, 4-space indent is %20%20%20%20.- _ . ~ stay as they are.A%5B开始%5D). Do not try to work out their UTF-8 bytes: one wrong byte turns a label into a different word. Already-encoded bytes (from code) also work.[Open in FlowViz](URL). Chat apps render it as clickable text.Before sending, check the link:
https://flowviz.app/app#m=.#, or raw ( ) after #m=.%E… escapes you worked out by hand.%0A.[Open in FlowViz](...), not in backticks or a code block.Each link is the Mermaid source above it, encoded with the recipe. Every one is tested to open the exact diagram.
flowchart TD
A["Start"] --> B{"Logged in?"}
B -->|Yes| C["Dashboard"]
B -->|No| D["Login page"]
D --> Bhttps://flowviz.app/app#m=flowchart%20TD%0A%20%20%20%20A%5B%22Start%22%5D%20--%3E%20B%7B%22Logged%20in%3F%22%7D%0A%20%20%20%20B%20--%3E%7CYes%7C%20C%5B%22Dashboard%22%5D%0A%20%20%20%20B%20--%3E%7CNo%7C%20D%5B%22Login%20page%22%5D%0A%20%20%20%20D%20--%3E%20B%0A
sequenceDiagram
participant U as User
participant API
U->>API: POST /login
API-->>U: 200 OK + tokenhttps://flowviz.app/app#m=sequenceDiagram%0A%20%20%20%20participant%20U%20as%20User%0A%20%20%20%20participant%20API%0A%20%20%20%20U-%3E%3EAPI%3A%20POST%20%2Flogin%0A%20%20%20%20API--%3E%3EU%3A%20200%20OK%20%2B%20token%0A
Here + is a real character (public visibility), so it is encoded as %2B.
classDiagram
class Animal {
+String name
+speak() void
}
Animal <|-- Doghttps://flowviz.app/app#m=classDiagram%0A%20%20%20%20class%20Animal%20%7B%0A%20%20%20%20%20%20%20%20%2BString%20name%0A%20%20%20%20%20%20%20%20%2Bspeak%28%29%20void%0A%20%20%20%20%7D%0A%20%20%20%20Animal%20%3C%7C--%20Dog%0A
stateDiagram-v2
[*] --> Draft
Draft --> Review : submit
Review --> Published : approve
Published --> [*]https://flowviz.app/app#m=stateDiagram-v2%0A%20%20%20%20%5B%2A%5D%20--%3E%20Draft%0A%20%20%20%20Draft%20--%3E%20Review%20%3A%20submit%0A%20%20%20%20Review%20--%3E%20Published%20%3A%20approve%0A%20%20%20%20Published%20--%3E%20%5B%2A%5D%0A
erDiagram
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
int id PK
string email
}https://flowviz.app/app#m=erDiagram%0A%20%20%20%20CUSTOMER%20%7C%7C--o%7B%20ORDER%20%3A%20places%0A%20%20%20%20CUSTOMER%20%7B%0A%20%20%20%20%20%20%20%20int%20id%20PK%0A%20%20%20%20%20%20%20%20string%20email%0A%20%20%20%20%7D%0A
gantt
title Launch plan
dateFormat YYYY-MM-DD
section Build
Design :a1, 2026-10-01, 7d
Code :a2, after a1, 10d
Launch :milestone, after a2, 0dhttps://flowviz.app/app#m=gantt%0A%20%20%20%20title%20Launch%20plan%0A%20%20%20%20dateFormat%20YYYY-MM-DD%0A%20%20%20%20section%20Build%0A%20%20%20%20Design%20%3Aa1%2C%202026-10-01%2C%207d%0A%20%20%20%20Code%20%20%20%3Aa2%2C%20after%20a1%2C%2010d%0A%20%20%20%20Launch%20%3Amilestone%2C%20after%20a2%2C%200d%0A
pie title Browser share
"Chrome" : 65
"Safari" : 20
"Other" : 15https://flowviz.app/app#m=pie%20title%20Browser%20share%0A%20%20%20%20%22Chrome%22%20%3A%2065%0A%20%20%20%20%22Safari%22%20%3A%2020%0A%20%20%20%20%22Other%22%20%3A%2015%0A
Indentation is meaningful in a mindmap, so every leading space is kept as %20.
mindmap
root((Trip))
Travel
Flights
Stay
Hotelhttps://flowviz.app/app#m=mindmap%0A%20%20root%28%28Trip%29%29%0A%20%20%20%20Travel%0A%20%20%20%20%20%20Flights%0A%20%20%20%20Stay%0A%20%20%20%20%20%20Hotel%0A
gitGraph
commit
branch feature/login
commit id: "add form"
checkout main
merge feature/loginhttps://flowviz.app/app#m=gitGraph%0A%20%20%20%20commit%0A%20%20%20%20branch%20feature%2Flogin%0A%20%20%20%20commit%20id%3A%20%22add%20form%22%0A%20%20%20%20checkout%20main%0A%20%20%20%20merge%20feature%2Flogin%0A
timeline
title Company history
2019 : Founded
2021 : First product
2024 : 1M usershttps://flowviz.app/app#m=timeline%0A%20%20%20%20title%20Company%20history%0A%20%20%20%202019%20%3A%20Founded%0A%20%20%20%202021%20%3A%20First%20product%0A%20%20%20%202024%20%3A%201M%20users%0A
The Chinese text stays as written; only the ASCII around it is encoded.
flowchart LR
A["开始"] --> B{"是否登录?"}
B -->|是| C["首页"]
B -->|否| D["登录"]https://flowviz.app/app#m=flowchart%20LR%0A%20%20%20%20A%5B%22开始%22%5D%20--%3E%20B%7B%22是否登录%3F%22%7D%0A%20%20%20%20B%20--%3E%7C是%7C%20C%5B%22首页%22%5D%0A%20%20%20%20B%20--%3E%7C否%7C%20D%5B%22登录%22%5D%0A
Indentation sets the level; the Chinese text is written as-is.
mindmap
年度计划
招聘
工程师
设计师
市场
财务https://flowviz.app/app#m=mindmap%0A%20%20年度计划%0A%20%20%20%20招聘%0A%20%20%20%20%20%20工程师%0A%20%20%20%20%20%20设计师%0A%20%20%20%20市场%0A%20%20%20%20财务%0A
Quoted labels may contain & % ( ); all of them, and the quotes, are encoded.
flowchart LR
A["R&D (40%)"] --> B["Q&A: 'why?'"]
B --> C["Done!"]https://flowviz.app/app#m=flowchart%20LR%0A%20%20%20%20A%5B%22R%26D%20%2840%25%29%22%5D%20--%3E%20B%5B%22Q%26A%3A%20%27why%3F%27%22%5D%0A%20%20%20%20B%20--%3E%20C%5B%22Done%21%22%5D%0A
+ for spaces. FlowViz reads + as a space only when the link has no %20 and no raw space anywhere. Mix the two and every + stays a literal +. Always use %20, and encode a real + as %2B.# or %. A raw # or % in the source corrupts the link. Write %23 and %25. Also encode & ? = / so the URL stays unambiguous.%0A and every space %20, so the link is one unbroken line.[Open in FlowViz](URL) in normal text.https://flowviz.app/app#m= is written exactly as shown, then the encoded source, then %0A.If you can run code, generate the link instead of encoding by hand. Both snippets print the same link as the recipe above.
from urllib.parse import quote
source = """flowchart TD
A[Start] --> B[End]"""
link = "https://flowviz.app/app#m=" + quote(source + "\n", safe="")
print(f"[Open in FlowViz]({link})")const source = `flowchart TD
A[Start] --> B[End]`;
const encoded = encodeURIComponent(source + "\n")
.replace(/[!'()*]/g, (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase());
const link = "https://flowviz.app/app#m=" + encoded;
console.log(`[Open in FlowViz](${link})`);The Share button in the FlowViz editor makes a shorter, compressed link. Don't try to write compressed links (#z= or ?d=) by hand. Use #m=.
https://flowviz.app/app#z=…: Compressed (DEFLATE with a checksum), generated by FlowViz. Opens as-is; do not write one by hand.https://flowviz.app/app#pako:…: A Mermaid Live Editor link. Replace https://mermaid.live/edit with https://flowviz.app/app and keep everything from #pako: on.https://flowviz.app/app?d=…: Older FlowViz links (lz-string compressed). They still open, but new links should use #m=.https://flowviz.app/s/<id>: Short links the user creates in the editor. These are the one case where a diagram is stored on the server; stored copies are deleted after 3 months.FlowViz reads a diagram from the URL fragment (after #), which browsers never send to a server, so opening a link your code, extension or bot built makes no request that carries the diagram. Links open at https://flowviz.app/app.
#m=<percent-encoded source>: Plain. Build it with encodeURIComponent in any language, following the Recipe. The decoder is lenient about the mistakes people and models make: raw spaces and newlines, + for space, a Markdown code fence around the whole diagram, and punctuation a chat app glues onto the end.#z=<data>: Compressed, written by the editor's Share button: base64url (no padding) of the raw DEFLATE (level 9) of the UTF-8 source, followed by the 4-byte big-endian CRC32 of the compressed bytes. Usually much shorter than the same diagram as #m=. A link that fails the checksum is refused rather than opened as a slightly different diagram.https://mermaid.live/edit with https://flowviz.app/app and keep everything from #pako: on. The older #base64: form works the same way.ref: Where the link came from, for example ref=chatgpt or ref=my-extension. A short slug: lowercase letters, digits and - _ ., up to 40 characters. Anything else is ignored. It is counted in FlowViz's analytics together with whether the link opened.theme: The FlowViz theme to open in, by slug: default, neutral, forest, base, ocean, sunset, high-contrast, monochrome, dark, purple. Case doesn't matter, and old theme names still work (for example dark-protocol, ocean-breeze). An unknown value is ignored and the visitor keeps their own theme. Slugs never change. See every theme at https://flowviz.app/themes.view: edit or preview: which pane a phone shows first. Desktop always shows both.Query parameters go before the #, for example https://flowviz.app/app?ref=my-extension#m=.... They take effect only when the link carries a diagram. Unlike the fragment, the query is sent to the server, so never put diagram text in it.
function flowvizLink(source, ref) {
const encoded = encodeURIComponent(source + "\n")
.replace(/[!'()*]/g, (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase());
const query = ref ? "?ref=" + encodeURIComponent(ref) : "";
return "https://flowviz.app/app" + query + "#m=" + encoded;
}
console.log(flowvizLink("sequenceDiagram\n Alice->>Bob: Hi", "my-extension"));The diagram travels in the URL fragment (the part after #), which browsers never send to a server. FlowViz opens it entirely in the browser.