VGL Guide — Concepts
Estimated reading time: 7 minutes.
Concepts
The document
Every VGL document declares a notation, which fixes the node and edge types available:
vgraph <graph_id>: <NOTATION> "<graph_label>" {
...
}
Nodes
node <id>: <NodeType> "<label>" [<attributes>];
The id must be unique in the document; the label and attributes are optional.
node q1: Question "What should we do?" [fontsize: 16; color: red];
Edges
edge <from_id> -> <to_id>: <EdgeType> "<label>" [<attributes>];
Both endpoints must be declared. Omit the edge type and VGL infers it from the node types, whenever that is unambiguous — which is most of the time, so most documents never name an edge type at all.
edge q1 -> a1: answered_by "Initial solution";
edge a1 -> pro1 [style: dashed];
edge q2 -> a2; // type inferred
Groups
Groups organise nodes hierarchically, nest to any depth, and may carry attributes. Edges may cross group boundaries freely.
group research "Research Phase" {
style: filled;
color: lightblue;
node q1: Question "What to research?";
node a1: Answer "User interviews";
group methodology "Methods" {
node m1: Pro "Direct feedback";
};
};
Folded groups. Prefix a group with folded to render it collapsed into a single box. Folding auto-redirects any edges that crossed the boundary to the collapsed box, and the editor can fold and unfold in place.
folded group methodology "Methods" { … };
Typed groups. A group can carry a type after its id, mirroring node typing —
group <id>: <GroupType> "<label>" { … }. The type selects its appearance: a C4 Organisation draws a dashed boundary when unfolded and a grey card when folded. See C4.
Detailed nodes. When the type is a node type rather than a group type, the group is a detailed node: the node itself, with its details inside —
group ibs: SoftwareSystem "Internet Banking System" { … }. It takes the node's attributes (url, tooltip, backgroundcolor, …) in its body and in views; a key that a node and a group share means the node's. It starts folded;
isfolded: false in a view (or in its body) opens it, and the boundary it then draws comes from its node type. See ADR-0032.
Views
One file can show its model several ways. A vview after the vgraph block changes only how things are shown — fold state, layout direction, colours — never what is true, so quality checks read the same in every view.
vview context "System Context" {
folded node type: SoftwareSystem;
}
vview containers "Containers" [rankdir: LR] {
node db [backgroundColor: "#ffd27f"];
node customer, web [fontsize: 16];
}
A view sets presentation attributes on node/group ids or, spelled with a colon, on a type (node type: Container). It cannot type, label or add members. A value equal to what the model already gives is dropped on export, so a view follows the model rather than pinning it. A view naming something the model lacks is kept and affects nothing.
A view also chooses what it shows, with rules applied in order. include and
exclude take a selector — node/group ids, node type:/group type: names, or * — optionally widened along edges by +n (n steps either way),
downstream n or upstream n; expand n widens the result so far. A view whose first rule is include starts empty, any other starts with everything. Selectors always read the model, never what earlier rules left. Edges are never selected: one shows when both its ends do, and where a view hides the middle of a chain it draws a dotted derived edge instead (derivedEdges: false turns them off). A rule chooses elements and sets nothing.
vview journey "Customer journey" {
include node customer downstream 2;
exclude node type: Database;
}
A node type also stands for its detailed nodes: `include node type: SoftwareSystem shows them with their details, and folded node type: SoftwareSystem folds them. group type:` picks plain groups only.
The model itself is the default view. Pick another by name:
vgraph-cli svg --view context.
Attributes
Inline in brackets, [a: 1; b: 2], or as bare statements inside a graph or group body.
| Applies to | Attributes |
|---|---|
| Node | color, fontColor, fontsize, shape, url, alignGroup (nodes sharing a value are placed at the same rank) |
| Edge | style (solid/dashed/dotted), color, weight, label, url |
| Group | style (filled/dashed/dotted), color, label, url |
| Graph | rankdir (LR/TB), fontcolor, labeljust (l/r/c), loopMarkers (all/independent/none, Causal Loop Diagrams: which loops get an R/B marker), watermark (true by default; false leaves the Vithanco mark off the exported image) |
Colouring one node. color sets a node's fill, overriding whatever its type says. fontColor sets the text on it; leave it out and the text is set to black or white for contrast, but only where it would otherwise stop being legible.
node epBackend: Container "Equipment Pooling Backend" [color: "#b6e6bd"];
node onApp: Container "ON App" [color: "#ffe08a"; fontColor: "#5c3d00"];
This is a per-node exception, not a second axis: the node keeps its type, so its shape, its stereotype line and every quality check still apply. Use it to mark what is new or changed in an otherwise ordinary diagram, and say what the colours mean somewhere the reader can see.
Every colour in VGL — a node's, an edge's, a group's, a graph's fontcolor — is a hex value or one of the 147 SVG colour keywords (red, cornflowerblue,
whitesmoke). Graphviz's larger X11 set is not accepted: chartreuse3 is an error, not a silent no-op. A name you write is kept as you wrote it when the document is exported; it is never derived back from a colour, since grey and gray are the same value.
Links
Any node, edge or group may carry a url pointing at whatever the element stands for — a ticket, a repository, a wiki page:
node q1: Question "Which datastore?" [url: "https://issues.example.com/ARCH-14"];
A linked element wears a small badge, clipped to its corner or sitting on the line for an edge. Clicking it follows the link in a new tab; hovering shows the destination first. The right-click menu carries Add URL… / Change URL…, Open URL and Remove URL.
Only http, https and mailto are accepted, and anything without a scheme is read as https://. Other schemes — javascript: above all, which would otherwise run as the page displaying the diagram — are refused. The check runs again at render time, so hand-written VGL cannot smuggle one into a published SVG either.
The badge is a real SVG link, so an exported SVG stays clickable wherever it is embedded (inline or via <object>; an SVG inside an <img> is inert by browser design).
Comments
// to end of line, anywhere in the document. Comments are not discarded: a comment belongs to the declaration it stands above, or follows on the same line, and is written back on save or export.
An element's leading comments are the whole block above it, back to the previous declaration — a blank line inside the block does not break it, so a section banner keeps its place:
// ==========================================
// TOP LEVEL - Undesirable Effects
// ==========================================
// Top row
node ude1: UndesirableEffect "Suppliers display a less uniform front";
A comment with nothing to belong to is dropped: before a closing brace, inside a vnotation block, or after the final }.
comment is reserved as an attribute name. [comment: "text"] is an equivalent way to attach one — useful when generating VGL programmatically — and it re-exports as a // text line.
Type inference and minimal syntax
Everything optional, omitted:
vgraph minimal: IBIS "Minimal Example" {
node q1: Question "Which database should we use?";
node a1: Answer "PostgreSQL";
node a2: Answer "MongoDB";
node p1: Pro "ACID compliance";
node c1: Con "More complex setup";
edge q1 -> a1; // inferred: answered_by
edge q1 -> a2;
edge a1 -> p1; // inferred: supports
edge a1 -> c1; // inferred: objects_to
}
Home