Skip to content

Commit 28df983

Browse files
committed
docs: swap remaining 7 SVG diagrams for AI-generated rasters
Test of using Nano Banana Pro for technical diagrams went well on MotionStateMachineDiagram (commit ``ec7ba5a``) — every label correct, every arrow in place, premium dark-UI styling. Scaling the same ``diagram_spec`` JSON-prompt pattern to the remaining seven diagrams. Each spec uses the same defenses that worked on the FSM: - ``layout_lock: true``, ``do_not_change_text: true``, ``do_not_misspell_anything: true`` - An ``exact_text`` array listing every visible string the model has to reproduce verbatim (URL paths, code identifiers, brand colour spellings, the ``≥`` symbol where present) - A ``do_not_render_metadata`` instruction added after the McpWorkflow first attempt leaked colour hex codes and ``x_pct`` positioning values into visible labels — the regenerate with that instruction came out clean - A ``rendering_notes`` field that explicitly forbids photographic / 3D / illustrative styling and locks the canvas to a flat dark UI technical-doc aesthetic What shipped: Page Diagram(s) swapped Spec ──── ────────────────── ──── Architecture.jsx SystemArchitectureDiagram system-architecture HlsPipelineDiagram hls-pipeline SecurityModelDiagram security-model Configuration.jsx ConfigPrecedenceDiagram config-precedence Dashboard.jsx DashboardIaDiagram dashboard-ia IncidentLifecycleDiagram incident-lifecycle Mcp.jsx McpWorkflowDiagram mcp-workflow All seven generated successfully on the first or second pass: - ConfigPrecedence — first pass; pyramid of 4 priority bands with vertical "overrides" arrow + footer note all correct - SystemArchitecture — first pass; 3 zones (LOCAL / CLOUD / CLIENT), amber padlock icons on boundary-crossing arrows, all subtitles preserved (UVC / DirectShow / V4L2, ~15 × 1s chunks / camera, etc.) - McpWorkflow — second pass after metadata leakage; 3-lane swimlane with 7 numbered steps in agent + CC lanes, 4 check-marks at the right CloudNode columns (view/watch/attach_snapshot/attach_clip), full READ/VISUAL/WRITE legend - IncidentLifecycle — first pass; main pipeline (Create → Investigate → Finalize → Review → Resolve/Dismiss) with EVIDENCE branch (snapshot, clip) above and NOTES & REVISIONS branch (observation, update_incident) below, all in cyan dashed - HlsPipeline — first pass; 3-lane swimlane, main encode path with parallel motion branch in CloudNode, "~15 segments / rolling window" pill in the right place, HTTPS and GET .ts arrow labels - SecurityModel — first pass; 4 concentric rings (TRANSPORT, AUTH, DATA, TENANT) with the green-filled innermost ring, full detail panel on the right with all 12 sublabels (TLS 1.2+ on every hop, Clerk JWT, nak_*, osc_*, AES-256-GCM creds, every row scoped to org_id, etc.) - DashboardIa — first pass; highest text density of the set (4 children × 4-5 sub-bullets each, plus ADMIN badges on Settings and Admin), every leaf string correct including "opensentry-command.fly.dev" subtitle on the root node and the full "The dashboard splits into four top-level sections..." footer Implementation: - ``frontend/public/images/<name>.{webp,jpg}`` for each — 1920x1080, total 7 diagrams ~635 KB WebP / ~1.6 MB JPEG. ``<picture>`` element with WebP source + JPEG fallback, ``loading="lazy"``, fixed width/height attrs to prevent CLS. - Each swap: ``import`` removed from the page, ``<XxxDiagram />`` replaced with a ``<figure className="docs-diagram"><picture>… </picture><figcaption className="docs-diagram-caption">… </figcaption></figure>`` reusing the existing matte-card frame styling and ``.docs-diagram-image`` class added in commit ``ec7ba5a``. - Specs preserved at ``docs/image-specs/<name>-diagram.json`` for regeneration. The original React components in ``DocsDiagrams.jsx`` are intact and unused — easy revert by flipping the imports + JSX back if any image ages badly. Verification: ``npm run build`` clean (572ms). Visual confirmation on the live site after CI deploys.
1 parent ec7ba5a commit 28df983

25 files changed

