Skip to main content

Diagram Style Guide — ByteByteGo-Inspired

Version: 1.0 Based on: ByteByteGo system design visual language + CLAUDE.md palette Applies to: All CloudForge architecture diagrams (Figma + Mermaid SVG)


[+] Color Palette

Layer Semantics

LayerHexRGB (0-1)Use
Portal / Frontend#3b82f60.231, 0.510, 0.965User-facing UI layers
API Gateway#1e40af0.118, 0.251, 0.686Request routing, auth, rate limiting
Core Engines#7c3aed0.486, 0.227, 0.929Business logic, scoring, dispatch
Risk / Security#dc26260.863, 0.149, 0.149Threat intel, vulnerability, breach
Policy / Governance#f59e0b0.961, 0.620, 0.043OPA, guardrails, compliance
FinOps / Cost#22c55e0.133, 0.773, 0.369Cost aggregation, budgets, alerts
Infrastructure#64748b0.392, 0.455, 0.545Storage, compute, cloud APIs

Accent Colors

PurposeHexUse
Async / Queues#ec4899Dashed arrows, event-driven paths
DR / Failover#ef4444Failover paths, disaster recovery
Success / Pass#22c55eThreshold pass, healthy state
Warning#f59e0bThreshold warn, degraded state
Labels / Metadata#6b7280Subtitle text, secondary info
Background (dark)#0f172aMain frame background
Card fillrgba(255,255,255,0.08)Node card background

[+] Typography

ElementFontSizeWeightColor
Diagram titleSystem (Inter)28px700 (Bold)#ffffff
Layer titleSystem (Inter)16px700 (Bold)Layer color
Layer subtitleSystem (Inter)11px400 (Regular)#99a3b3
Node labelSystem (Inter)13px500 (Medium)#ffffff
Node metadataSystem (Inter)9px400 (Regular)#8c94a5

[!] Canvas Width Rule (README / DOCX Litmus Test)

Design for the display context, not the authoring tool.

GitHub README content column: ~888px. DOCX body at 150 DPI: ~975px.

Canvas WidthDownscale at 888px14px text renders asVerdict
3000px3.4x4.1pxUnreadable
1920px2.2x6.4pxMarginal
1200px1.4x10pxOK with bold
900px1.0x14pxCrisp

Rule: All diagrams targeting README or DOCX embed must use a 900px canvas width (or max 1200px with 20px+ font). This forces vertical stacking over wide side-by-side layouts — which is better for scrolling documents anyway.

For Figma presentation frames (portfolio, slides), use 1920x1080 with proportionally larger text (28px+).


[+] Layout

Composition Patterns

PatternUseExample
Horizontal tiers (LR)System overview, data flowarchitecture.mmd
Vertical tiers (TD)Deep dives, sequence flowsfailover-sequence.mmd
Hub-spokeCentral engine with satellitesrisk-intelligence-pipeline.mmd

Spacing

ElementValue
Main frame padding40-140px
Layer frame width310px
Layer gap25px
Node card size260 x 50px
Node vertical spacing110-160px (varies by count)
Card internal padding15px left, 15px top
Metadata offsety+18px below label
Snap grid20px

Corner Radius

ElementRadius
Main frame16px
Layer subframe12px
Node card8px
Icon badge4px

[+] Icons

Sourcing Priority

  1. Official CSP icons (AWS/Azure/GCP) via icon-library MCP — 64px source, render at 32-36px
  2. Homelab icons (Terraform, Redis, Prometheus) — homelab-svg-assets/
  3. Figma primitives — diamond (queue), hexagon (cache), circle (endpoint)

Placement

PositionSizeUse
Layer header (top-right)36x36pxOne icon per layer representing its domain
Inside node card (left)24x24pxPer-component icon (ByteByteGo standard)
Standalone (diagram)48x48pxHero/focal point icons

Icon Mapping (CloudForge)

ComponentIconProvider
API GatewayArch_Amazon-API-Gateway_64AWS
Auth / ShieldArch_AWS-Shield_64AWS
VulnerabilityArch_Amazon-Inspector_64AWS
Cost/FinOpsArch_AWS-Cost-Explorer_64AWS
Terraformterraform.svgHomelab
PostgreSQLAzure-Database-PostgreSQL-Server_64Azure
RedisCache-Redis_64Azure
WorkflowsArch_AWS-Express-Workflows_64AWS

