Establishes mandatory standards for Mermaid diagrams in Blue documents: - Neutral theme required for dark/light mode compatibility - Leaf node counting for LR flow warnings (>3 nodes) - Plain text for architecture labels (no emoji color injection) - Shape semantics advisory for new diagrams - Auto-fix for theme declaration only (colors require manual review) Includes alignment dialogue with 10/10 tensions resolved across 3 rounds. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
9.1 KiB
RFC 0043: Mermaid Diagram Standards for Blue Documents
| Status | Accepted |
| Created | 2026-01-30 |
| Spike | 2026-01-30T1521Z-mermaid-diagram-style-guide |
| Dialogue | 2026-01-30T1730Z-rfc-0043-mermaid-diagram-standards |
Summary
Establish mandatory standards for Mermaid diagrams in all Blue-generated documents, ensuring readability in both light and dark modes through the neutral theme, vertical flow preference, and automated lint enforcement.
Problem
Mermaid diagrams in Blue documents have inconsistent styling that causes readability issues:
- Dark mode incompatibility — Custom fill colors (
#e8f5e9,#e3f2fd) designed for light mode become unreadable in dark mode - Invisible text — Dark nodes with no explicit text color disappear against dark backgrounds
- Subgraph label contrast — Colored subgraph backgrounds obscure labels
- Horizontal sprawl —
flowchart LRrequires horizontal scrolling on narrow viewports - No enforcement — Authors must remember style rules manually
This affects:
- ADRs with architecture diagrams
- RFCs with system designs
- Dialogue recordings with flow visualizations
- Any document Blue generates containing Mermaid
Proposal
1. Mandatory Theme Declaration
All Mermaid diagrams MUST begin with the neutral theme declaration:
%%{init: {'theme': 'neutral'}}%%
flowchart TB
...
2. Flow Direction Guidelines
| Direction | When to Use | Enforcement |
|---|---|---|
TB (top-to-bottom) |
Default for all diagrams | — |
LR (left-to-right) |
Only when ≤3 leaf nodes | Advisory warning |
The constraint is horizontal space. LR with 4+ nodes forces horizontal scrolling on narrow viewports.
Node Counting: Count leaf nodes (terminal visual elements), not container subgraphs. A diagram with 2 subgraphs each containing 4 nodes counts as 8 nodes for threshold purposes.
3. Prohibited Styling
The following are NOT ALLOWED:
%% PROHIBITED
style NODE fill:#e8f5e9
style NODE fill:#any-color
classDef custom fill:#color
The neutral theme provides sufficient visual distinction through grayscale shading.
4. Emoji Guidance
| Context | Emoji Allowed | Rationale |
|---|---|---|
| Architecture component labels | No | Platform-dependent color rendering undermines neutral theme |
| Subgraph titles | No | Same dark-mode readability issues as custom fills |
| Annotations/comments | Yes | Non-critical context where variance is acceptable |
Example:
%% GOOD: Plain text architecture labels
subgraph SV["Superviber Control Plane"]
ORCH["Orchestration"]
end
%% BAD: Emoji injects platform-dependent color
subgraph SV["☁️ Superviber Cloud"]
5. Recommended Shape Semantics
Advisory for new diagrams. Legacy documents exempt.
| Shape | Syntax | Semantic |
|---|---|---|
| Rectangle | [text] |
Services, components, processes |
| Rounded | (text) |
User-facing elements, entry points |
| Database | [(text)] |
Data stores, persistence |
| Stadium | ([text]) |
External systems, third-party |
| Hexagon | {{text}} |
Decision points, conditionals |
| Circle | ((text)) |
Events, triggers |
6. Edge Label Guidelines
Advisory, not prescriptive.
- Recommended maximum: 15 characters
- Use abbreviations:
mTLS,gRPC,REST - Longer labels acceptable when clarity requires it
7. Lint Rule Enforcement
Extend crates/blue-mcp/src/handlers/lint.rs (existing infrastructure):
/// Mermaid diagram linting for Blue documents
fn check_mermaid_blocks(content: &str) -> Vec<Diagnostic> {
let mut diagnostics = vec![];
for block in extract_mermaid_blocks(content) {
// REQUIRED: Neutral theme declaration
if !block.contains("'theme': 'neutral'")
&& !block.contains("\"theme\": \"neutral\"") {
diagnostics.push(Diagnostic {
severity: Severity::Error,
message: "Mermaid diagram must use neutral theme".into(),
suggestion: Some("Add: %%{init: {'theme': 'neutral'}}%%".into()),
auto_fix: Some(AutoFix::PrependLine(
"%%{init: {'theme': 'neutral'}}%%".into()
)),
});
}
// PROHIBITED: Custom fill colors (NO auto-fix - preserves semantic intent)
if block.contains("fill:#") || block.contains("fill: #") {
diagnostics.push(Diagnostic {
severity: Severity::Error,
message: "Custom fill colors prohibited in Mermaid diagrams".into(),
suggestion: Some("Remove style directives manually; review semantic intent".into()),
auto_fix: None, // Intentionally no auto-fix
});
}
// ADVISORY: LR flow with >3 leaf nodes
if block.contains("flowchart LR") || block.contains("graph LR") {
let leaf_count = count_leaf_nodes(&block);
if leaf_count > 3 {
diagnostics.push(Diagnostic {
severity: Severity::Warning,
message: format!(
"LR flow with {} leaf nodes may cause horizontal scrolling",
leaf_count
),
suggestion: Some("Consider flowchart TB for better viewport fit".into()),
auto_fix: None,
});
}
}
}
diagnostics
}
/// Count leaf nodes (terminal visual elements, not container subgraphs)
fn count_leaf_nodes(mermaid_content: &str) -> usize {
// Count node definitions: ID[label], ID(label), ID[(label)], etc.
// Exclude: subgraph, end, style, classDef, linkStyle
let node_pattern = regex::Regex::new(r"^\s*(\w+)\s*[\[\(\{\<]").unwrap();
let exclude_keywords = ["subgraph", "end", "style", "classDef", "linkStyle"];
mermaid_content
.lines()
.filter(|line| {
let trimmed = line.trim();
!exclude_keywords.iter().any(|kw| trimmed.starts_with(kw))
&& node_pattern.is_match(trimmed)
})
.count()
}
8. Template Integration
Update Blue's document templates to generate compliant Mermaid by default:
fn generate_mermaid_block(diagram_type: &str, content: &str) -> String {
format!(
"```mermaid\n%%{{init: {{'theme': 'neutral'}}}}%%\n{} TB\n{}\n```",
diagram_type,
content
)
}
Migration
Auto-Fix Scope
| Issue | Auto-Fix | Rationale |
|---|---|---|
| Missing theme declaration | ✓ Yes | Non-destructive prepend |
| Custom fill colors | ✗ No | Preserves semantic intent; requires manual review |
| LR with >3 nodes | ✗ No | Advisory only; architectural choice |
Migration Process
- Run lint with
--fixto auto-add theme declarations - Manual review for custom colors (lint reports, human decides)
- Priority: ADRs > RFCs > Dialogues
Implementation Track
Templates and lint can proceed in parallel:
- Templates: Generate compliant diagrams for new documents
- Lint: Flag violations in existing documents (warning-only mode during transition)
Alternatives Considered
A. dark Theme Only
Rejected: Looks poor in light mode. We need both-mode compatibility.
B. base Theme with Custom Variables
Rejected: Requires verbose themeVariables block in every diagram. High maintenance burden.
C. Pre-render to SVG at Build Time
Rejected: Loses live preview in editors. Adds build complexity.
D. Documentation Only (No Enforcement)
Rejected: Relies on authors remembering. Inconsistency will creep back.
E. New blue_lint Crate
Rejected: Existing lint infrastructure in crates/blue-mcp/src/handlers/lint.rs already handles RFC docs. Extend, don't duplicate.
Success Criteria
- All Mermaid diagrams pass
blue_lintwithout errors - Diagrams readable in VS Code light theme, VS Code dark theme, GitHub light, GitHub dark
- No custom
fill:#directives in any Blue document - Template generates compliant diagrams by default
- Lint runs in parallel with template development
References
- Spike: Mermaid Diagram Style Guide
- Alignment Dialogue — 10/10 tensions resolved
- Mermaid Theming Documentation
- ADR 0005: Single Source of Truth
Tasks
- Extend
lint.rswith Mermaid block extraction - Implement theme declaration check with auto-fix
- Implement fill color check (error, no auto-fix)
- Implement leaf node counting for LR warning
- Update document generation templates
- Migrate existing diagrams in ADRs (manual color review)
- Migrate existing diagrams in RFCs (manual color review)
- Add Mermaid cheatsheet to
.blue/docs/