Write the final diagram into the target .md file. Add **Figure N:** *description* label.
Pre-Flight Checklist (Steps A-T-A)
Before writing any Mermaid code, answer these:
□ Diagram type selected (flowchart/sequence/gantt/quadrant/etc.)
□ Layout direction chosen (LR preferred for flow, TD for hierarchy)
□ Subgraph strategy decided (Medallion vs Lineage vs Pipeline)
□ Color assignments mapped (what color = what meaning)
□ Multi-line node labels use <br/> NOT \n
Quality Gate (Steps C-C-U)
After creating the diagram, verify ALL of these:
□ Init directive is FIRST line inside mermaid block
□ edgeLabelBackground is '#ffffff' (white background for edge labels)
□ ALL nodes have style/classDef (no unstyled nodes)
□ Colors are GitHub Pastel v2 (NOT saturated: no #51cf66, #339af0, #fab005)
□ linkStyle default stroke:#57606a,stroke-width:1.5px (flowcharts)
□ Node labels use <br/> for line breaks, NOT \n
□ Diagram rendered and visually inspected
□ No dimension > 3x the other (use subgroups to balance)
□ Figure label added below diagram block
□ Written to target file (not just shown in chat)
Common Violations This Prevents
Violation
ATACCU Step That Catches It
Saturated colors instead of pastels
Apply Skills — load palette first
Missing init directive
Apply Skills — it's step 3
edgeLabelBackground: 'transparent' used
Apply Skills — use '#ffffff' (white background)
\n in node labels (renders as literal text)
Create — use <br/> for line breaks
Missing linkStyle
Create — every flowchart needs it
Lopsided layout (7-way fan-out)
Think — choose layout pattern
Diagram only in chat, not in file
Update — write to .md file
No figure label
Update — add label
VS Code 1.109+ Native Chat Rendering
VS Code 1.109 introduces native Mermaid rendering in chat via the renderMermaidDiagram tool.
When to Use Native Rendering
When creating diagrams in Copilot Chat (not markdown files), use the native tool for:
Interactive exploration: Pan, zoom, and full-screen viewing
Immediate feedback: See diagrams without switching to markdown preview
Iterative refinement: Quick edits with instant re-render
Copy source: Extract the Mermaid code for documentation
Usage Pattern
User: Create a sequence diagram showing OAuth flow
Alex: [uses renderMermaidDiagram tool]
→ Interactive diagram appears in chat
→ User can pan/zoom/fullscreen
→ "Copy source" extracts code for docs
When NOT to Use
Documentation authoring: Use markdown code blocks for .md files
GitHub rendering: Embed Mermaid in markdown for native GitHub support
Presentations: Export to image formats or use D2
Combined Workflow
Design in chat: Use renderMermaidDiagram for rapid iteration
Finalize: Copy the Mermaid source code
Document: Paste into markdown file with ```mermaid code fence
Assets
File
Purpose
markdown-light.css
VS Code preview styling
polish-mermaid-setup.prompt.md
Interactive Mermaid configuration helper
Setup: Copy CSS to .vscode/, add "markdown.styles": [".vscode/markdown-light.css"] to settings.
Mermaid Config: Run the "Polish Mermaid Setup" prompt to configure Mermaid rendering for your VS Code environment.
Markdown Best Practices
Document Structure Template
# Title> Brief description or tagline
---
## Overview
Introductory paragraph explaining the purpose.
---
## Section 1
Content with proper formatting.
### Subsection 1.1
More detailed content.
---
## Tables**Table N:***Description of what the table shows*
| Column 1 | Column 2 |
| -------- | -------- |
| Data | Data |
---
## Diagrams` ` `mermaid
flowchart LR
A --> B
` ` `
**Figure N:***Description of what the diagram shows*
---
*Footer or closing statement*
Figure and Table Conventions
Mandatory Labeling: Every diagram and table MUST have a label:
**Figure 1:***Description in italics***Table 1:***Description in italics*
Numbering: Sequential within document, reset per document
Placement: Label immediately follows the diagram/table block
🏷️ Shields.io Badges
Badge Anatomy
Badges use Shields.io - a free service for generating status badges.
@startuml
!theme aws-orange
participant User
participant System
participant Database
User -> System: Request
System -> Database: Query
Database --> System: Response
System --> User: Result
@enduml
Graphviz DOT (Complex Networks):
digraph G {
rankdir=TB;
node [shape=box, style=filled, fillcolor=lightblue];
A -> B;
A -> C;
B -> D;
C -> D;
}
%%{init}%% directive with edgeLabelBackground: '#ffffff'
classDef or style for node colors
linkStyle default stroke:#57606a for arrow color
Edge labels |text| with white background (from init)
💡 For color theory and design principles, see the graphic-design skill. The palette values here come from that skill's color system, optimized for GitHub rendering.
A --> B Standard arrow
A --- B Line without arrow
A -.-> B Dotted arrow
A ==> B Thick arrow
A --"label"--> B Labeled edge
A -->|"label"| B Alternative label syntax
Color Palette (Legacy — GitHub-Compatible)
Note: Superseded by GitHub Pastel Palette v2 below. Kept for reference only.
Purpose
Background
Border/Stroke
GitHub Light
#f6f8fa
#d1d9e0
Text
-
#1f2328
Lines
-
#656d76
Success
#e8f5e9
#2e7d32
Info
#e3f2fd
#1565c0
Warning
#fff3e0
#ef6c00
Special
#f3e5f5
#7b1fa2
Danger
#ffebee
#c62828
Neutral
#f5f5f5
#424242
GitHub Pastel Palette v2 (Default)
Higher contrast, better accessibility. Always use this palette for new diagrams.
flowchart LR
A[Source] --> |Transform| B[Target]
style A fill:#ddf4ff,color:#0550ae,stroke:#80ccff
style B fill:#d3f5db,color:#1a7f37,stroke:#6fdd8b
linkStyle default stroke:#57606a,stroke-width:1.5px
Key Principles:
Light fills (#fff1e5, #ddf4ff) — Easy on the eyes
Medium text (#953800, #0550ae) — Readable but not harsh
Soft strokes matching fill family
Gray arrows (#57606a) — Neutral, doesn't compete with nodes
1.5-2px stroke-width — Visible but not heavy
edgeLabelBackground: '#ffffff' — White background for readable edge labels
Fishbowl Pastel Palette (Alternative)
Softer palette with uniform dark text. Good for governance, compliance, and presentation diagrams.
When to choose Fishbowl over GitHub Pastel v2: Use Fishbowl when all nodes need equal visual weight (e.g., governance structures, compliance flows). Use GitHub Pastel v2 when nodes carry semantic meaning that should be color-coded by category.
classDef blue fill:#ddf4ff,color:#0550ae,stroke:#80ccff
classDef green fill:#d3f5db,color:#1a7f37,stroke:#6fdd8b
classDef purple fill:#d8b9ff,color:#6639ba,stroke:#bf8aff
classDef gold fill:#fff8c5,color:#9a6700,stroke:#d4a72c
classDef red fill:#ffebe9,color:#cf222e,stroke:#f5a3a3
classDef bronze fill:#fff1e5,color:#953800,stroke:#ffb77c
classDef neutral fill:#eaeef2,color:#24292f,stroke:#d0d7de
Apply to multiple nodes: class A,B,C blue
Apply inline: A[Label]:::blue
Subgraph Styling
Style subgraph backgrounds with the style directive using the subgraph ID:
flowchart LR
subgraph SG1["Phase 1"]
direction TB
A --> B
end
subgraph SG2["Phase 2"]
direction TB
C --> D
end
style SG1 fill:#ddf4ff,stroke:#80ccff,color:#0550ae
style SG2 fill:#d3f5db,stroke:#6fdd8b,color:#1a7f37
Key: Use fill for background, keep it light. The color property sets the title text color.
Gantt Chart Theming
Gantt charts use different theme variables than flowcharts:
Problem: Diagrams become too wide (horizontal) or too tall (vertical), causing poor readability
Detection: Look for diagrams where one dimension is 3x+ the other
Pattern: Use opposing directions for outer flowchart vs. inner subgraphs:
%% Pattern 1: TD outer with LR inner (vertical stack of horizontal lanes)
flowchart TD
subgraph Phase1["Phase 1"]
direction LR
A --> B --> C
end
subgraph Phase2["Phase 2"]
direction LR
D --> E --> F
end
%% Pattern 2: LR outer with TB inner (horizontal flow of vertical stacks)
flowchart LR
subgraph Group1["Group 1"]
direction TB
A --> B --> C
end
subgraph Group2["Group 2"]
direction TB
D --> E --> F
end
Anti-Pattern 1: Single subgraph with opposing direction has no effect (nothing to stack)
%% WRONG - single subgraph, direction LR does nothing useful
flowchart TD
subgraph Only["Only Subgraph"]
direction LR
A --> B --> C --> D --> E %% Still very wide!
end
%% RIGHT - break into multiple subgraphs
flowchart TD
subgraph Phase1["Setup"]
direction LR
A --> B
end
subgraph Phase2["Execute"]
direction LR
C --> D
end
Anti-Pattern 2: Cross-subgraph edges defined inside subgraphs (causes layout confusion)
%% WRONG - edge to next subgraph defined inside source subgraph
flowchart TD
subgraph Phase1["Setup"]
direction LR
A --> B
B --> C %% C is in Phase2!
end
subgraph Phase2["Execute"]
direction LR
C --> D
end
%% RIGHT - cross-subgraph edges defined outside all subgraphs
flowchart TD
subgraph Phase1["Setup"]
direction LR
A --> B
end
subgraph Phase2["Execute"]
direction LR
C --> D
end
B --> C %% Cross-subgraph edge outside
subgraph Phase3["Complete"]
direction LR
E
end
Anti-Pattern 3: Independent subgraphs without connections default to vertical stacking
%% WRONG - no connections between subgraphs, ignores LR direction
flowchart LR
subgraph A["Group A"]
direction TB
A1 --> A2
end
subgraph B["Group B"]
direction TB
B1 --> B2
end
%% Result: Groups stack vertically despite LR!
%% RIGHT - invisible links force horizontal layout
flowchart LR
subgraph A["Group A"]
direction TB
A1 --> A2
end
subgraph B["Group B"]
direction TB
B1 --> B2
end
A ~~~ B %% Invisible link forces LR arrangement
Named Layout Patterns
Use these named patterns for consistent, well-proportioned diagrams. Each combines an outer flowchart direction with inner subgraph directions.
Medallion Pattern (TD + LR)
Use when: Phases/layers stack vertically, each containing a horizontal flow.
flowchart TD
subgraph Phase1["Phase 1: Ingestion"]
direction LR
A[Source] --> B[Validate] --> C[Store]
end
subgraph Phase2["Phase 2: Processing"]
direction LR
D[Load] --> E[Transform] --> F[Enrich]
end
Phase1 --> Phase2
Result: Compact rectangle. Good for pipelines, ETL stages, layered architectures.
Lineage Pattern (LR + TB)
Use when: Groups flow left-to-right, each containing a vertical stack.
flowchart LR
subgraph Cluster1["Input"]
direction TB
A1[Raw] --> A2[Clean]
end
subgraph Cluster2["Process"]
direction TB
B1[Compute] --> B2[Validate]
end
subgraph Cluster3["Output"]
direction TB
C1[Format] --> C2[Deliver]
end
Cluster1 --> Cluster2 --> Cluster3
Result: Wide timeline-like layout. Good for data lineage, system boundaries, progression.
Pipeline Pattern (LR + LR)
Use when: Everything flows left-to-right (flat pipeline, no vertical stacking needed).
Result: Simple horizontal chain. Good for CI/CD, request flows, simple sequences.
Pattern Decision Matrix
Your Content
Pattern
Outer
Inner
Typical Shape
Phases with steps inside
Medallion
TD
LR
Tall rectangle
Groups flowing in sequence
Lineage
LR
TB
Wide rectangle
Simple linear flow
Pipeline
LR
—
Narrow strip
Hierarchy, org chart
Tree
TD
—
Triangle
Complex interconnected
Medallion
TD
LR
Structured layers
Independent Subgraphs (Invisible Links)
When subgraphs have no logical connections between them, Mermaid ignores the outer direction and stacks them vertically by default. Fix with invisible links (~~~):
flowchart LR
subgraph A["Group A"]
direction TB
A1 --> A2
end
subgraph B["Group B"]
direction TB
B1 --> B2
end
A ~~~ B %% Forces horizontal arrangement per outer LR
Rule: Always add ~~~ between independent subgraphs to enforce the outer direction.
Multiple independent groups: Chain invisible links: A ~~~ B ~~~ C ~~~ D
Subgraph Title Truncation (VS Code Only)
Problem: Subgraph titles get truncated in VS Code preview
Note: This is a VS Code Mermaid renderer bug. GitHub renders correctly.
Root Cause: VS Code calculates subgraph width from content nodes, NOT title text.
Workaround: Make content nodes wider so the subgraph expands:
%% BAD in VS Code - narrow nodes clip title
subgraph CONSCIOUS["🌟 Conscious Mind"]
A["Chat"]
B["Commands"]
end
%% GOOD - descriptive labels force wider box
subgraph CONSCIOUS["🌟 Conscious Mind"]
A["💬 Chat Participant"]
B["⚡ VS Code Commands"]
end
Mermaid Parse Errors
Problem: Nested quotes, parentheses, or reserved words cause cryptic parse errors
%% ❌ FAILS - nested quotes
["Return with<br/>"🌐 Results<br/>(Info)"]
%% ✅ WORKS - no nested quotes
["🌐 Return Results<br/>Info"]
Rule 2: Avoid HTML tags inside node labels (some renderers choke on them)
%% ❌ RISKY - <i> tag may break parsing
SYN["synapses.json<br/><i>inert — rarely traversed</i>"]
%% ✅ SAFE - plain text with em dash
SYN["synapses.json — inert, rarely traversed"]
Rule 3: Avoid em dashes (—) in subgraph titles (some parsers treat them as operators)
%% ❌ RISKY - em dash in subgraph title
subgraph P1["Phase 1 — Compiled Graph"]
%% ✅ SAFE - colon or hyphen instead
subgraph P1["Phase 1: Compiled Graph"]
subgraph P1["Phase 1 - Compiled Graph"]
Rule 4: Place style directives for subgraphs outside the subgraph block
%% ❌ FAILS in some renderers - style inside subgraph
subgraph SG["My Group"]
style SG fill:#ddf4ff,stroke:#80ccff
direction TB
A --> B
end
%% ✅ WORKS everywhere - style after all subgraphs
subgraph SG["My Group"]
direction TB
A --> B
end
style SG fill:#ddf4ff,stroke:#80ccff
classDiagram-Specific Pitfalls
Critical: classDiagram has a different parser than flowchart. Syntax that works in flowcharts often breaks in class diagrams. Never assume cross-compatibility.
Reserved Keyword Collisions
classDiagram reserves more keywords than flowcharts. Using them as classDef names or class annotations collides with the parser.
Reserved Word
Why It Breaks
Safe Alternative
abstract
Parsed as <<abstract>> annotation
abstractStyle, base, iface
interface
Parsed as <<interface>> annotation
ifaceStyle, contract
enumeration
Parsed as <<enumeration>> annotation
enumStyle, enumDef
service
Parsed as <<service>> annotation
svcStyle, serviceType
%% ❌ FAILS - "abstract" is a classDiagram keyword
classDef abstract fill:#ddf4ff,stroke:#80ccff
%% ❌ ALSO FAILS - "abstract" parsed as <<abstract>> annotation
class MemorySystem abstract
%% ✅ WORKS - renamed classDef avoids collision
classDef base fill:#ddf4ff,stroke:#80ccff
class MemorySystem base
Comma-Separated Class Lists
class A,B,C styleName syntax works in flowchart but NOT in classDiagram. Each class needs its own class X styleName line.
%% ❌ FAILS in classDiagram - comma syntax not supported
class UserStore,SessionStore,CacheStore storage
%% ✅ WORKS - one line per class
class UserStore storage
class SessionStore storage
class CacheStore storage
Note: In flowchart, class A,B,C styleNameis valid (skillCatalog.ts uses this correctly).
classDef Property Limitations
classDef in classDiagram only supports SVG presentation attributes. CSS text properties are silently ignored.
Works
Silently Ignored
fill, stroke, stroke-width, color
font-weight, font-style, font-size
rx (border radius)
text-decoration, letter-spacing
opacity
padding, margin
%% ❌ SILENTLY IGNORED - font-weight does nothing
classDef important fill:#fff3e0,stroke:#ef6c00,font-weight:bold
%% ✅ WORKS - use only SVG attributes
classDef important fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
stroke-dasharray Space Parsing
The space in stroke-dasharray:6 3 breaks Mermaid's comma-delimited property parser in classDiagram. In flowchart it may work.
%% ❌ FAILS in classDiagram - space in value breaks parser
classDef dashed stroke-dasharray:6 3
%% ⚠️ MAY WORK - single value, no space
classDef dashed stroke-dasharray:5
%% ✅ SAFE in flowchart - space tolerated
classDef dashed stroke-dasharray:5 5
Rule: In classDiagram, avoid stroke-dasharray entirely or use a single integer value. In flowchart, stroke-dasharray:5 5 works.
Decimal stroke-width
Decimal values like stroke-width:2.5px can cause inconsistent rendering across Mermaid renderers.
Critical: architecture-beta is an experimental diagram type with a much stricter tokenizer than mature types. Assume nothing works unless proven.
Spaces in Bracket Labels
Labels in [...] do not support spaces. Multi-word labels cause the parser to treat each word as a separate token.
%% ❌ FAILS - space in bracket label
service api(server)[API Gateway]
%% ✅ WORKS - no spaces (use underscores or camelCase)
service api(server)[APIGateway]
service api(server)[Api_Gateway]
Hyphens in Labels
Hyphens like 4-3-3 are parsed as edge connectors (-- or -), not literal characters. There is no escape mechanism.
%% ❌ FAILS - hyphens parsed as edge syntax
service formation(server)[4-3-3]
%% ✅ WORKS - no hyphens
service formation(server)[Formation433]
Reserved IDs
Common programming keywords may conflict with the parser:
Avoid
Safe Alternative
var
varStore, envVar
in
input, inbound
out
output, outbound
Comments May Not Work
%% comments that work in all other diagram types may cause parse errors in architecture-beta.
%% ❌ MAY FAIL - standard comments
%% This is my architecture
architecture-beta
%% ✅ SAFE - no comments at all
architecture-beta
Icons Only on service, Not group
(icon) syntax only works on service declarations. Using it on group causes a parse error.
%% ❌ FAILS - group does not accept (icon)
group cloud(cloud)[Infrastructure]
%% ✅ WORKS - group has only id and [label]
group cloud[Infrastructure]
%% ✅ WORKS - service accepts (icon)
service api(server)[API]
Rule: service id(icon)[Label] — icon required. group id[Label] — no icon, no parentheses.
Cross-Diagram Syntax Compatibility Matrix
This table summarizes which syntax features work in which diagram types:
Feature
flowchart
classDiagram
architecture-beta
class A,B,C style
✅
❌
N/A
classDef with font-weight
❌ (ignored)
❌ (ignored)
N/A
stroke-dasharray:5 5
✅
❌
N/A
Spaces in [labels]
✅
N/A
❌
Hyphens in labels
✅ (quoted)
✅ (quoted)
❌
%% comments
✅
✅
⚠️
(icon) on groups
N/A
N/A
❌
Reserved Words in Labels and Titles
Problem: Certain words are reserved syntax in specific diagram types. Using them as the first word in a task description or node label causes parse errors like got 'callbackname', got 'keyword', etc.
Gantt Chart Reserved Words (cause callbackname or keyword errors):
Reserved
Why
Safe Alternative
call
Click callback syntax
Invoke, Execute, Generate, Run
click
Click handler syntax
Select, Choose, Trigger
after
Dependency keyword (only at start)
Rephrase to not start with after
done
Task state modifier
Use as tag :done, not in description
active
Task state modifier
Use as tag :active, not in description
crit
Task state modifier
Use as tag :crit, not in description
%% ❌ FAILS - "Call" is reserved
Call Azure OpenAI embeddings API :p1c, after p1b, 2d
%% ✅ WORKS - rephrase to avoid reserved word
Generate Azure OpenAI embeddings :p1c, after p1b, 2d
Flowchart Reserved Words (cause unexpected parse behavior):
Reserved
Why
Safe Alternative
end
Subgraph terminator
Wrap in quotes: ["End"]
subgraph
Block keyword
Wrap in quotes: ["Subgraph"]
class
classDef application
Wrap in quotes: ["Class"]
style
Style directive
Wrap in quotes: ["Style"]
click
Click handler
Wrap in quotes: ["Click"]
default
Default linkStyle target
Wrap in quotes: ["Default"]
%% ❌ FAILS - "end" is reserved
A --> end
%% ✅ WORKS - quoted label
A --> E["End"]
classDiagram Reserved Words (cause parse errors when used as classDef names or class annotations):
Reserved
Why
Safe Alternative
abstract
Parsed as <<abstract>> stereotype
base, abstractStyle, iface
interface
Parsed as <<interface>> stereotype
ifaceStyle, contract
enumeration
Parsed as <<enumeration>> stereotype
enumStyle, enumDef
service
Parsed as <<service>> stereotype
svcStyle, serviceType
%% ❌ FAILS - "abstract" treated as keyword
classDef abstract fill:#ddf4ff,stroke:#80ccff
class MemorySystem abstract
%% ✅ WORKS - safe name
classDef base fill:#ddf4ff,stroke:#80ccff
class MemorySystem base
General Safety Rule: If a parse error occurs on a label or title, wrap it in double quotes ("text") or rephrase to avoid the reserved word. When in doubt, quote it.
XY Chart Bar Coloring (xychart-beta)
Problem: Individual bars all render the same color despite plotColorPalette
Root Cause: xychart-beta only applies different colors to different data series (multiple bar or line commands), not individual bars in a single series.
%% ❌ FAILS - single series, all bars same color
xychart-beta
x-axis [A, B, C]
bar [1, 2, 3] %% All same color!
%% ✅ WORKS - multiple series, each gets color from palette
xychart-beta
x-axis [A, B, C]
bar [1, 2, 3] %% Color 1
bar [4, 5, 6] %% Color 2
Alternative Solutions:
Pie chart — Use pie with theming when showing proportions:
pie showData
title "Task Distribution"
"Task A" : 8
"Task B" : 4
Visual ASCII table — Use markdown table with visual bars:
| Task | Value | Visual |
| ---- | ----- | ------ |
| A | **8** | ████████░░░░ |
| B | **4** | ████░░░░░░░░ |
Stacked bar (grouped) — Split data into multiple series
C4 Diagram Limitations
Problem: C4Component syntax not fully supported in standard Mermaid
Solution: Use flowcharts with subgraphs instead:
flowchart TB
subgraph SYSTEM["🏦 System Name"]
A["📝 Component A"]
B["📊 Component B"]
end
USER(("👤 User"))
USER --> A
USER --> B
Blockquote Tall Boxes
Problem: Blockquotes render with excessive vertical padding