[+] Connectors / Arrows

Line Styles

StyleStrokePatternUse
Sync API2px #94a3b8SolidREST calls, direct invocations
Async event2px #ec4899Dashed (5px/3px)Webhooks, queues, CDC
Optional path1.5px #6b7280Dotted (2px/4px)Fallback, optional enrichment
Failover2.5px #ef4444Dashed (8px/4px)DR paths, circuit breaker

Arrowheads

  • Standard: Filled triangle, 10px, same color as stroke
  • Bidirectional: Double arrowhead for two-way sync
  • No head: Plain line for association/grouping

Labels on Arrows

  • Font: 10px, centered above line, 6-8px offset
  • Color: #94a3b8 (same as line, or slightly lighter)
  • Content: Protocol or action (e.g., "REST", "gRPC", "webhook", "CDC")

[+] Node Card Anatomy

+------------------------------------------+
| [Icon 24x24] Service Name | <- 13px white, medium
| (implementation detail) | <- 9px #8c94a5, regular
+------------------------------------------+
8px corner radius
rgba(255,255,255,0.08) fill
260 x 50px

Two-Line Label Format

Primary Label           <- Title case, 13px
tech-stack, key-detail <- lowercase, 9px, gray

[+] Dark Theme vs Light Theme

PropertyDark (default)Light (BBG classic)
Background#0f172a#ffffff
Card fillrgba(255,255,255,0.08)#f5f5f5
Text primary#ffffff#1f2937
Text secondary#8c94a5#6b7280
Layer strokeLayer color @ 50% alphaLayer color @ 30% alpha
Arrow color#94a3b8#9ca3af

Default: Dark theme for portfolio, presentations, Figma. Use light theme for: README embeds, printed docs, high-contrast accessibility.


[+] Figma Workflow

Creating a New Diagram

  1. Create main frame — 2600x900 (LR) or 1200x1600 (TD), dark bg #0f172a, radius 16px
  2. Add title — 28px bold white, top-left with 40px margin
  3. Create layer subframes — 310px wide, layer color fill @ 15% alpha, stroke @ 50%, radius 12px
  4. Add layer titles — 16px bold in layer color, subtitle 11px gray
  5. Create node cards — 260x50, rgba(255,255,255,0.08), radius 8px
  6. Add labels — 13px white label + 9px gray metadata inside each card
  7. Place icons — Layer headers (36px) + node cards (24px) via icon-library MCP
  8. Draw arrows — SVG connectors between layers, varied styles per type
  9. Export — PNG @2x for Figma, SVG for README embedding

MCP Tool Sequence

icon-library:search_icons → icon-library:get_icon_svg → figma:create_from_svg
figma:create_frame (main) → create_frame (layers) → create_frame (cards)
figma:create_text (labels) → set_corner_radius → export_node_as_image

[!] Draw.io Icon Embedding

The Semicolon Trap

Draw.io XML uses CSS-like style attributes: style="key=value;key=value" where ; is the property delimiter. Data URIs contain a literal ; in the MIME type (data:image/png;base64,...) which the style parser splits on before the image decoder sees it — silently breaking the icon.

Symptom: Icons render in Draw.io desktop but disappear in CLI export (--export --format png).

Fix: URL-Encode the Semicolon

Replace ; with %3B in the data URI MIME separator:

WRONG:  image=data:image/png;base64,iVBOR...
RIGHT: image=data:image/png%3Bbase64,iVBOR...

WRONG: image=data:image/svg+xml;base64,PHN2...
RIGHT: image=data:image/svg+xml%3Bbase64,PHN2...

This works for all MIME types. Draw.io's image renderer URL-decodes %3B back to ; after style parsing completes.

Icon Embedding Workflow

# 1. Get icon SVG from icon-library MCP or local filesystem
# search_icons("shield", provider="aws") → get_icon_base64(path)

# 2. For PNG embedding (heroicons, rasterized icons):
rsvg-convert -w 128 -h 128 icon.svg -o icon.png
BASE64=$(base64 -i icon.png | tr -d '\n')

