Build a diagram compiler, not a template library.
The durable asset is a typed semantic graph. Every diagram is a view over that model, compiled through a visual language, a layout policy, and a renderer adapter. Style consistency comes from a controlled semantic cascade with explicit overrides, automatic legends, and inspectable provenance.
How to use this guide
Start with the decision register when selecting an architecture. Use the middle sections as implementation contracts. Use the quality gates and red-team findings as release criteria.
Decision makers
Read the executive decision, reference architecture, decision register, roadmap, and material risks.
Architects
Read the question taxonomy, layout router, visual language, semantic cascade, and renderer strategy.
Implementers
Read the canonical model, token schema, computed-style behavior, geometry pipeline, mobile behavior, and validation gates.
Problem framing
Diagram-as-code systems often collapse modeling, styling, layout, rendering, and interaction into one syntax. That works for small diagrams. It fails for distributed systems, ontology, lineage, trust boundaries, runtime state, mobile navigation, and multi-audience communication.
Knowledge
What entities exist? What relationships are factual, inferred, planned, historical, or runtime-derived?
Communication
What question should the view answer? Which audience must understand, decide, or act?
Presentation
Which layout, visual channels, controls, and renderer best express the selected view?
Tool landscape
The major tools operate at different layers. They should be composed rather than compared as if they solve the same problem.
| Class | Representative tools | Best use | Primary limitation |
|---|---|---|---|
| Model-first architecture | LikeC4, Structurizr | Reusable architecture models and scoped views | Not a universal ontology, lineage, or runtime model |
| Textual diagram DSL | Mermaid, D2, PlantUML, nomnoml, Graphviz DOT | Documentation, source control, concise authoring | Renderer-specific syntax and limited interaction |
| Interactive graph UI | React Flow, AntV X6, GoJS | Editors, custom nodes, selection, controls | Automatic layout is external or proprietary |
| Graph analysis | Cytoscape.js, G6, Sigma.js | Topology, clustering, ontology, large graphs | Less suitable for highly authored card layouts |
| Layout engines | ELK, Dagre, D3, WebCola, Graphviz | Positions, routing, constraints, graph aesthetics | Cannot infer domain meaning |
| Rendering gateway | Kroki | Unified access to many textual engines | Compatibility layer, not canonical model |
| Specialized generation | Python Diagrams, WaveDrom, DBML, Penrose | Infrastructure, timing, schema, constraint diagrams | Narrow domain coverage |
| Commercial SDK | yFiles, GoJS | Advanced layout, editing, support | Licensing and vendor dependence |
Primary portfolio
React FlowELKSVGMermaid
Default combination for curated interactive HTML, deterministic layout, portable static output, and documentation export.
Specialized portfolio
Cytoscape.jsSigma.jsD2LikeC4
Use for compound topology, very large graph exploration, technical diagrams, and architecture-model interchange.
Diagram question taxonomy
A diagram should be selected by the question it must answer. One diagram should have one primary communication question.
| Question | Diagram form | Preferred layout |
|---|---|---|
| What systems exist and who uses them? | Landscape or system context | Layered, radial, or curated |
| What is inside this system? | Container or component | Compound layered |
| Where does it run? | Deployment or topology | Layered with containment |
| What calls what? | Dependency graph | Left-to-right layered |
| What happens during this use case? | Sequence or dynamic view | Time vertical, participants horizontal |
| What states can an entity enter? | State machine | Layered or orthogonal cyclic graph |
| Who performs each process step? | Swimlane or BPMN | Flow axis plus ownership lanes |
| Where did this data originate? | Data lineage | Left-to-right layered, expandable detail |
| What concepts exist and relate? | Ontology or knowledge graph | Clustered force, radial, query-focused |
| Where are security boundaries? | Trust-boundary view | Containment plus directional flows |
| When will work happen? | Gantt or timeline | Time scale plus lanes |
| How much flows between stages? | Sankey | Layered weighted flow |
Canonical model and view compiler
The system should model the system once, then compile only the view needed to answer the current question.
Swipe horizontally to inspect the full architecture.
Canonical TypeScript shape
interface DiagramModel {
id: string;
version: string;
generatedAt: string;
entities: Entity[];
relationships: Relationship[];
groups: Group[];
vocabularies: Vocabulary[];
evidence: EvidenceRecord[];
sourceRegistry: SourceRecord[];
}
interface DiagramView {
id: string;
title: string;
question: string;
audience: string[];
perspective:
| "architecture"
| "runtime"
| "deployment"
| "lineage"
| "ontology"
| "security"
| "ownership"
| "temporal";
rootIds: string[];
include: ViewPredicate[];
exclude: ViewPredicate[];
depth: number;
relationshipKinds: string[];
layoutPolicy: LayoutPolicy;
visualPolicy: VisualPolicy;
interactionPolicy: InteractionPolicy;
responsivePolicies: ResponsiveViewPolicy[];
}
Layout system
Layout selection must be question-driven. Different algorithms express different semantic relationships.
Layered
Directed dependencies, requests, event flow, lineage, pipelines, and decision graphs.
Default: ELK Layered.
Force or stress
Ontology, knowledge graphs, unknown clusters, and ecosystem exploration.
Default: Cytoscape fCoSE.
Constraint
Trust boundaries, lanes, fixed anchors, ownership, ports, and semantic alignment.
Default: ELK constraints or WebCola.
Hierarchy
Taxonomy, decomposition, ownership, package trees, and call trees.
Default: D3 tree or ELK.
Radial
Blast radius, dependency depth, one selected system and its neighborhood.
Rule: radial distance must mean something.
Timeline or lane
Sequence, Gantt, event history, ownership flow, and incident causality.
Rule: time must be an explicit axis.
Layout router
function selectLayout(ctx: LayoutContext): LayoutFamily {
if (ctx.hasTimeAxis) return "timeline";
if (ctx.hasGeography) return "geographic";
if (ctx.hasFixedPositions || ctx.hasSemanticLanes) return "constraint";
if (ctx.isRootedTree && !ctx.hasContainment) return "tree";
if (ctx.isDirectedAcyclic || ctx.dominantDirectionRatio >= 0.7) {
return ctx.hasContainment ? "compound" : "layered";
}
if (ctx.highDegreeNodeCount > 0 && ctx.purpose === "explain") {
return "radial";
}
if (ctx.purpose === "explore") return "force";
return "constraint";
}
Visual language
Each visual channel should have one dominant meaning. The same color, border, or line type must not encode unrelated dimensions.
Relationship grammar
| Relationship | Stroke | Arrow | Notes |
|---|---|---|---|
| Synchronous request | Solid | Filled | Label protocol and operation |
| Asynchronous event | Dashed | Open | Label topic or event |
| Data movement | Solid accent | Filled | Label schema or data class |
| Dependency | Thin solid | Open | Avoid implying runtime traffic |
| Fallback | Long dash | Open | Label trigger condition |
| Inferred relationship | Dotted | Open | Show confidence and provenance |
| Administrative control | Dash-dot | Labeled | Separate from data plane |
Settings architecture
The system should separate environment, reusable design decisions, semantic recipes, matching rules, and deliberate exceptions.
Settings
Layout engine, direction, routing, zoom, density, legend position, mobile projection, print behavior.
Tokens
Reusable design decisions such as colors, typography, spacing, node dimensions, motion, and line strength.
Styles
Named visual recipes such as node.service, relationship.async, or confidence.inferred.
Rules
Selector-based application of styles using kind, tags, metadata, hierarchy, relationship endpoints, state, or zoom.
Overrides
Explicit exceptions with reason, author, issue, creation date, and optional expiry.
Legend
A compiled representation of the semantic language currently used in the view.
Semantic cascade
The system should use an ordered, property-by-property cascade. It should not reproduce CSS specificity.
Swipe horizontally to inspect the full cascade.
!important. Exact IDs exist only in the override layer.Channel ownership
| Semantic dimension | Primary channels | Secondary channels |
|---|---|---|
| Entity kind | Shape, icon, base fill | Base border |
| Relationship kind | Line pattern, arrowhead | Line color |
| Domain or category | Fill hue or accent rail | Group header |
| Ownership | Container, label, corner marker | Accent |
| Lifecycle | Border pattern, badge | Muted opacity |
| Runtime health | Status marker, halo | Border color |
| Confidence | Line pattern, marker | Opacity |
| Trust | Boundary and boundary label | Edge crossing marker |
| Selection | Outer ring, handles | Elevation |
| Quantitative magnitude | Width or size | Sequential color |
Tokens, named styles, rules, and expressions
Token layers
- Primitive tokens
Literal colors, dimensions, timing values, and font families. - Semantic tokens
Meaning-bearing aliases such ascolor.node.service.fill. - Context modifiers
Light, dark, high contrast, screen, print, mobile, desktop, compact, reduced motion. - Resolved map
Concrete values for the active context before element rules are applied.
Named style example
styles:
node.service:
appliesTo: node
facet: kind
properties:
shape: rounded-rectangle
fill: "{color.node.service.fill}"
borderColor: "{color.node.service.border}"
icon: "{icon.node.service}"
paddingInline: "{space.node.padding.inline}"
paddingBlock: "{space.node.padding.block}"
legend:
group: Elements
label: Service
description: Independently deployable software service
Rule example
rules:
- id: services
layer: kind
select:
kind: service
use:
- node.service
- id: deprecated-elements
layer: facet
select:
tags:
contains: deprecated
use:
- lifecycle.deprecated
Restricted expression example
{
"$expr": [
"step",
["zoom"],
"hidden",
0.65,
"title-only",
1.0,
"title-and-technology",
1.4,
"full"
]
}
Legend system
The legend must be generated from the same semantic style definitions that render the diagram.
- Resolve the current view.
- Resolve computed styles for visible elements.
- Record semantic styles that contributed visible meaning.
- Deduplicate and order legend entries.
- Render swatches using the same resolved tokens.
- Add continuous scales for quantitative mappings.
- Exclude interaction-only states unless an interaction guide is requested.
Legend modes
UsedFull languageCustomCompactExplanatory
Override rule
A semantic override must reuse an existing legend-backed style, add a legend definition, or fail validation.
Computed-style inspector example
Payment API
──────────────────────────────────
fill
Result: #315DA8
Token: color.node.service.fill
Context: dark / standard contrast
Applied by: style node.service
Rule: kind = service
borderStyle
Result: dotted
Applied by: style lifecycle.deprecated
Rule: tag contains deprecated
size
Result: large
Applied by: element override
Reason: Primary subject of decision view
Text, node sizing, and alignment
Layout must use measured node dimensions after the final font and content are available.
- Load the actual font.
- Normalize title and metadata content.
- Measure text runs and semantic wrap points.
- Calculate width, height, icon rail, badges, and ports.
- Run layout and route edges.
- Measure edge labels and detect collisions.
- Repair spacing, scope, or orientation.
Alignment rules
- Use a fixed icon or number rail.
- Top-align leading icons, badges, or numbers with the title stack.
- Do not vertically center them against title-plus-description height.
- Reset heading margins inside nodes.
- Use a shared spacing scale for padding, labels, ports, and lane gutters.
- Validate optical centering of SVG glyphs inside wrappers.
- Never shrink text below the readability floor simply to fit the full graph.
Mobile and viewport behavior
A mobile diagram is a different projection of the same model, not a desktop screenshot scaled down.
Viewport controls
- Fit all
- Fit selection
- 100% semantic scale
- Reset view
Responsive recompilation
- Left-to-right becomes top-to-bottom.
- Lower-level groups collapse.
- Secondary labels move into a detail panel.
- Full topology becomes selected-node neighborhood.
Semantic zoom
| Level | Visible information |
|---|---|
| Landscape | Domains, systems, trust zones, aggregate relationships |
| System | Containers, important relationships, ownership |
| Component | Components, protocols, state, key metadata |
| Detail | Attributes, evidence, fields, provenance, runtime metrics |
Input and accessibility
Provide pinch zoom, wheel and trackpad zoom, pan, keyboard traversal, search, breadcrumbs, a synchronized node list, non-drag alternatives, focus visibility, screen-reader summaries, and reduced-motion behavior.
Quality gates
1 · Model validity
IDs, endpoints, containment, temporal consistency, provenance, and lifecycle state.
2 · View validity
Primary question, audience, scope, legend, acronyms, and complexity budget.
3 · Geometry
No overlap, clipping, hidden arrowheads, edge-label collisions, or connector intrusion.
4 · Visual language
One meaning per channel, legend parity, theme consistency, and redundant cues.
5 · Accessibility
Contrast, keyboard, focus, target size, reduced motion, text alternative, and forced colors.
6 · Responsive behavior
320, 390, 768, 1024, and 1440 pixels, plus orientation and text zoom.
7 · Communication
Scope, main relationship, boundaries, risk, and intended action are evident.
Complexity repair order
- Remove unrelated relationships.
- Aggregate repeated nodes.
- Collapse lower-level groups.
- Replace repeated edges with aggregate edges.
- Move metadata into details.
- Split temporal and structural concerns.
- Generate coordinated views.
- Introduce semantic zoom and neighborhood isolation.
Skill and memory design
The future diagram-architect skill should retain durable decision logic, renderer limitations, battle scars, validation rules, and accepted fixtures.
diagram-architect/
├── SKILL.md
├── CHANGELOG.md
├── references/
│ ├── diagram-question-taxonomy.md
│ ├── visual-language.md
│ ├── layout-router.md
│ ├── style-system.md
│ ├── token-resolution.md
│ ├── legend-generation.md
│ ├── responsive-diagrams.md
│ └── evaluation-framework.md
├── profiles/
│ ├── c4-architecture.md
│ ├── topology.md
│ ├── ontology.md
│ ├── lineage.md
│ ├── state-machine.md
│ ├── process-swimlane.md
│ └── timeline-gantt.md
├── battle-scars/
│ ├── connector-border-collision.md
│ ├── layout-before-measurement.md
│ ├── unreadable-fit-view.md
│ ├── mobile-desktop-shrink.md
│ ├── css-specificity-war.md
│ ├── legend-drift.md
│ ├── one-off-color-language.md
│ └── raw-literal-proliferation.md
└── evals/
├── routing.json
├── geometry.json
├── responsive.json
├── accessibility.json
└── comprehension.json
Retrieval workflow
- Classify the diagram question.
- Retrieve one primary diagram profile.
- Retrieve one renderer profile.
- Retrieve five to nine relevant battle scars.
- Select one primary layout technique.
- Compile, audit, repair, and record reusable findings.
Recommended system decisions
These decisions form the initial architecture baseline. Each remains reversible until production fixtures and performance evidence justify commitment.
| Decision | Recommendation | Why | Material alternative |
|---|---|---|---|
| Canonical model | Custom typed TypeScript graph | Covers architecture, lineage, ontology, evidence, time, and policy without renderer coupling. | LikeC4 or Structurizr as the sole source model. |
| Primary layout | ELK | Layering, ports, compound graphs, constraints, and routing suit distributed systems. | Dagre for simple graphs; yFiles for premium supported layout. |
| Interactive renderer | React Flow | Custom HTML nodes, controls, selection, accessibility primitives, and React integration. | AntV X6 or GoJS. |
| Analytical graph | Cytoscape.js | Compound topology, filtering, graph analysis, and query-focused exploration. | AntV G6. |
| Large graph | Sigma.js | WebGL rendering and Graphology integration. | G6 GPU/WASM or yFiles. |
| Portable static output | Native SVG plus semantic HTML | Accessibility, print quality, responsiveness, and no runtime dependency. | Canvas or server-rendered PNG. |
| Token core | DTCG-compatible tokens | Typed aliases, groups, context resolution, and portable interchange. | Custom token format. |
| Style resolution | Fixed ordered cascade without CSS specificity | Deterministic, explainable, and safe for visual controls. | Native CSS cascade or renderer-local style rules. |
| Legend | Compile from semantic styles | Prevents drift between notation and explanation. | Manually maintained legend. |
| Mobile | Responsive view recompilation | Preserves readability and intent instead of shrinking the desktop view. | Fit-to-view only. |
Implementation roadmap
Phase 1 · Contracts
Canonical TypeScript model, view specification, visual-token schema, layout router, evaluation schema, and initial fixtures.
Phase 2 · Static compiler
ELK adapter, SVG renderer, Mermaid and LikeC4 export, text measurement, geometry audits, legend, and provenance.
Phase 3 · Interactive HTML
React Flow renderer, semantic zoom, selection, isolation, search, breadcrumbs, fit controls, and accessible list.
Phase 4 · Specialized graphs
Cytoscape.js, Sigma.js, OpenLineage ingestion, cloud inventory, runtime overlays, and stable diff layouts.
Phase 5 · Diagram intelligence
Question-to-view generation, automatic scope reduction, geometry repair, language linting, and comprehension testing.
Repository shape
diagram-system/
├── packages/
│ ├── model/
│ ├── ingestion/
│ ├── view-compiler/
│ ├── visual-language/
│ ├── layout/
│ ├── renderers/
│ ├── exporters/
│ └── evaluation/
├── skills/
│ └── diagram-architect/
├── fixtures/
│ ├── topology/
│ ├── ontology/
│ ├── lineage/
│ ├── sequence/
│ ├── state/
│ └── mobile/
└── apps/
├── diagram-studio/
└── static-artifact-builder/
Material risks and controls
No universal renderer
React Flow, Mermaid, LikeC4, Cytoscape.js, Sigma.js, and SVG solve different problems.
Control: renderer portfolio behind one compiler.
Automatic layout lacks domain knowledge
Algorithms optimize geometry, not architecture meaning.
Control: semantic constraints and view contracts.
Large graphs still become hairballs
Rendering capacity does not equal comprehension.
Control: scoped subgraphs, aggregation, semantic zoom, and coordinated views.
Style systems can become opaque
CSS-like specificity and inline overrides make behavior hard to explain.
Control: fixed cascade layers and computed-style provenance.
Mobile fit is not mobile communication
Labels may technically fit while becoming unreadable.
Control: responsive recompilation and semantic zoom.
Metrics are incomplete proxies
Few crossings do not prove understanding.
Control: task-based comprehension evaluation.
Primary sources
This guide consolidates the prior research and design synthesis. The following primary references informed the conclusions.
| Guide area | Primary evidence | Nature of conclusion |
|---|---|---|
| Model and views | LikeC4, Structurizr, OpenLineage | Observed capabilities plus a custom-model recommendation. |
| Layout | ELK, React Flow, Graphviz, Cytoscape.js, G6 | Observed algorithm portfolios plus question-driven routing. |
| Style cascade | LikeC4, Cytoscape.js, Vega-Lite, Mermaid, D2 | Cross-system synthesis into a simpler ordered cascade. |
| Tokens and expressions | DTCG, Mapbox expressions, Material Color Utilities | Standards-aligned recommendation with diagram-specific extensions. |
| Mobile and accessibility | React Flow, SVG, WCAG 2.2 | Observed platform behavior plus responsive projection rules. |
| Evaluation | Physics of Notations, graph aesthetics research, WCAG | Evidence-informed quality model requiring internal benchmark validation. |
Evidence map
- LikeC4 documentation
- Structurizr documentation
- Mermaid diagram syntax and examples
- Mermaid theming and configuration
- React Flow API reference
- React Flow layout guidance
- React Flow accessibility guidance
- Cytoscape.js documentation
- Cytoscape.js layout guidance
- Sigma.js documentation
- AntV G6 layout overview
- AntV X6 overview
- ELK Layered reference
- Graphviz layout engines
- Kroki diagram rendering gateway
- yFiles for HTML
- GoJS documentation
- D2 classes
- Vega-Lite configuration
- Mapbox style expressions
- Design Tokens Community Group format
- Material Color Utilities
- D3 chromatic scales
- WCAG 2.2
- WCAG animation guidance
- OpenLineage object model
- Physics of Notations
Methodology
The research was organized by problem layer: modeling, view selection, visual language, style resolution, layout, rendering, interaction, accessibility, and validation. Tool capabilities were treated as complementary. Recommendations were then red-teamed against portability, mobile use, semantic clarity, renderer limitations, and long-term maintainability.