Architecture Diagrams
An architecture diagram is a set of typed nodes, optional groups that zone them, and directed relationships between nodes.
Overview
The model lives in Atelier\Diagram\Architecture\: ArchitectureDiagram, ArchitectureGroup (id, label), ArchitectureNode (id, kind, label, optional groupId), ArchitectureNodeKind (an enum), and ArchitectureRelationship (from, to, optional label). All model classes are immutable.
Reach for it to sketch software structure: system overviews, service boundaries, data tiers, and integration maps. Each node carries a kind badge (COMPONENT, DATABASE, QUEUE, and so on) and groups read as zones. It is a small generic grammar. For formal C4 notation, use C4 diagrams instead.
Format
architecture
title Checkout platform
group Web [Web tier]
component App [Frontend app]
group Data [Data tier]
database Orders [Orders DB]
App -> Api : calls
Node ids match [A-Za-z_][A-Za-z0-9_]*. Node kinds are person, system, container, component, database, queue, and external. A group opens a lane; nodes declared after it belong to it until the next group. There is no end statement and no indentation-derived nesting; indentation is cosmetic. Full grammar: Mermaid support.
Builder API
ArchitectureDiagramBuilder (or Diagram::architecture(), which returns it) is the one way to build the model:
use Atelier\Diagram\Diagram;
$diagram = Diagram::architecture()
->title('Checkout platform')
->group('Web', 'Web tier')
->component('App', 'Frontend app', 'Web')
->component('Api', 'Checkout API', 'Web')
->group('Data', 'Data tier')
->database('Orders', 'Orders DB', 'Data')
->relationship('App', 'Api', 'calls')
->relationship('Api', 'Orders', 'writes')
->build();
Diagram::of($diagram)->saveSvg('architecture.svg');
title()- Sets an optional, non-empty title.
Argument Type Description $textstringDiagram title. group()- Declares a group lane. Duplicate ids throw.
Argument Type Description $idstringUnique group identifier. $label?stringDisplay label; defaults to $id. person()/system()/container()/component()/database()/queue()/external()- Declares a node of the selected kind. Duplicate ids and unknown groups throw.
Argument Type Description $idstringUnique node identifier. $label?stringDisplay label; defaults to $id.$groupId?stringExisting group identifier. node()- Calls the generic form behind the typed node helpers.
Argument Type Description $kindstring|ArchitectureNodeKindNode kind token or enum case. $idstringUnique node identifier. $label?stringDisplay label; defaults to $id.$groupId?stringExisting group identifier. relationship()- Adds a directed relationship. Both endpoints must already be declared.
Argument Type Description $fromstringExisting source node identifier. $tostringExisting target node identifier. $label?stringOptional relationship label. build()- Assembles the immutable
ArchitectureDiagramin declaration order. Validation is eager, so invalid identifiers, duplicate ids, unknown groups, and unknown endpoints throw when declared.
Options
| Setting | Default | Effect |
|---|---|---|
title(string) |
none | heading above the diagram |
group(...) |
none | cluster box laid out left-to-right; ungrouped nodes place outside lanes |
- Node kinds: each kind sets the badge text and its fill/stroke colors (see Themes).
- Determinism: layout is source-order based and deterministic; the same model always yields the same SVG.
Layout\Architecture\ArchitectureLayoutEngine arranges groups as cluster boxes with a header rail, places nodes inside them in a grid by declaration order, and routes relationships between node boxes with atelier/layout's orthogonal router, drawing explicit arrowheads. Relationship labels sit over a halo through the shared route-label helper.
Themes
Node colors are keyed by kind. component uses nodeFillColor / nodeStrokeColor; external uses a muted stroke (mutedTextColor); person, system, container, database, and queue each take a distinct entry from accentColors (cycled by index) for their stroke, kind badge, and a translucent fill wash of the same hue, so a palette with several colors keeps kinds visually separated. Badge text uses backgroundColor so it stays readable on any accent. Group headers, node strokes, and relationship arrows use nodeStrokeColor; labels use textColor.
All presets apply (Theme::default(), dark(), blueprint(), mono(), neutral()), and a Scene\BackgroundPattern (as in blueprint()) sits behind the diagram. See Theming.
Theme::blueprint() gives the same services a deep canvas with high-contrast group boundaries.
Parse
Header keyword: architecture.
$diagram = Diagram::fromMermaid($source); // throws ParseException
$result = Diagram::tryFromMermaid($source); // non-throwing ParseResult
toMermaid() / toMarkdown() serialize a built model back to the canonical form. Full grammar and round-trip rules: Mermaid support.
Debug
On a rejected source, inspect ParseResult::getDiagnostic() (a ParserDiagnostic with a message, a stable code, and a source span) or catch ParseException (getLineNumber(), getSourceLine()). Render a code frame with ParserDiagnosticFormatter:
$result = Diagram::tryFromMermaid($source);
if ($result->isFailure()) {
echo \Atelier\Diagram\Parser\Support\ParserDiagnosticFormatter::format($result->getDiagnostic());
}
See parser diagnostics.