# 3. For SVG embedding (CSP icons, vector):
BASE64=$(base64 -i icon.svg | tr -d '\n')

# 4. In Draw.io XML style attribute — NOTE THE %3B:
# PNG: style="shape=image;image=data:image/png%3Bbase64,${BASE64};..."
# SVG: style="shape=image;image=data:image/svg+xml%3Bbase64,${BASE64};..."

Icon Sizing in Draw.io

ContextWidth/HeightNotes
Standalone hero64x64Primary diagram icons
Node card inline48x48Inside labeled containers
Layer header badge36x36Top-right of tier frames
Dense layouts (>15 icons)32x32Minimum readable size

Battle-Tested: 2026-04-04

Confirmed working with 12 heroicons (cloud, check-circle, cpu-chip, bolt, shield-check, server, etc.) across dual-opa-architecture.drawio. Both PNG and SVG URIs survive CLI export with %3B encoding.


[!] Visual Polish Guardrails (Enforced)

These rules are mandatory for all diagram outputs. Sessions that violate them must self-correct before marking a diagram complete.

G1: Icon Placement — Inline Left, Not Clustered Right

Icons MUST be positioned inside their parent node card or tier, left-aligned with the component label text. The ByteByteGo pattern is: [Icon 24px] [8px gap] [Label text].

  • WRONG: Icons clustered in a column on the right edge of the tier frame
  • RIGHT: Each icon sits left of its corresponding component name inside the node card
  • Layer-level header icons (36px, top-right of tier frame) are the only exception

G2: Tier Icon Completeness

Every tier frame MUST contain at least one representative icon. If no specific service icon exists, use a generic shape (hexagon for cache, diamond for queue, circle for endpoint) or a colored rectangle placeholder — but never leave a tier icon-less.

G3: Split-Tier Dividers