Lines changed: 678 additions & 19 deletions
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
{
2+
"diagram_spec": {
3+
"meta": {
4+
"spec_version": "1.0.0",
5+
"title": "Configuration Precedence",
6+
"description": "4 stacked horizontal bands showing config-source priority: SQLite (lowest) → YAML → Environment → CLI flags (highest)."
7+
},
8+
"canvas": {
9+
"width": 1920,
10+
"height": 760,
11+
"unit": "px",
12+
"background_color": "#0a0a0f",
13+
"style_notes": "Flat dark UI. Subtle background grid texture. NOT photographic, NOT 3D, NOT illustrative — a technical product-doc diagram."
14+
},
15+
"semantics": {
16+
"diagram_type": "priority_stack",
17+
"primary_relationship": "override"
18+
},
19+
"bands": [
20+
{
21+
"label": "CLI flags",
22+
"sub_label": "--node-id · --api-key · --api-url",
23+
"fill_color": "#a855f7",
24+
"fill_opacity": 0.85,
25+
"rounded_corners": 6,
26+
"width_pct": 0.30,
27+
"y_position_top": true,
28+
"priority_label": "priority 4"
29+
},
30+
{
31+
"label": "Environment",
32+
"sub_label": "SOURCEBOX_SENTRY_* · RUST_LOG",
33+
"fill_color": "#f59e0b",
34+
"fill_opacity": 0.85,
35+
"rounded_corners": 6,
36+
"width_pct": 0.42,
37+
"priority_label": "priority 3"
38+
},
39+
{
40+
"label": "YAML config",
41+
"sub_label": "config.yaml (legacy, migrated)",
42+
"fill_color": "#3b82f6",
43+
"fill_opacity": 0.85,
44+
"rounded_corners": 6,
45+
"width_pct": 0.54,
46+
"priority_label": "priority 2"
47+
},
48+
{
49+
"label": "SQLite database",
50+
"sub_label": "data/node.db — source of truth",
51+
"fill_color": "#22c55e",
52+
"fill_opacity": 0.85,
53+
"rounded_corners": 6,
54+
"width_pct": 0.66,
55+
"y_position_bottom": true,
56+
"priority_label": "priority 1"
57+
}
58+
],
59+
"layout_notes": "Four bands stacked vertically with consistent vertical spacing. Centered horizontally. Each band wider than the one above it forming a downward-widening pyramid (priority 4 narrowest at top, priority 1 widest at bottom). Each band has bold label on the left in white sans-serif (Inter), code-style sub-label in JetBrains Mono below the label in 70% white. To the right of each band, the 'priority N' text in muted grey sans-serif.",
60+
"annotations": [
61+
{
62+
"type": "vertical_arrow",
63+
"label": "overrides",
64+
"position": "left_of_stack",
65+
"color": "rgba(255,255,255,0.4)",
66+
"direction": "upward",
67+
"label_rotation": -90,
68+
"notes": "thin vertical arrow on the left side of the stack pointing UP, with the word 'overrides' labelled vertically (rotated 90° counter-clockwise) alongside it"
69+
},
70+
{
71+
"type": "footer_note",
72+
"text": "Missing values fall through to the next band. Present values at a higher band win.",
73+
"position": "centered_below_stack",
74+
"color": "rgba(255,255,255,0.55)"
75+
}
76+
],
77+
"constraints": {
78+
"layout_lock": true,
79+
"exact_text": [
80+
"CLI flags", "--node-id · --api-key · --api-url", "priority 4",
81+
"Environment", "SOURCEBOX_SENTRY_* · RUST_LOG", "priority 3",
82+
"YAML config", "config.yaml (legacy, migrated)", "priority 2",
83+
"SQLite database", "data/node.db — source of truth", "priority 1",
84+
"overrides",
85+
"Missing values fall through to the next band. Present values at a higher band win."
86+
],
87+
"do_not_change_text": true,
88+
"do_not_misspell_anything": true,
89+
"rendering_notes": "Flat dark UI technical diagram. Crisp typography. Sub-labels in monospace. NOT photographic. Aspect ratio 16:9. Premium product-doc styling."
90+
}
91+
}
92+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
{
2+
"diagram_spec": {
3+
"meta": {
4+
"spec_version": "1.0.0",
5+
"title": "Dashboard Information Architecture",
6+
"description": "Tree diagram: 'Dashboard' root at top, four child sections below (Live view, Settings, Admin, Incidents), each with 4-5 leaf bullet items. Settings and Admin carry an ADMIN badge."
7+
},
8+
"canvas": {
9+
"width": 1920,
10+
"height": 920,
11+
"unit": "px",
12+
"background_color": "#0a0a0f",
13+
"style_notes": "Flat dark UI. NOT photographic. NOT 3D. Subtle grid background."
14+
},
15+
"root": {
16+
"label": "Dashboard",
17+
"subtitle": "opensentry-command.fly.dev",
18+
"accent": "green",
19+
"icon": "cloud",
20+
"x_pct": 0.50,
21+
"y_pct": 0.06
22+
},
23+
"children": [
24+
{
25+
"label": "Live view",
26+
"accent": "blue",
27+
"x_pct": 0.10,
28+
"y_pct": 0.22,
29+
"items": [
30+
"Camera tiles",
31+
"Fullscreen + multi-view",
32+
"Snapshot capture",
33+
"Manual record"
34+
]
35+
},
36+
{
37+
"label": "Settings",
38+
"accent": "amber",
39+
"admin_only": true,
40+
"x_pct": 0.36,
41+
"y_pct": 0.22,
42+
"items": [
43+
"Node Management",
44+
"Recording Policy",
45+
"Organization",
46+
"Subscription",
47+
"Danger Zone"
48+
]
49+
},
50+
{
51+
"label": "Admin",
52+
"accent": "purple",
53+
"admin_only": true,
54+
"x_pct": 0.62,
55+
"y_pct": 0.22,
56+
"items": [
57+
"Stream Access Logs",
58+
"Usage Statistics",
59+
"MCP Tool Activity",
60+
"System Health"
61+
]
62+
},
63+
{
64+
"label": "Incidents",
65+
"accent": "cyan",
66+
"x_pct": 0.88,
67+
"y_pct": 0.22,
68+
"items": [
69+
"Open incidents",
70+
"Evidence viewer",
71+
"Markdown reports",
72+
"Triage actions"
73+
]
74+
}
75+
],
76+
"tree_lines": "Connect root node down to a horizontal busbar at y_pct ~0.16, then drop a thin vertical line from the busbar to the top of each child node. All lines in muted white (rgba(255,255,255,0.10)).",
77+
"child_node_styling": "Rounded rectangles with title only (no subtitle), accent border per spec. Width about 220px, height about 50px.",
78+
"leaf_styling": "Bullet items hang off a thin vertical line dropping from the LEFT edge of each child node. Each item is a thin horizontal tick line + plain-text label in muted grey, sans-serif, 14px. Items stack vertically with consistent 28px spacing.",
79+
"admin_badge_styling": "Small pill badge labelled 'ADMIN' (caps, letter-spacing) in purple, attached to the top-right corner of nodes flagged admin_only.",
80+
"footer_caption": {
81+
"text": "The dashboard splits into four top-level sections. Admin-only branches are gated on the Pro / Pro Plus plan.",
82+
"color": "rgba(255,255,255,0.55)",
83+
"position": "centered_below_diagram"
84+
},
85+
"constraints": {
86+
"layout_lock": true,
87+
"exact_text": [
88+
"Dashboard", "opensentry-command.fly.dev",
89+
"Live view", "Camera tiles", "Fullscreen + multi-view", "Snapshot capture", "Manual record",
90+
"Settings", "Node Management", "Recording Policy", "Organization", "Subscription", "Danger Zone",
91+
"Admin", "Stream Access Logs", "Usage Statistics", "MCP Tool Activity", "System Health",
92+
"Incidents", "Open incidents", "Evidence viewer", "Markdown reports", "Triage actions",
93+
"ADMIN",
94+
"The dashboard splits into four top-level sections. Admin-only branches are gated on the Pro / Pro Plus plan."
95+
],
96+
"do_not_change_text": true,
97+
"do_not_misspell_anything": true,
98+
"do_not_render_metadata": "do NOT render any color hex codes, rgba() values, x_pct/y_pct positioning values, or any JSON metadata as visible text. Visible text must come ONLY from the exact_text array.",
99+
"rendering_notes": "Premium technical-doc tree diagram. Crisp typography. Settings and Admin nodes get a small purple ADMIN pill in their top-right corner. Leaf items in muted grey hang off a thin connecting line from each child. Footer caption below the tree. NOT photographic. Aspect ratio 16:9."
100+
}
101+
}
102+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
{
2+
"diagram_spec": {
3+
"meta": {
4+
"spec_version": "1.0.0",
5+
"title": "HLS Segment Pipeline",
6+
"description": "How a frame becomes playable video. Three horizontal swimlanes (CLOUDNODE, CLOUD, CLIENT). Main path: Camera → FFmpeg → HLS segments → Segment uploader → (HTTPS) → Segment RAM cache → Same-origin proxy → hls.js player. Side branch parallel motion probe in CloudNode lane: Motion probe → scene-change score → WebSocket event."
7+
},
8+
"canvas": {
9+
"width": 1920,
10+
"height": 920,
11+
"unit": "px",
12+
"background_color": "#0a0a0f",
13+
"style_notes": "Flat dark UI. NOT photographic. Three horizontal swimlanes with dashed coloured borders."
14+
},
15+
"lanes": [
16+
{"label": "CLOUDNODE", "color": "#3b82f6", "fill": "rgba(59,130,246,0.03)", "y_pct": 0.10, "height_pct": 0.40},
17+
{"label": "CLOUD", "color": "#22c55e", "fill": "rgba(34,197,94,0.04)", "y_pct": 0.55, "height_pct": 0.18},
18+
{"label": "CLIENT", "color": "#a855f7", "fill": "rgba(168,85,247,0.03)", "y_pct": 0.78, "height_pct": 0.12}
19+
],
20+
"cloudnode_lane_main_row": [
21+
{"label": "Camera", "subtitle": "raw frames", "accent": "blue", "x_pct": 0.05},
22+
{"label": "FFmpeg", "subtitle": "libx264 / NVENC", "accent": "blue", "x_pct": 0.21},
23+
{"label": "HLS segments", "subtitle": ".ts · 1s each", "accent": "blue", "x_pct": 0.37},
24+
{"label": "Segment uploader", "subtitle": "POST /push-segment", "accent": "blue", "x_pct": 0.55}
25+
],
26+
"cloudnode_lane_motion_branch_row": [
27+
{"label": "Motion probe", "accent": "amber", "x_pct": 0.21},
28+
{"label": "scene-change score", "accent": "amber", "x_pct": 0.37},
29+
{"label": "WebSocket event", "accent": "amber", "x_pct": 0.55}
30+
],
31+
"cloud_lane": [
32+
{"label": "Segment RAM cache", "accent": "green", "x_pct": 0.32},
33+
{"label": "Same-origin proxy", "accent": "green", "x_pct": 0.52}
34+
],
35+
"client_lane": [
36+
{"label": "hls.js player", "accent": "purple", "x_pct": 0.52}
37+
],
38+
"edges": [
39+
{"from": "Camera", "to": "FFmpeg", "label": "", "lane": "cloudnode_main"},
40+
{"from": "FFmpeg", "to": "HLS segments", "label": "", "lane": "cloudnode_main"},
41+
{"from": "HLS segments", "to": "Segment uploader", "label": "", "lane": "cloudnode_main"},
42+
{"from": "FFmpeg", "to": "Motion probe", "label": "", "lane": "cloudnode_main_to_branch", "style": "dashed_amber"},
43+
{"from": "Motion probe", "to": "scene-change score", "label": "", "style": "solid_amber"},
44+
{"from": "scene-change score", "to": "WebSocket event", "label": "", "style": "solid_amber"},
45+
{"from": "Segment uploader", "to": "Segment RAM cache", "label": "HTTPS", "style": "solid_green_arrow_crossing_lanes"},
46+
{"from": "WebSocket event", "to": "Same-origin proxy", "label": "", "style": "dashed_green"},
47+
{"from": "Segment RAM cache", "to": "Same-origin proxy", "label": "", "style": "solid_green"},
48+
{"from": "Same-origin proxy", "to": "hls.js player", "label": "GET .ts", "style": "solid_grey_crossing_lanes"}
49+
],
50+
"annotation_pill": {
51+
"position": "right_side_of_cloud_lane",
52+
"text_top": "~15 segments",
53+
"text_bottom": "rolling window",
54+
"fill": "rgba(34,197,94,0.1)",
55+
"border_color": "#22c55e"
56+
},
57+
"constraints": {
58+
"layout_lock": true,
59+
"exact_text": [
60+
"CLOUDNODE", "CLOUD", "CLIENT",
61+
"Camera", "raw frames",
62+
"FFmpeg", "libx264 / NVENC",
63+
"HLS segments", ".ts · 1s each",
64+
"Segment uploader", "POST /push-segment",
65+
"Motion probe", "scene-change score", "WebSocket event",
66+
"Segment RAM cache", "Same-origin proxy",
67+
"hls.js player",
68+
"HTTPS", "GET .ts",
69+
"~15 segments", "rolling window"
70+
],
71+
"do_not_change_text": true,
72+
"do_not_misspell_anything": true,
73+
"do_not_render_metadata": "do NOT render any color hex codes, rgba() values, x_pct/y_pct positioning values, or any JSON metadata as visible text. Visible text must come ONLY from the exact_text array.",
74+
"rendering_notes": "Premium technical-doc style. Crisp typography. Three horizontal swimlanes with dashed coloured borders, lane labels in spaced caps on the left edge. Main encode path on top row of CloudNode lane (blue). Parallel motion branch on second row of CloudNode lane (amber). Cloud lane has 2 nodes. Client lane has 1 node. NOT photographic. Aspect ratio 16:9."
75+
}
76+
}
77+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"diagram_spec": {
3+
"meta": {
4+
"spec_version": "1.0.0",
5+
"title": "Incident Lifecycle",
6+
"description": "Left-to-right pipeline: Create → Investigate → Finalize → Review → branch into Resolve or Dismiss. Investigate has parallel Evidence (snapshot, clip) and Notes & Revisions (observation, update_incident) branches above and below."
7+
},
8+
"canvas": {
9+
"width": 1920,
10+
"height": 840,
11+
"unit": "px",
12+
"background_color": "#0a0a0f",
13+
"style_notes": "Flat dark UI. NOT photographic. NOT 3D. NOT illustrative. Subtle grid background."
14+
},
15+
"main_pipeline": [
16+
{"label": "Create", "subtitle": "title · severity · camera", "accent": "amber", "x_pct": 0.05},
17+
{"label": "Investigate", "subtitle": "attach evidence + notes", "accent": "amber", "x_pct": 0.22, "wide": true},
18+
{"label": "Finalize", "subtitle": "markdown report body", "accent": "blue", "x_pct": 0.43},
19+
{"label": "Review", "subtitle": "human triage", "accent": "purple", "x_pct": 0.60},
20+
{"label": "Resolve", "subtitle": "", "accent": "green", "x_pct": 0.80, "y_offset": -0.08, "small": true},
21+
{"label": "Dismiss", "subtitle": "", "accent": "default","x_pct": 0.80, "y_offset": 0.08, "small": true}
22+
],
23+
"main_arrows": [
24+
{"from": "Create", "to": "Investigate", "label": "open"},
25+
{"from": "Investigate", "to": "Finalize", "label": "write report"},
26+
{"from": "Finalize", "to": "Review", "label": "publish"},
27+
{"from": "Review", "to": "Resolve", "color": "green"},
28+
{"from": "Review", "to": "Dismiss", "color": "grey"}
29+
],
30+
"evidence_branch": {
31+
"lane_label": "EVIDENCE",
32+
"lane_color": "#06b6d4",
33+
"position": "above_investigate_node",
34+
"nodes": [
35+
{"label": "snapshot", "x_offset_from_investigate": -0.025},
36+
{"label": "clip", "x_offset_from_investigate": 0.025}
37+
],
38+
"connections_style": "dashed_cyan_curved_lines_from_investigate_node_up_to_each_evidence_node",
39+
"node_styling": "small_pill_shaped_rounded_rectangle_with_cyan_border_and_label"
40+
},
41+
"notes_branch": {
42+
"lane_label": "NOTES & REVISIONS",
43+
"lane_color": "#06b6d4",
44+
"position": "below_investigate_node",
45+
"nodes": [
46+
{"label": "observation", "x_offset_from_investigate": -0.025},
47+
{"label": "update_incident", "x_offset_from_investigate": 0.025}
48+
],
49+
"connections_style": "dashed_cyan_curved_lines_from_investigate_node_down_to_each_notes_node",
50+
"node_styling": "small_pill_shaped_rounded_rectangle_with_cyan_border_and_label"
51+
},
52+
"constraints": {
53+
"layout_lock": true,
54+
"exact_text": [
55+
"Create", "title · severity · camera",
56+
"Investigate", "attach evidence + notes",
57+
"Finalize", "markdown report body",
58+
"Review", "human triage",
59+
"Resolve", "Dismiss",
60+
"open", "write report", "publish",
61+
"snapshot", "clip", "observation", "update_incident",
62+
"EVIDENCE", "NOTES & REVISIONS"
63+
],
64+
"do_not_change_text": true,
65+
"do_not_misspell_anything": true,
66+
"do_not_render_metadata": "do NOT render any color hex codes, rgba() values, x_pct/y_pct positioning values, or any other JSON metadata as visible text. Visible text must come ONLY from the exact_text array.",
67+
"rendering_notes": "Premium technical-doc style. Crisp typography. Main pipeline nodes are rounded rectangles with title + subtitle and accent border per spec. Evidence and Notes nodes are smaller cyan pill-shapes. Dashed cyan curved lines connect Investigate up to Evidence and down to Notes. Resolve has a green accent (positive); Dismiss is neutral. NOT photographic. Aspect ratio 16:9."
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)