line 3: ...), the line number is a link — clicking it jumps to and selects that line in the editor.type ). Pressing Tab again at the same spot cycles through every match.{. Right between a freshly auto-closed {/} pair, Enter splits into three lines (opening line, indented empty line with the cursor, closing brace).{ and " auto-insert their matching closer (} or a second "); typing that closer again while one already sits right there just steps over it instead of inserting a second one.type line) are colored.Use the tabs above for a step-by-step introduction to each diagram type's syntax, building from a minimal example up to the full feature set.
A few small features work the same way inside any ordinary quoted name ("like this"), in any diagram type — they aren't specific to one diagram. This page covers that single-line form; a canvas box's content uses a different, more elaborate multiline form (real line breaks, plus lists) — see the Canvas tab's own "Content" section for that one.
\n inside a quoted name inserts a manual line break. The container it's drawn in (box, ellipse, ...) grows to fit the extra line.
type usecasediagram
actor Customer
system "ATM\nSystem" {
usecase "Withdraw\ncash"
association Customer--"Withdraw\ncash"
}
text renders part of a label in bold — only the text part is shown, the ** markers themselves never appear in the output.
type usecasediagram
actor Customer
system ATM {
usecase "**Withdraw cash** (most common)"
association Customer--"**Withdraw cash** (most common)"
}
_text_ renders part of a label in italic — only the text part is shown, the _ markers themselves never appear in the output. Deliberately a single underscore rather than *text*, so it never collides with bold's own doubled asterisks.
type usecasediagram
actor Customer
system ATM {
usecase "Withdraw cash (_most common_)"
association Customer--"Withdraw cash (_most common_)"
}
[text](target) turns part of a label into a real, clickable link in the rendered SVG — only the text part is shown, and it grows the container the same way plain text does.
type usecasediagram
actor Customer
system ATM {
usecase "[Withdraw cash](https://example.com/docs/withdraw)"
association Customer--"[Withdraw cash](https://example.com/docs/withdraw)"
}
A target can be anything a browser understands in an href:
[docs](https://example.com/docs)[home](/index.html)[up one level](../overview.html)[jump down](#section-2)Plain text, bold, italic and links can all be mixed freely within the same label, and a label can even contain more than one link. None of bold, italic and link markup is recognized nested inside another, though — [text](url) won't render as a bold link, just as literal ** characters around the link.
Four diagram types accept an optional color <value> attribute directly on one of their own elements — a canvas box, a Clean Architecture or Stakeholder Map ring, or a Conflict Map party. A color only ever recolors that one element's own fill, never its outline or label text, which always stay the diagram's own fixed neutral color.
Pick either a built-in preset — a quick, curated shortcut — or an exact hex value for full control:
type canvas
row {
box "Problem" color darkblue
box "Solution" color #7fb3e0
}
| Keyword | Color | Keyword | Color |
|---|---|---|---|
black | red | ||
white | darkred | ||
gray | lightred | ||
darkgray | orange | ||
lightgray | yellow | ||
blue | green | ||
darkblue | darkgreen | ||
lightblue | lightgreen | ||
purple | pink |
default rounds out the list — it means "not set", the same as leaving color out entirely: every element falls back to whatever it used before color existed (canvas/Conflict Map: a fixed neutral fill; Clean Architecture: a fixed position-based palette; Stakeholder Map: its usual radius-based gradient).
Anything the presets don't cover, spell out directly as #rgb or #rrggbb (hex digits, upper- or lowercase, right after color):
ring "Core" color #1a2b3c { ... }
party Stefan color #e91e63
box "Risks" color #c0392b
A color attribute never changes an element's outline or label text — only its fill. Those always stay the diagram's own fixed neutral color, so a ring's or box's own name always stays legible regardless of which color it carries.
colorValue = ( "default" | "black" | "white" | "gray" | "darkgray" | "lightgray"
| "red" | "darkred" | "lightred" | "orange" | "yellow"
| "green" | "darkgreen" | "lightgreen"
| "blue" | "darkblue" | "lightblue" | "purple" | "pink" ) | hex ;
hex = "#" ( 3 | 6 hexDigit ) ;
color <value> sits directly after the element's own name — box <name> [color <value>], ring <name> [color <value>], party <name> [power <level>] [color <value>] (after power, if both are given) — see each diagram type's own tab for its exact position.
Not to be confused with Mindmap's own scheme <name> (see the Mindmap tab) — a separate, whole-diagram visual identity (root/branch colors, stroke widths, dashing all at once), not a single element's fill. There is no other diagram-wide color option — an earlier, generic theme <name> declaration (once valid on every diagram type, then narrowed to a few) has since been removed entirely in favor of this per-element color and Mindmap's own scheme.
A use case diagram connects actors (head + bust icons) to use cases (ellipses) inside a system (rectangle), via associations (lines).
Every file starts with a type declaration. The smallest useful diagram is one actor, one system with one use case, and one association connecting them:
type usecasediagram
actor Customer
system ATM {
usecase "Withdraw cash"
association Customer--"Withdraw cash"
}
An association always connects exactly one actor with exactly one use case (never actor–actor or use case–use case).
Add as many actor/usecase/association lines as needed. A multi-word name needs quotes; as gives it a short alias for associations to reuse:
type usecasediagram
actor Customer
actor "Bank Employee" as Employee
system ATM {
usecase "Withdraw cash"
usecase "Check balance"
usecase "Print statement"
association Customer--"Withdraw cash"
association Customer--"Check balance"
association Employee--"Print statement"
}
Use cases can relate to each other, not just to actors:
include a--b: "a includes b" — a always triggers b too.extends a--b: "a extends b" — a is an optional extension of the base case b, optionally with condition entries explaining when it applies.extensionpoint entries, marking where an extends may hook in.type usecasediagram
actor Customer
system ATM {
usecase "Insert card"
usecase "Withdraw cash" {
extensionpoint "Lock card"
}
usecase "Enter PIN"
association Customer--"Insert card"
include "Withdraw cash"--"Enter PIN"
extends "Insert card"--"Withdraw cash" {
condition "Card stolen"
condition "Wrong PIN 3 times"
}
}
An optional shadow line right after type usecasediagram (before any actor/system) turns on a drop-shadow effect for the *whole diagram* — every actor, the system, every use case and every connection. It's all-or-nothing: there's no way to shadow only some elements, and it's off by default, so existing diagrams don't need any changes:
type usecasediagram
shadow
actor Customer
system ATM {
usecase "Withdraw cash"
association Customer--"Withdraw cash"
}
diagram = typeDecl shadowDecl? { actorDecl | systemDecl } ;
typeDecl = "type" ident ;
shadowDecl = "shadow" ;
actorDecl = "actor" name [ "as" ident ] ;
systemDecl = "system" name "{" { usecaseDecl | assocDecl | includeDecl | extendDecl } "}" ;
usecaseDecl = "usecase" name [ "as" ident ] [ "{" extensionPointDecl { extensionPointDecl } "}" ] ;
extensionPointDecl = "extensionpoint" name ;
assocDecl = "association" name "--" name ;
includeDecl = "include" name "--" name ;
extendDecl = "extends" name "--" name [ "{" conditionDecl { conditionDecl } "}" ] ;
conditionDecl = "condition" name ;
name = ident | string ;
| Keyword | Meaning / what it controls |
|---|---|
type usecasediagram | Required as the first line of the file; selects this diagram's grammar. usecasediagram has no theme/color of its own — no natural, repeated element here to color. |
shadow | Optional, right after type usecasediagram, before any actor/system. Turns on a drop-shadow effect for every actor, system, use case and connection in the diagram — a whole-diagram toggle, off by default. |
actor <name> | Declares an actor icon. Must appear at the top level, outside any system block. |
system <name> { ... } | Declares the system rectangle. Everything it contains (usecase, association, include, extends) lives inside its { } block. |
usecase <name> | Declares an ellipse inside a system. Optionally takes its own { ... } block containing one or more extensionpoint entries, which draws it "comparted" (a lower compartment listing them). |
association <a>--<b> | Draws a line between exactly one actor and one usecase (order doesn't matter). Actor–actor or usecase–usecase is a parse error. |
as <alias> | Optional on actor/usecase (not on system): gives the just-declared element a short alias, so a later association/include/extends can reference it instead of repeating the full quoted name. Must be declared before it's used; can only be assigned once per element. The full name stays usable afterward too. |
include <a>--<b> | "a includes b": dashed arrow, open arrowhead, labeled <<include>>, from a to b. Only valid between two usecases, never with an actor. |
extends <a>--<b> | "a extends b" (a is the extension, b the base): same arrow style, labeled <<extends>>. Only valid between two usecases. Optionally takes a { ... } block of condition entries. |
condition <text> | Inside an extends { ... } block; at least one is required if the block is opened. Rendered as a callout box ("Condition:" + list) attached to the extends line. |
extensionpoint <text> | Inside a usecase { ... } block; at least one is required if the block is opened. Marks a named point in that usecase where an extends may hook in; turns the ellipse into a comparted usecase. |
| Names | A bare identifier (Customer, ATM) or a quoted, multi-word string ("Bank Employee"), with \"/\\ escapes and \n for a manual line break (see the Text & Links tab for \n and clickable links, which work the same way here). |
A goal tree breaks a root goal down into sub-goals, recursively.
The smallest goal tree is a single goal with no children (a leaf):
type goaltree
goal "Increase revenue"
A goal with children needs exactly one decomposition, and or or, with at least one child goal each:
type goaltree
goal "Increase revenue" and {
goal "Grow existing customers"
goal "Acquire new customers"
}
Decompositions nest freely, and any leaf goal can be marked achieved. Achievement then propagates upward automatically: an and goal is achieved once all its children are, an or goal once any one of them is.
type goaltree
goal "Increase revenue" and {
goal "Grow existing customers" or {
goal "Upsell premium plan" achieved
goal "Cross-sell add-ons"
}
goal "Acquire new customers"
}
diagram = typeDecl goalDecl ;
goalDecl = "goal" name ( decomp | "achieved"? ) ;
decomp = ( "and" | "or" ) "{" goalDecl { goalDecl } "}" ;
| Keyword | Meaning / what it controls |
|---|---|
type goaltree | Required as the first line of the file; selects this diagram's grammar. goaltree has no theme/color of its own — no natural, repeated element here to color; the green achieved fill is fixed regardless. |
goal <name> | Declares a goal node. With no decomposition it's a leaf; with a decomposition it's an internal node. |
and { ... } | Decomposition attached to a goal: all listed child goals must be achieved for this goal to count as achieved. Drawn as an orthogonal connector (a bar, then a line down to each child), like an org chart. Needs at least one child. |
or { ... } | Decomposition attached to a goal: any single child being achieved is enough. Drawn as direct, straight lines to each child. Needs at least one child. |
achieved | Marks a leaf goal (one with no and/or) as achieved, shown filled green. Only valid on a leaf — a goal with a decomposition never declares this itself; its status is always computed bottom-up instead (an and goal is achieved once every child is, an or goal once any one child is), all the way up to the root. |
| Names | A bare identifier or a quoted, multi-word string, with \"/\\/\n support (see the Text & Links tab). |
A feature model (FODA) breaks a root feature down into child features, marking which are required and how child groups relate.
A root feature with one child is already a valid model:
type featuremodel
feature "Coffee Maker" {
feature "Water tank"
}
Every feature is mandatory by default — mandatory only needs to be written to make that explicit, or to switch a feature to optional. Optional children get a hollow circle where they attach, mandatory ones a filled circle:
type featuremodel
feature "Coffee Maker" {
mandatory feature "Water tank"
optional feature "Milk frother"
}
Instead of a plain { ... } list, a group of children can be alternative (exactly one, drawn with a hollow arc) or or (at least one, filled arc). Separately, requires/excludes link two features anywhere in the tree by name, regardless of nesting:
type featuremodel
feature "Coffee Maker" {
mandatory feature "Water tank"
optional feature "Milk frother"
mandatory feature "Grinder" alternative {
feature "Conical burr grinder"
feature "Disc burr grinder"
}
}
requires "Milk frother" "Disc burr grinder"
requires "Milk frother" "Disc burr grinder" means: choosing the milk frother forces the disc burr grinder. excludes works the same way but rules two features out together.
diagram = typeDecl featureDecl { constraint } ;
featureDecl = "feature" name [ decomp ] ;
decomp = ( "alternative" | "or" ) "{" featureDecl { featureDecl } "}"
| "{" member { member } "}" ;
member = [ "mandatory" | "optional" ] featureDecl ;
constraint = ( "requires" | "excludes" ) name name ;
| Keyword | Meaning / what it controls |
|---|---|
type featuremodel | Required as the first line of the file; selects this diagram's grammar. featuremodel has no theme/color of its own — the filled/hollow mandatory-vs-optional circles and group arc are fixed regardless. |
feature <name> | Declares a feature node. With no children it's a leaf. With children, it needs exactly one of the three body forms below. |
{ ... } (plain body) | Each child is independently marked mandatory/optional (see below); no group-level constraint between siblings. |
mandatory | The default — writing it is only ever needed to be explicit, or to switch back from optional. This child must be included whenever its parent is. Drawn with a filled circle where it attaches. Only meaningful on children of a plain { ... } body, not inside a group. |
optional | This child may be omitted even when its parent is included. Drawn with a hollow circle where it attaches. Only meaningful on children of a plain { ... } body, not inside a group. |
alternative { ... } (group body) | Exactly one of the listed children must be chosen (XOR). Drawn as a hollow arc spanning the children. mandatory/optional don't apply inside this group — the group cardinality governs all children equally. Needs at least one child (in practice, more than one is the point). |
or { ... } (group body) | At least one of the listed children must be chosen. Drawn as a filled arc. Same "no per-child mandatory/optional" rule as alternative. |
requires <a> <b> | Top-level statement (outside any feature block): choosing feature a forces feature b to be chosen too. Rendered as a dashed curve with a one-way arrow. Both names must exist somewhere in the tree; a feature can't require itself. |
excludes <a> <b> | Top-level statement: features a and b can never both be chosen. Rendered as a dashed curve with arrows on both ends (symmetric relationship). Same name-existence rules as requires. |
| Names | A bare identifier or a quoted, multi-word string, with \"/\\/\n support (see the Text & Links tab). |
A stakeholder map groups stakeholders (drawn as actors) into concentric rings, by how close they are to a decision.
One ring with one actor is already valid:
type stakeholdermap
ring "Core" {
actor "Product Owner"
}
A ring's body can hold a further ring nested inside it, in addition to (or instead of) its own actors — each nested ring becomes the next ring over. By default, the outermost-*written* ring (the one at the top level) is the innermost one, and nesting moves outward:
type stakeholdermap
ring "Core" {
actor "Product Owner"
actor "Tech Lead"
ring "Direct" {
actor "Engineering Manager"
actor "Design Lead"
ring "Indirect" {
actor CTO
actor Sales
}
}
}
Here "Core" is the innermost ring, "Indirect" the outermost — same result as declaring three separate rings innermost-first, just written as nesting instead. A ring can skip actors of its own entirely and hold only a nested ring (a purely organizational wrapper), but a ring with neither actors nor a nested ring is a parse error, and only one ring may be nested per body — concentric rings can't branch into siblings the way a tree can.
actor accepts the same optional as <alias> form as in a use case diagram, though nothing in a stakeholder map references that alias elsewhere.
An optional color right after a ring's own name overrides its fill — a preset name or a hex value (see the Color tab):
type stakeholdermap
ring "Core" color darkblue {
actor "Product Owner"
}
Without color, a ring falls back to its usual radius-based gradient fill.
Add invert right after type stakeholdermap to flip which end is which: the top-level ring becomes the *outermost* one instead, and nesting then moves inward — so the writing order matches the visual nesting depth directly, which can read more naturally when you think of stakeholders "from the outside in":
type stakeholdermap
invert
ring "Public" {
actor "General Users"
ring "Registered Customers" {
actor "Paying Customers"
ring "Executive Sponsors" {
actor CEO
actor CFO
}
}
}
Here "Public" is drawn as the outermost ring and "Executive Sponsors" as the core — without invert, the same source would draw it the other way around.
diagram = typeDecl invertDecl? ring ;
invertDecl = "invert" ;
ring = "ring" name [ "color" colorValue ] "{" actorDecl* ring? "}" ;
actorDecl = "actor" name [ "as" ident ] ;
| Keyword | Meaning / what it controls |
|---|---|
type stakeholdermap | Required as the first line of the file; selects this diagram's grammar. |
invert | Optional, right after type stakeholdermap. Flips which end of the nesting is drawn as the core: without it, the top-level ring is innermost and nesting moves outward; with it, the top-level ring is outermost and nesting moves inward. |
ring <name> [color <value>] { ... } | Declares one concentric ring. Exactly one top-level ring is required. Its body holds zero or more actor declarations and, optionally, one further nested ring (which becomes the next ring over — see "Inverting the order" for which direction "over" means). A ring needs at least one actor or a nested ring; a nested ring must be the last thing in its parent's body. The name is free text (not a fixed vocabulary, unlike techradar's rings). |
color <value> | Optional, right after a ring's own name — a preset name or a hex value (see the Color tab). Overrides only that ring's fill — see "Color" above. Without it, the usual radius-based gradient is used instead. |
actor <name> [as <alias>] | Declares a stakeholder inside a ring, drawn with the same icon as a use case diagram's actor. The optional as <alias> is accepted (same grammar as usecasediagram) but has no effect here — nothing in a stakeholder map references it. |
as <alias> | Optional on actor: gives it a short alias, same grammar as usecasediagram's as. Unlike there, nothing in a stakeholder map ever reads the alias back — it's accepted but has no visible effect. |
| Names | A bare identifier or a quoted, multi-word string, with \"/\\/\n support (see the Text & Links tab). |
A Kano model plots rated needs against Functionality (horizontal) and Satisfaction (vertical), against the four classic Kano curves — Attractive, Performance, Indifferent, Must-be. Both axes always run -4..4.
The background (axes, all four curves) is always drawn, even without a single line of content:
type kanomodel
fill attractive and fill mustbe shade the region between their curve and the plot edge — there's no fill for Performance/Indifferent, since those are straight lines through the whole plot rather than a bounded region:
type kanomodel
fill attractive
fill mustbe
A need is a name, a coordinate (functionality, satisfaction), and a symbol (circle, square, triangle, or diamond). Coordinates must stay within -4..4:
type kanomodel
fill attractive
fill mustbe
need "Fast checkout" (2, 3) circle
need "24/7 support" (-1, -3) triangle
diagram = typeDecl { fillDecl | needDecl } ;
fillDecl = "fill" ( "attractive" | "mustbe" ) ;
needDecl = "need" name "(" number "," number ")" symbol ;
symbol = "circle" | "square" | "triangle" | "diamond" ;
| Keyword | Meaning / what it controls |
|---|---|
type kanomodel | Required as the first line of the file; selects this diagram's grammar. An otherwise-empty kanomodel (just the background) is valid. kanomodel has no theme/color of its own — the plot frame/axis/need markers are fixed black, the four Kano curves unaffected regardless. |
fill attractive | Shades the region between the Attractive curve and the plot's upper-left edge. Optional, no effect if omitted beyond the curve itself being drawn unfilled. |
fill mustbe | Shades the region between the Must-be curve and the plot's lower-right edge. Optional, same as above. There's no fill for Performance or Indifferent — both are straight lines spanning the whole plot, not a bounded region. |
attractive | fill's value for shading the Attractive curve's region — see fill attractive above. |
mustbe | fill's value for shading the Must-be curve's region — see fill mustbe above. |
need <name> (functionality, satisfaction) <symbol> | Plots one rated need at the given coordinate. Both coordinates are integers or decimals in the fixed range -4..4 (a value outside that range is a parse error) — functionality is the horizontal axis (None → Best), satisfaction the vertical axis (Frustrated → Delighted). |
<symbol> | One of circle, square, triangle, diamond. Purely a marker shape, fixed black-on-white; it carries no meaning of its own beyond distinguishing needs from each other on a crowded plot. |
circle | One of the four <symbol> shapes for a need's marker — see above. |
square | One of the four <symbol> shapes for a need's marker — see above. |
triangle | One of the four <symbol> shapes for a need's marker — see above. |
diamond | One of the four <symbol> shapes for a need's marker — see above. |
| Names | A bare identifier or a quoted, multi-word string, with \"/\\/\n support (see the Text & Links tab). The need's name is drawn centered below its marker. |
A tech radar (ThoughtWorks-style) tracks rated technologies, tools, platforms and techniques in four parts (quarters), each with one or more rings from the center outward.
Every tech radar starts with two named lists: parts (exactly four) and rings (one or more), declared once up front. Blips then come as a flat list afterward, each naming which part and ring it belongs to. Declaration order fixes position — parts go top-left, top-right, bottom-left, bottom-right; rings go innermost first.
type techradar
parts [Languages, Tools, Platforms, Techniques]
rings [use, evaluate, rethink]
blip "TypeScript" part Languages ring use
blip "Docker" part Tools ring use
blip "Kubernetes" part Platforms ring use
blip "Pair programming" part Techniques ring use
A part or ring can be given a short alias with as, the same idea as usecasediagram's actor/use-case aliases — handy once a part's name is long and referenced by many blips:
type techradar
parts ["Languages & Frameworks" as Lang, Tools, Platforms, Techniques]
rings [use, evaluate, rethink]
blip "TypeScript" part Lang ring use
blip "Svelte" part Lang ring evaluate
blip "Docker" part Tools ring use
blip "Kubernetes" part Platforms ring use
blip "Pair programming" part Techniques ring use
A blip can declare a trend, up or down, drawn as a triangle instead of a plain circle, and can be marked breaking — drawn with an extra ring around its marker — independently of (and combinable with) trend:
type techradar
parts ["Languages & Frameworks" as Lang, Tools, Platforms, Techniques]
rings [use, evaluate, rethink]
blip "TypeScript" part Lang ring use trend up
blip "GraphQL" part Lang ring use breaking
blip "Svelte" part Lang ring evaluate trend up
blip "jQuery" part Lang ring rethink trend down
blip "Docker" part Tools ring use
blip "Kubernetes" part Platforms ring use
blip "Pair programming" part Techniques ring use
Every blip is numbered on the radar itself; its name appears in a legend below, grouped by part — direct name labels would be unreadable once a radar has more than a handful of tightly-packed blips.
For a radar with many blips, the below-radar legend list can grow tall and repetitive. hoverlegend — a bare flag right after type — swaps it out for a per-blip tooltip instead: hover a blip's marker to see its name, revealed by a plain CSS :hover rule embedded in the SVG itself (no JavaScript). The canvas shrinks to just the radar, since there's no list to reserve room for:
type techradar
hoverlegend
parts [Languages, Tools, Platforms, Techniques]
rings [use, evaluate, rethink]
blip "TypeScript" part Languages ring use
blip "Docker" part Tools ring use
blip "Kubernetes" part Platforms ring use
blip "Pair programming" part Techniques ring use
A tooltip only appears while the SVG is hovered inside a browser (an inline <svg> in a web page, or the file opened directly) — it won't trigger inside a plain <img src="..."> embed, since the browser never processes an embedded image's own interactivity that way.
diagram = typeDecl hoverlegendDecl? partsDecl ringsDecl blipDecl* ;
hoverlegendDecl = "hoverlegend" ;
partsDecl = "parts" "[" item { "," item } "]" ;
ringsDecl = "rings" "[" item { "," item } "]" ;
item = name [ "as" ident ] ;
blipDecl = "blip" name "part" ref "ring" ref [ "trend" ( "up" | "down" ) ] [ "breaking" ] ;
ref = name | ident ;
| Keyword | Meaning / what it controls |
|---|---|
type techradar | Required as the first line of the file; selects this diagram's grammar. techradar has no theme/color of its own — ring band fills, part colors and blip colors are all fixed regardless. |
hoverlegend | Optional, right after type. Replaces the below-radar legend list with a per-blip hover tooltip (pure CSS, no JavaScript) — see Hover legend above. |
parts [ ... ] | Declares the radar's four quarters as a comma-separated list. Exactly four are required (more or fewer is a parse error). Declaration order fixes position — 1st = top-left, 2nd = top-right, 3rd = bottom-left, 4th = bottom-right. |
rings [ ... ] | Declares the radar's concentric bands, from the center outward, as a comma-separated list. At least one is required; unlike a part, a ring's name is free text (not a fixed vocabulary). |
as <alias> | Optional on a parts/rings entry: gives it a short alias, so a blip's part/ring reference can use it instead of repeating a long quoted name. Must be declared before it's used; can only be assigned once per entry. |
blip <name> part <ref> ring <ref> | Declares one rated item, naming which part and ring it belongs to — by the part/ring's full name or its alias. Both references are required. |
part | Introduces a blip's part reference — see blip <name> part <ref> ring <ref> above. |
ring | Introduces a blip's ring reference — see blip <name> part <ref> ring <ref> above. |
trend up | Draws the blip as an upward-pointing triangle instead of a plain circle. |
trend down | Draws the blip as a downward-pointing triangle. |
up | trend's value for an upward-pointing triangle — see trend up above. |
down | trend's value for a downward-pointing triangle — see trend down above. |
breaking | Draws an extra, unfilled ring around the blip's marker, independent of and combinable with trend. |
| Names | A bare identifier or a quoted, multi-word string, with \"/\\/\n support (see the Text & Links tab). A blip's name never appears directly on the radar (see above) — only its assigned number does; the name shows up in the legend instead. |
A conflict map places parties (people, teams, companies) around a circle and shows the quality of the relationships between them — close, loose, alliance or disturbed, optionally cut — plus who has authority over whom, and where an active conflict sits.
Every conflict map starts with a flat list of party declarations, followed by relation declarations connecting them by name:
type conflictmap
party Stefan
party Sarah
relation Stefan -- Sarah
A party may carry an optional power level, drawn as the party's circle size:
type conflictmap
party Stefan power high
party Sarah
party Max power low
A party may also carry an optional color, after power if both are given — a preset name or a hex value (see the Color tab):
type conflictmap
party Stefan power high color darkred
party Sarah color #7fb3e0
Without color, a party falls back to a fixed neutral fill. Conflict Map has no diagram-wide color option at all — color is the only per-party color available.
A relation is undirected and defaults to close (a solid line) when no style is given. The other styles each draw a different line:
type conflictmap
party A
party B
party C
party D
relation A -- B loose
relation A -- C alliance
relation A -- D disturbed
A severed or destroyed keyword, placed after the style (if any), overlays one or two crossing tick marks on top of whatever line was already drawn — independent of style, so any style can be cut:
type conflictmap
party A
party B
party C
relation A -- B severed
relation A -- C alliance destroyed
An optional directed flag, placed after style/cut (if any), turns a relation into a plain arrow from the first party (the one "with authority") to the second — drawn on top of whichever style/cut it's given:
type conflictmap
party Stefan
party Sarah
relation Stefan -- Sarah directed
A relation may end with an optional conflict flag (drawn as a small lightning-bolt marker on the line) and/or a free-text quoted label:
type conflictmap
party Sarah
party Tom
relation Sarah -- Tom conflict "win-lose"
A party may be given a short alias with as, the same idea as usecasediagram's actor/use-case aliases — handy once a party's name is long and referenced by several relations:
type conflictmap
party "Müller GmbH" as Mueller
party Sarah
relation Sarah -- Mueller alliance
Every relation line above can also be written in a shorter, symbol-based form, led by its own rel keyword (shorter than relation, and the default suggestion Ctrl+Space/the inline preview offers) instead of just the two parties and a symbol between them. Both forms can be freely mixed in the same file:
type conflictmap
party A
party B
party C
rel A == B
rel A -|- C
The symbol's base character picks the style (doubled: -- close, .. loose, == alliance, ~~ disturbed); an optional single character between the two bases adds a modifier (| for a cut — equivalent to severed, there is no compact form for destroyed — or // for the conflict flag); a leading < or trailing > arrowhead makes it directed (equivalent to relation's own directed flag), combinable with any style:
type conflictmap
party A
party B
rel A --> B
rel A .//. B "win-lose"
Ctrl+Space right after typing rel and a party name offers a curated starting list of the most common symbols — the full alphabet is bigger than what's listed there, but every valid combination the keyword notation can express (aside from destroyed) has a symbol equivalent.
diagram = typeDecl partyDecl* ( relationDecl | pumlDecl )* ;
partyDecl = "party" name [ "as" ident ] [ "power" powerLevel ] [ "color" colorValue ] ;
powerLevel = "low" | "medium" | "high" ;
relationDecl = "relation" ref "--" ref [ style ] [ cut ] [ "directed" ] [ "conflict" ] [ string ] ;
style = "close" | "loose" | "alliance" | "disturbed" ;
cut = "severed" | "destroyed" ;
ref = name | ident ;
pumlDecl = "rel" ref edgeSymbol ref [ string ] ;
edgeSymbol is a base character doubled (--/../==/~~), optionally with a single | or // between the two, and optionally with a leading < or trailing > arrowhead — see the PlantUML-style notation section above for the full table.
| Keyword | Meaning / what it controls |
|---|---|
type conflictmap | Required as the first line of the file; selects this diagram's grammar. Conflict Map has no diagram-wide color option — only the per-party color below. |
party <name> | Declares one participant, drawn as a circle placed around the diagram. |
as <alias> | Optional on a party declaration: gives it a short alias, so a relation can reference it instead of repeating a long quoted name. Must be declared before it's used; can only be assigned once per party. |
power low | Draws the party's circle at a smaller-than-default size. |
power medium | The default circle size when power is omitted entirely. |
power high | Draws the party's circle at a larger-than-default size. |
color <value> | Optional on a party, after power if both are given — a preset name or a hex value (see the Color tab). Overrides only that party's own circle fill — see "Color" above. Without it, a fixed neutral fill is used instead. |
low | power's value for a smaller circle — see power low above. |
medium | power's value for the default circle size — see power medium above. |
high | power's value for a larger circle — see power high above. |
relation <a> "--" <b> | Declares a bond between two parties, referenced by name or alias — undirected unless directed is also given. |
close | relation's default style when none is given — a solid line. |
loose | Draws the relation as a dashed line. |
alliance | Draws the relation as two parallel lines. |
disturbed | Draws the relation as a wavy line. |
severed | Overlays the relation's already-chosen style with one perpendicular tick mark — independent of style, see "Cutting a relation" above. |
destroyed | Overlays the relation's already-chosen style with two perpendicular tick marks. |
directed | Optional on relation: draws it as a plain arrow from the first party (who "has authority") to the second, on top of whichever style/cut it's given — see "Authority (directed relations)" above. |
conflict | Optional on relation: overlays a lightning-bolt marker at the line's midpoint. |
| Label string | An optional quoted string at the end of a relation/PlantUML-style declaration, after any conflict flag — shown as small italic text beside the line (e.g. "win-lose"). |
rel <a> -- <b> etc. (edge symbol) | The PlantUML-style notation's own alternative to relation — always led by rel, see "PlantUML-style notation" above for the full symbol table. |
| Names | A bare identifier or a quoted, multi-word string, with \"/\\/\n support (see the Text & Links tab). |
A canvas is a business-canvas-style grid of titled, colored boxes/areas (e.g. a Data Science/ML Canvas or a Product Canvas) — rows of boxes laid out left to right, with no cross-references between them at all.
Every canvas is one or more row blocks, each holding box declarations. Boxes in the same row are laid out left to right, sharing that row's width equally:
type canvas
row {
box "Problem" color blue
box "Solution" color blue
box "Actions" color green
}
row {
box "Values" color red
box "Risks" color red
}
Two or more boxes can share one row slot by stacking vertically inside a column block instead of standing alone:
type canvas
row {
box "Problem" color blue
column {
box "Data" color blue
box "Hypothesis" color blue
}
box "Solution" color blue
}
Different rows don't need to divide their width the same way — a row with three boxes and a row with five boxes still span the same overall canvas width, they just split it differently.
ratio gives a row or box a relative weight against its siblings, instead of the default equal split. A row's ratio is compared against other rows' (controlling height); a box's ratio only makes sense inside a column, compared against its own column siblings' (controlling that box's share of the shared height):
type canvas
row ratio 3 {
column {
box "Data" ratio 2
box "Hypothesis" ratio 3
}
}
row ratio 2 {
box "Values"
}
Here the top row is 1.5× as tall as the bottom row, and within the column, "Hypothesis" is 1.5× as tall as "Data". Omitting ratio is the same as ratio 1.
color overrides a box's own fill — a named preset (e.g. darkblue) or a literal hex value (e.g. #1a2b3c), see the Color tab for the full preset list and how to pick between the two. Chosen per box instead of once for the whole diagram, since a canvas typically needs several colors visible at once. A box without color falls back to a fixed neutral fill — color only ever overrides the fill, never the box's border or title text, which always stay that fixed neutral color.
A box can optionally hold body text — a content value written as a """-delimited block, real line breaks allowed inside (unlike every other quoted name in this tool, where only the \n escape breaks a line):
type canvas
row {
box "Problem" color blue content """
**Ask the right questions:**
- What is the problem?
- Why is it a problem?
"""
}
Content supports a small set of inline markup — bold, _italic_, and [text](target) links (bold and links work exactly like everywhere else, see the Text & Links tab) — plus two flat, one-level list forms: - item for an unordered list, 1. item for an ordered one (its numbers are always renumbered from 1 when rendered, so the source never needs to be kept in sync by hand). A blank line inside content is a paragraph gap, handy for separating two labeled sections:
type canvas
row {
box "Performance / Impact" color red content """
**Ask the right questions:**
- What is the impact? How to measure it?
**Example:**
- Increase our customer base
- Reduce cost of acquisition
"""
}
Content is entirely optional — a box with none renders exactly as before, just its centered title. A box that does declare content grows past its own ratio if it needs more room to fit it.
In the editor, typing """ right after content auto-inserts the closing """ with a blank line in between, ready to type into. A few more conveniences while writing content:
- or 1. line continues the list onto the next line automatically; pressing Enter again on an empty item clears it instead of piling up empty bullets.* wraps it in *...*; pressing * again on the still-selected word turns that into .... _ works the same way for italic.[ wraps it in [...], ready to type (target) right after for a link. ( works the same way for a plain parenthesis.diagram = typeDecl rowDecl+ ;
rowDecl = "row" [ "ratio" number ] "{" ( boxDecl | columnDecl ) + "}" ;
columnDecl = "column" "{" boxDecl boxDecl+ "}" ;
boxDecl = "box" name [ "color" colorValue ] [ "ratio" number ] [ "content" multilineString ] ;
| Keyword | Meaning / what it controls |
|---|---|
type canvas | Required as the first line of the file; selects this diagram's grammar. |
row | Declares one horizontal band of boxes/columns, laid out left to right. At least one row is required. |
column | Groups two or more boxes into one row slot, stacked vertically instead of standing alone. A column needs at least two boxes — one box belongs directly in the row. |
box <name> | Declares one titled area. Its name is a bare identifier or a quoted, multi-word string (see the Text & Links tab). |
color <value> | Optional on a box: a preset name or a hex value (see the Color tab). Overrides only the box's fill; falls back to a fixed neutral fill when omitted. |
ratio <number> | Optional on a row (weighed against other rows' height) or a box inside a column (weighed against its column siblings' share of the shared height). Defaults to 1 when omitted. |
content """...""" | Optional on a box: body text below its title, real line breaks allowed inside. Supports bold, _italic_, [text](target) links, and one flat level of - unordered/1. ordered lists. Grows the box past its ratio if needed. |
A data flow diagram (Gane/Sarson notation) shows processes (circles), external entities/terminators (rectangles) and data stores (open-ended rectangles), connected by directed, labeled data flows. A "context diagram" is simply the special case of exactly one process and no stores.
Every data flow diagram declares at least one process, then connects it to other elements with flow:
type dataflowdiagram
process System
entity Customer
flow Customer -> System "Request"
flow System -> Customer "Response"
entity is an external terminator — someone or something outside the system that sends or receives data. store is a data store — a place data is held between processes:
type dataflowdiagram
process "Order Management" as OM
entity Customer
store Orders
flow Customer -> OM "Order"
flow OM -> Orders "Save order"
flow Orders -> OM "Order data"
A flow always needs at least one endpoint to be a process — entity/store never talk to each other directly, only through a process. process--process is allowed.
process/entity/store all accept an optional as <alias>, the same mechanism as usecasediagram's actor/use case aliases — useful for a long, quoted name a flow would otherwise have to repeat in full:
type dataflowdiagram
process "Order Management" as OM
entity Customer
flow Customer -> OM "Order"
Declaring exactly one process draws a "context diagram" (level 0): the process sits at the center, every entity/store is placed evenly around it. Declaring more than one process switches to a different layout: processes sit in a row, with entities/stores clustered above or below near whichever process(es) they connect to:
type dataflowdiagram
process A
process B
entity Source
store Log
flow Source -> A "Input"
flow A -> Log "Write"
flow Log -> B "Read"
flow A -> B "Handoff"
diagram = typeDecl ( processDecl | entityDecl | storeDecl ) + flowDecl* ;
processDecl = "process" name [ "as" ident ] ;
entityDecl = "entity" name [ "as" ident ] ;
storeDecl = "store" name [ "as" ident ] ;
flowDecl = "flow" ref "->" ref name ;
ref = name | ident ;
At least one process is required. entity/store are optional and repeatable, declarable in any order alongside process, but every declaration must come before the first flow. A flow's label (the last, quoted name) is never optional — an unlabeled flow has no meaning in this notation.
| Keyword | Meaning / what it controls |
|---|---|
type dataflowdiagram | Required as the first line of the file; selects this diagram's grammar. dataflowdiagram has no theme/color of its own — no natural, repeated element here to color. |
process <name> | Declares a process, drawn as a circle. At least one is required. |
entity <name> | Declares an external entity/terminator, drawn as a plain rectangle. |
store <name> | Declares a data store, drawn as an open-ended rectangle (a name between a top and bottom line, no left/right border). |
as <alias> | Optional on process/entity/store: gives it a short alias, so a flow can reference it instead of repeating a long quoted name. Must be declared before it's used; can only be assigned once. |
flow <a> "->" <b> <label> | Declares a directed, labeled data flow from a to b, referenced by name or alias — at least one of a/b must be a process. The label is mandatory. |
A mind map breaks a central topic down into branches, recursively — structurally the same idea as a goal tree, but drawn radially instead of top-down, and without any decomposition/achievement semantics.
The smallest mind map is a single node with no children (a leaf):
type mindmap
node "Product Launch"
A node with children lists them in a { ... } body — at least one child each. The root's own direct children are split by declaration order, the first half drawn to the left, the rest to the right, each growing outward ring by ring with depth:
type mindmap
node "Product Launch" {
node "Marketing" {
node "Social Media"
node "Press Release"
}
node "Engineering"
}
Each of the root's direct branches is automatically drawn in its own color (cycling through a small fixed palette), inherited by every node underneath it — the central topic itself stays a fixed dark color regardless of that palette.
An optional scheme right after type mindmap swaps the whole visual identity — root/branch colors, border thickness, corner roundness, and whether borders/connectors are dashed. signal (the default) is the look shown above; pastel is softer and rounder; blueprint is monochrome blue with dashed connectors; neon is vivid with thick, bold strokes; ink is grayscale with dashed borders and connectors throughout:
type mindmap
scheme neon
node "Product Launch" {
node "Marketing"
node "Engineering"
}
By default, every connector is a plain line of constant width end to end. An optional linestyle right after type mindmap/any scheme <name> switches to flowing instead, where every connector becomes a filled ribbon that starts noticeably thicker near the center and tapers smoothly down to its usual width — the closer to the center a connector starts, the thicker its own start is, continuing seamlessly from wherever the connector above it left off:
type mindmap
linestyle flowing
node "Product Launch" {
node "Marketing"
node "Engineering"
}
Every node — including the root — can pick how its own children are arranged with an optional layout right after its name: radial (the default) is the arrangement shown above (a ring for the root's direct children, a compact list for everything deeper); horizontal arranges children in a row directly below the node, connected the same way a feature model's parent-child lines are (a plain straight line); vertical instead stacks children in a column below the node, each reached by a strictly orthogonal connector — straight down from the node, then a sharp 90° turn straight across to the child, never a diagonal or curved line, at any nesting depth — both regardless of which side of the diagram the node itself sits on, letting you draw a classic top-down org chart instead of a radial mind map. A node's own layout only affects *its* children — an unrelated branch elsewhere in the same diagram keeps using the default radial arrangement unless it opts in too:
type mindmap
node "CEO" layout horizontal {
node "CTO" layout horizontal {
node "Engineering Manager" layout vertical {
node "Backend Team"
node "Frontend Team"
node "QA Team"
}
}
node "CFO"
node "COO"
}
Here the CEO's direct reports (CTO/CFO/COO) are drawn in a row; the CTO's own single report keeps that row style; the Engineering Manager then switches its own teams to a narrow vertical column instead of widening the chart further.
diagram = typeDecl schemeDecl? linestyleDecl? nodeDecl ;
schemeDecl = "scheme" ( "signal" | "pastel" | "blueprint" | "neon" | "ink" ) ;
linestyleDecl = "linestyle" ( "regular" | "flowing" ) ;
nodeDecl = "node" name [ "layout" ( "radial" | "horizontal" | "vertical" ) ] [ "{" nodeDecl { nodeDecl } "}" ] ;
| Keyword | Meaning / what it controls |
|---|---|
type mindmap | Required as the first line of the file; selects this diagram's grammar. |
scheme signal | scheme pastel | scheme blueprint | scheme neon | scheme ink | Optional, right after type mindmap. Selects the whole visual identity (root/branch colors, border thickness, corner roundness, dashed or solid) — see "Scheme" above. signal is the default. mindmap's own genuinely diagram-specific replacement for the generic theme declaration every diagram type once had. |
signal | scheme's default value — see "Scheme" above. |
pastel | scheme's softer, rounder value — see "Scheme" above. |
blueprint | scheme's monochrome-blue, dashed-connector value — see "Scheme" above. |
neon | scheme's vivid, thick-stroked value — see "Scheme" above. |
ink | scheme's grayscale, fully-dashed value — see "Scheme" above. |
linestyle regular | linestyle flowing | Optional, right after type mindmap/scheme. regular (the default) draws every connector at a constant width end to end; flowing draws a tapered ribbon instead — see "Line style" above. |
regular | linestyle's default value — see linestyle regular above. |
flowing | linestyle's tapered-ribbon value — see linestyle flowing above. |
node <name> | Declares a node. With no children it's a leaf; with a { ... } body it's an internal node, its children drawn one ring further out. |
layout radial | layout horizontal | layout vertical | Optional, right after a node's own name. Controls how *that node's* children are arranged — see "Node layout" above. radial is the default. |
radial | layout's default value — see "Node layout" above. |
horizontal | layout's row value, for a classic top-down org-chart level — see "Node layout" above. |
vertical | layout's column value, for a narrower org-chart branch — see "Node layout" above. |
| Names | A bare identifier or a quoted, multi-word string, with \"/\\/\n support (see the Text & Links tab). |
A Clean Architecture diagram (Robert C. Martin) draws concentric rings — Entities at the core, then Use Cases, then outward through however many layers your architecture needs — each optionally split into named segments.
One ring is already valid:
type cleanarchitecture
ring "Entities" {
segment "Business Objects"
}
A ring's body can hold a further ring nested inside it, in addition to (or instead of) its own segment items — each nested ring becomes the next ring over. By default, the outermost-*written* ring (the one at the top level) is the innermost one, and nesting moves outward — the same convention the Stakeholder Map tab's own rings use:
type cleanarchitecture
ring "Entities" {
ring "Use Cases" {
ring "Interface Adapters" {
segment "Controllers"
segment "Presenters"
segment "Gateways"
}
}
}
Here "Entities" is the innermost ring (drawn as a filled disk), "Interface Adapters" the outermost. A ring can skip segment entirely and hold only a nested ring (a purely organizational wrapper), but a ring with neither segment nor a nested ring is a parse error, and only one ring may be nested per body — concentric rings can't branch into siblings the way a tree can.
segment divides a ring into named angular slices instead of one continuous band — as many as you like, in declaration order:
type cleanarchitecture
ring "Frameworks & Drivers" {
segment "Web"
segment "DB"
segment "Devices"
segment "External Interfaces"
}
An optional color right after a ring's own name overrides its fill — a preset name or a hex value (see the Color tab for the full preset list):
type cleanarchitecture
ring "Interface Adapters" color blue {
segment "Controllers"
}
ring "Frameworks & Drivers" color #8ecae6 {
segment "Web"
}
Without color, a ring falls back to a fixed, position-based default palette (gold at the core, then pink, green, blue, lilac, cycling if there are more rings than colors) — resembling the classic diagram's own look without having to spell out a color on every ring.
Add invert right after type cleanarchitecture to flip which end is which: the top-level ring becomes the *outermost* one instead, and nesting then moves inward:
type cleanarchitecture
invert
ring "Frameworks & Drivers" {
ring "Interface Adapters" {
ring "Use Cases" {
ring "Entities" {
segment "Business Objects"
}
}
}
}
diagram = typeDecl invertDecl? ring ;
invertDecl = "invert" ;
ring = "ring" name [ "color" colorValue ] "{" ringItem* ring? "}" ;
ringItem = segmentDecl ;
segmentDecl = "segment" name ;
| Keyword | Meaning / what it controls |
|---|---|
type cleanarchitecture | Required as the first line of the file; selects this diagram's grammar. |
invert | Optional, right after type cleanarchitecture. Flips which end of the nesting is drawn as the core — see "Inverting the order" above. |
ring <name> [color <value>] { ... } | Declares one concentric ring. Exactly one top-level ring is required. Its body holds zero or more segment items and, optionally, one further nested ring (which becomes the next ring over). A ring needs at least a segment or a nested ring; a nested ring must be the last thing in its parent's body. |
color <value> | Optional, right after a ring's own name — a preset name or a hex value (see the Color tab). Overrides only that ring's fill — see "Color" above. Without it, a fixed, position-based default palette is used instead. |
segment <name> | Optional, inside a ring's body, repeatable. Divides the ring into named angular slices instead of one continuous band — see "Segments" above. |
| Names | A bare identifier or a quoted, multi-word string, with \"/\\/\n support (see the Text & Links tab). |
Nothing rendered yet.