Diagram Style Guide¶
This site uses Mermaid as the standard for architecture, flow, state, and sequence diagrams. SVG remains available as an exception for geospatial illustrations, high-resolution figures, and cases where Mermaid's layout engine is insufficient.
This guide defines when to use each diagram type, formatting conventions, accessibility requirements, and a reusable snippet library.
When to Use Mermaid vs SVG¶
| Use Mermaid for | Use SVG for |
|---|---|
| Architecture and component diagrams | Geospatial maps and spatial illustrations |
| Pipeline and data flow diagrams | High-resolution design artifacts |
| Comparison diagrams (monolith vs microservices) | Diagrams requiring precise visual positioning |
| Request/response sequence flows | Custom icons or branding elements |
| State machines (embedded firmware, auth flows) | Cases where Mermaid layout is unacceptable |
| Decision trees | β |
Default: if in doubt, use Mermaid. Its text-based format is version-controlled, diffable, and editable by any contributor without tooling.
Diagram Types by Content¶
Flowchart β Architecture and Pipeline Diagrams¶
Use flowchart LR (left-to-right) for most architecture and pipeline diagrams. Use flowchart TD (top-down) for hierarchical structures.
Best for: data pipelines, control plane / data plane separation, service topology, deployment architecture.
Sequence Diagram β Request and Event Flows¶
Use sequenceDiagram for depicting interactions between services or components over time β HTTP requests, event bus publishing, auth flows.
sequenceDiagram
Client->>API: POST /request
API->>Queue: publish event
Queue->>Worker: deliver event
Worker->>API: callback result
Best for: API call flows, message broker interactions, authentication sequences, streaming event propagation.
State Diagram β Embedded Firmware and Lifecycle States¶
Use stateDiagram-v2 for firmware state machines, lifecycle management, and any system with discrete, well-defined states and transitions.
stateDiagram-v2
[*] --> Idle
Idle --> Active: sensor trigger
Active --> Idle: timeout
Active --> Sleep: low battery
Sleep --> Idle: wake timer
Best for: ESP32 firmware state machines, pipeline job state transitions, deployment lifecycle stages.
Formatting Conventions¶
Node labels: keep node text short β 1β4 words. Use abbreviations if needed. Long labels wrap awkwardly and reduce diagram readability.
Orientation: prefer LR (left-to-right) for architecture and pipeline diagrams. Reserve TD (top-down) for hierarchies (DNS trees, org charts, decision trees).
Subgraphs for boundaries: use subgraph blocks to show control plane / data plane separation, organizational boundaries, network zones, or logical groupings.
flowchart LR
subgraph Control Plane
Scheduler
Registry
end
subgraph Data Plane
Worker1
Worker2
end
Scheduler --> Worker1
Scheduler --> Worker2
Complexity limit: keep diagrams under approximately 15 nodes. If a diagram exceeds this, split it into two diagrams: one showing the high-level topology, one showing a specific subsystem in detail.
Consistent arrow semantics: use --> for data flow, ---> for async or eventual flow (when Mermaid supports it via labels), and --label--> for labeled edges when the relationship needs clarification.
Accessibility¶
- Avoid tiny text: Mermaid auto-sizes nodes to their labels. Short labels produce readable diagrams; very long labels produce tiny text. Keep labels concise.
- Avoid deeply nested subgraphs: more than 2 levels of nesting becomes visually ambiguous. Prefer flat diagrams with clear labels over deep hierarchies.
- Split complex diagrams: a reader who cannot parse a diagram in 10 seconds will skip it. If the diagram requires 20+ nodes to represent the concept, split it into a sequence of simpler diagrams.
- Light and dark mode: MkDocs Material renders Mermaid with theme-aware colors. Do not hardcode fill colors β let the theme handle node styling for consistent light/dark rendering.
Mermaid Snippet Library¶
1. Control Plane vs Data Plane¶
flowchart LR
subgraph Control["Control Plane (governs)"]
direction TB
Catalog["Data Catalog"]
Schema["Schema Registry"]
Access["Access Policies"]
Lineage["Lineage Graph"]
end
subgraph Data["Data Plane (flows)"]
direction TB
Files["Parquet Files"]
Events["Kafka Events"]
Tables["Delta Tables"]
Models["Model Outputs"]
end
Catalog -.governs.-> Files
Schema -.enforces.-> Events
Access -.controls.-> Tables
Lineage -.tracks.-> Models 2. Pipeline with Stages¶
flowchart LR
Raw["Raw Source\n(S3 / Kafka)"]
Ingest["Ingest\n(schema validate)"]
Transform["Transform\n(dbt / Spark)"]
Serve["Serve\n(warehouse / API)"]
Monitor["Monitor\n(freshness Β· quality)"]
Raw --> Ingest --> Transform --> Serve
Monitor -.observes.-> Ingest
Monitor -.observes.-> Transform
Monitor -.observes.-> Serve 3. Monolith vs Microservices Comparison¶
flowchart LR
subgraph Monolith["Monolith"]
direction TB
M_UI["UI"]
M_API["API Layer"]
M_BL["Business Logic"]
M_DB["Shared DB"]
M_UI --> M_API --> M_BL --> M_DB
end
subgraph Micro["Microservices"]
direction TB
S_GW["API Gateway"]
S_A["Service A\n+ DB A"]
S_B["Service B\n+ DB B"]
S_C["Service C\n+ DB C"]
S_GW --> S_A
S_GW --> S_B
S_GW --> S_C
end 4. Broker-Based Messaging (MQTT)¶
flowchart LR
Sensor["ESP32 Sensor"]
Broker["MQTT Broker\n(Mosquitto)"]
Sub1["Subscriber\n(Home Assistant)"]
Sub2["Subscriber\n(Data Logger)"]
Sub3["Subscriber\n(Alert Engine)"]
Sensor -->|"publish topic/temp"| Broker
Broker -->|"deliver"| Sub1
Broker -->|"deliver"| Sub2
Broker -->|"deliver"| Sub3 5. Training vs Serving ML Pipeline¶
flowchart LR
subgraph Training["Training Pipeline (offline)"]
direction LR
RawData["Raw Data"]
FeatEng["Feature Engineering\n(batch)"]
Train["Model Training\n(GPU cluster)"]
Registry["Model Registry"]
RawData --> FeatEng --> Train --> Registry
end
subgraph Serving["Serving Pipeline (online)"]
direction LR
Request["Inference Request"]
FeatStore["Feature Store\n(online)"]
Infer["Model Server"]
Response["Prediction Response"]
Request --> FeatStore --> Infer --> Response
end
Registry -.deploy model.-> Infer Authoring a New Diagram¶
- Choose the diagram type from the table above.
- Keep nodes to 15 or fewer.
- Use subgraphs to show system boundaries.
- Label edges when the relationship is not obvious from the node names alone.
- Test that the diagram renders in the MkDocs dev server (
mkdocs serve) before committing. - If the diagram is too complex, split it before submitting.
See also
- SVG Workflow Generation Best Practices β the full Mermaid-first, artifact-driven workflow for producing committed SVG diagrams
- Mermaid β SVG Workflow Pipeline (Tutorial) β step-by-step guide to running the render pipeline