When two logical sections share a horizontal row (e.g., "Threat Intelligence" + "Policy Engine" side-by-side), they MUST have:

  • A visible vertical divider (1px #334155 or tier stroke color at 50% alpha)
  • OR a 16px minimum gap with distinct background fills
  • The divider must be visually distinct — not just a color shift

G4: Component Text Spacing

All component names within a tier must use consistent spacing:

  • Minimum 24px horizontal gap between adjacent component names
  • Text nodes must be baseline-aligned within their tier row
  • If components wrap to a second row, maintain the same left margin and gap

G5: No Dead Space

Tier frames must fill the parent frame with consistent padding:

  • Bottom margin below the last tier: same as top margin (frame padding value, typically 40-64px)
  • No tier should have >20% internal empty space (resize the tier frame to fit content)
  • If the frame has >100px of unused space at the bottom, shrink the frame height to match

G6: Vertical-First Layout

Diagrams MUST default to vertical (top-down) flow unless the user explicitly requests horizontal:

  • Tier stacking: Tiers stack vertically (Portal at top → Cloud Providers at bottom)
  • Component detail: When a tier has >4 components, stack them in rows within the tier rather than stretching horizontally
  • Split sections: Side-by-side sections within a tier are acceptable (e.g., Threat Intel + Policy Engine), but the tiers themselves flow top-to-bottom
  • Why: Vertical layouts survive downscaling for README/DOCX (scrolling context). Horizontal layouts require side-scrolling or extreme shrinkage.

This applies to BOTH presentation frames (1920px) and README frames (900px). Horizontal tier-to-tier flow requires explicit opt-in.

G7: Connector Label Legibility

Arrow labels must be:

  • 10px minimum font size (never smaller)
  • Positioned above the line with 6-8px offset (never overlapping the stroke)
  • Contrast ratio: label text must be readable against the background (use #94a3b8 on dark, #6b7280 on light)

G8: README Zoom Verification (MANDATORY)

After any visual edit to a Figma diagram frame (set_svg, set_effects, set_fill_color, move_node, resize_node, set_image_fill, delete_node followed by re-import), you MUST verify readability at the rendered scale before proceeding.

Step 1 — Read the frame width dynamically:

frame_info = get_node_info(nodeId=<frame>)
frame_width = frame_info.absoluteBoundingBox.width

Step 2 — Validate frame is within acceptable embed range:

ConditionAction
frame_width < 888No downscaling needed. Verify at scale=1.0.
888 <= frame_width <= 2400Normal range. Compute scale and verify.
frame_width > 2400WARN: Heavy downscaling will degrade readability. Consider reducing frame width or increasing font sizes proportionally.

Step 3 — Compute scale and export:

README_COLUMN = 888   # GitHub README content width in px
scale = README_COLUMN / frame_width
export_node_as_image(nodeId=<frame>, format="PNG", scale=scale)

Step 4 — Derive minimum source sizes from scale:

min_source_font = ceil(10 / scale)    # 10px rendered = readable threshold
min_source_icon = ceil(24 / scale) # 24px rendered = recognizable threshold

Reference table (derived from formula, not hardcoded):

Frame WidthScaleMin FontMin Icon
1920px0.4622px53px
1440px0.6217px39px
1200px0.7414px33px
900px0.9911px25px

Step 5 — Verification checklist (must ALL pass at scaled export):

  1. All tier labels readable (not blurred/aliased)
  2. All component text legible (individual words distinguishable)
  3. All icons recognizable (shape identifiable, not amorphous blobs)
  4. All arrows visible (direction clear, effects not washed out)
  5. Badge/watermark text at least partially readable

Enforcement: This step is NOT optional. A diagram edit is not complete until the scaled verification export confirms readability. If any item fails, fix the source and re-verify before moving to the next edit.

G9: Icon Style Consistency

All icons within a diagram frame MUST come from the same visual family:

BackgroundIcon SourceFill ColorExample
Dark (#0f172a)Res_48_Dark#FFFFFF (white monochrome)Console, Shield, Metrics, Database
Light (#ffffff)Res_48_Light#232F3D (charcoal monochrome)Same glyphs, dark fill

Rules:

  • NEVER use Arch_* icons in tier frames — they have opaque colored square backgrounds that clash with card fills
  • NEVER mix colored service icons (pink CloudWatch, purple Aurora) with monochrome general icons
  • All 4 tier icons in CF.1 use the Res_General-Icons family: Console (T1), Shield (T6), Metrics (T8), Database (T10)
  • Light variants use identical glyph paths with #232F3D fill instead of #FFFFFF
  • Max 5 icon-library searches per session — use the Res_48_Dark/Light inventory instead of ad-hoc searching

G10: Export Artifact Cleanup

Verification exports from export_node_as_image are ephemeral — they exist only to confirm readability during the edit session.

Rules:

  • One-time verification PNGs MUST NOT be committed to git
  • If export_node_as_image writes to disk (e.g., via save parameter), delete the file immediately after visual confirmation
  • Only final production exports (File > Export > PNG 2x from Figma desktop) belong in docs/core/diagrams/
  • The export_node_as_image tool returns inline image data by default — prefer this over disk writes for verification
  • If a verification PNG is found in the working tree during git status, remove it before committing

[+] Mermaid Alignment

When generating .mmd source files, use these theme variables to approximate the dark theme:

%%{init: {'theme': 'base', 'themeVariables': {
'fontFamily': 'Inter, system-ui, sans-serif',
'fontSize': '14px',
'primaryColor': '#3b82f6',
'primaryTextColor': '#fff',
'primaryBorderColor': '#1e3a8a',
'lineColor': '#64748b',
'secondaryColor': '#f59e0b',
'tertiaryColor': '#22c55e'
}}}%%

The Mermaid SVGs support CSS edge animation (stroke-dasharray + @keyframes dash) — these animate when viewed in browsers but not in GitHub <img> tags.


Document History

VersionDateChanges
1.02026-03-24Initial release — BBG style research + CloudForge implementation
1.12026-04-04Added Draw.io icon embedding section — semicolon trap + %3B fix, icon sizing table, battle-tested workflow
1.22026-04-04Added [!] Visual Polish Guardrails (G1-G7) — icon placement, tier completeness, split-tier dividers, spacing, dead space, vertical-first layout, connector labels
1.32026-04-06Added G8 (README zoom verification — mandatory), G9 (icon style consistency — Res_48_Dark/Light only), G10 (export artifact cleanup)