Skip to content

Commit 7eaf92c

Browse files
Sbussisoclaude
andcommitted
docs: two new AI-generated diagrams — setup wizard + notifications fan-out
- CloudNode Setup section now leads with a 5-step wizard flow (Prerequisites → Configuration → Install → Verify → Launch), with annotated branches for the FFmpeg package-manager fallback (winget / brew / apt-dnf-pacman) and encoder auto-detect (NVENC / QSV / AMF / libx264 fallback). - Notifications section now leads with a fan-out diagram showing EVENT → AUDIENCE FILTER → 4 channels (in-app inbox, email, incidents tab, MCP activity log), with the email gate (per-org opt-in, bounce suppression, motion cooldown) inlined on the email channel, plus the motion-digest 1+1 capping rule. Both shipped as 2752×1536 WebP (primary) + JPEG (fallback) via <picture>, lazy-loaded, with descriptive alt text. Specs live in docs/image-specs/ alongside the existing diagram specs so future regenerations stay deterministic. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0a8f558 commit 7eaf92c

8 files changed

Lines changed: 242 additions & 0 deletions

File tree

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
{
2+
"diagram_spec": {
3+
"meta": {
4+
"spec_version": "1.0.0",
5+
"title": "Notifications Fan-out — one event, four channels",
6+
"description": "A platform event enters from the left, passes through the audience filter (admin-only vs all members) and the email opt-in gate, then fans out to four delivery channels on the right: in-app SSE inbox, email via Resend, Incidents tab, and the MCP activity log. The diagram shows where each gate sits and which channels are gated by what."
7+
},
8+
"canvas": {
9+
"width": 1920,
10+
"height": 1000,
11+
"unit": "px",
12+
"background_color": "#0a0a0f",
13+
"style_notes": "Flat dark UI. NOT photographic. NOT 3D. NOT illustrative. Subtle grid background. Premium technical-doc aesthetic — crisp typography, generous whitespace, soft glow on accents."
14+
},
15+
"regions": {
16+
"event_source": {
17+
"x_pct": 0.06,
18+
"y_pct": 0.50,
19+
"label": "EVENT",
20+
"subtitle": "platform-detected change",
21+
"examples_panel": {
22+
"title": "examples",
23+
"items": [
24+
"node offline / recovered",
25+
"camera offline / recovered",
26+
"motion detected",
27+
"incident opened",
28+
"MCP key created / revoked",
29+
"member added / role changed",
30+
"CloudNode disk almost full"
31+
],
32+
"styling": "small panel attached below the EVENT node, JetBrains Mono items, muted grey, no bullets — just a stacked list"
33+
},
34+
"node_styling": "tall rounded rectangle, amber accent border, label in spaced caps, subtitle in muted grey Inter"
35+
},
36+
"audience_gate": {
37+
"x_pct": 0.30,
38+
"y_pct": 0.50,
39+
"label": "AUDIENCE FILTER",
40+
"subtitle": "admin-only vs all members",
41+
"node_styling": "diamond / hexagonal shape with subtle purple accent border to read as 'decision point', label centered"
42+
},
43+
"email_gate": {
44+
"x_pct": 0.52,
45+
"y_pct": 0.18,
46+
"label": "EMAIL GATE",
47+
"subtitle": "per-org opt-in · bounce suppression · motion cooldown 15 min",
48+
"node_styling": "rectangular gate with green accent border, sits ON the line going to the email channel"
49+
}
50+
},
51+
"channels": [
52+
{
53+
"label": "IN-APP INBOX",
54+
"subtitle": "bell icon · SSE · real-time",
55+
"accent": "cyan",
56+
"x_pct": 0.85,
57+
"y_pct": 0.10
58+
},
59+
{
60+
"label": "EMAIL",
61+
"subtitle": "Resend · opt-in · cooldown",
62+
"accent": "green",
63+
"x_pct": 0.85,
64+
"y_pct": 0.36
65+
},
66+
{
67+
"label": "INCIDENTS TAB",
68+
"subtitle": "if filed as incident",
69+
"accent": "amber",
70+
"x_pct": 0.85,
71+
"y_pct": 0.62
72+
},
73+
{
74+
"label": "MCP ACTIVITY LOG",
75+
"subtitle": "admin dashboard · audit",
76+
"accent": "purple",
77+
"x_pct": 0.85,
78+
"y_pct": 0.88
79+
}
80+
],
81+
"arrows": [
82+
{"from": "event_source", "to": "audience_gate", "style": "solid_white_with_arrowhead"},
83+
{"from": "audience_gate", "to": "channel_in_app", "style": "solid_cyan_curve_up"},
84+
{"from": "audience_gate", "to": "email_gate", "style": "solid_white_with_arrowhead"},
85+
{"from": "email_gate", "to": "channel_email", "style": "solid_green_curve"},
86+
{"from": "audience_gate", "to": "channel_incidents", "style": "solid_amber_curve_down"},
87+
{"from": "audience_gate", "to": "channel_mcp_log", "style": "solid_purple_curve_down"}
88+
],
89+
"annotations": [
90+
{
91+
"near": "channel_email",
92+
"label": "MOTION DIGEST",
93+
"subtitle": "1 immediate + 1 summary, capped at 2 / cycle / camera",
94+
"position": "small_pill_below_email_channel",
95+
"color": "#06b6d4"
96+
},
97+
{
98+
"near": "channel_mcp_log",
99+
"label": "ADMIN ONLY",
100+
"position": "small_pill_above_mcp_log_channel",
101+
"color": "#a855f7"
102+
}
103+
],
104+
"constraints": {
105+
"layout_lock": true,
106+
"exact_text": [
107+
"EVENT", "platform-detected change",
108+
"examples",
109+
"node offline / recovered",
110+
"camera offline / recovered",
111+
"motion detected",
112+
"incident opened",
113+
"MCP key created / revoked",
114+
"member added / role changed",
115+
"CloudNode disk almost full",
116+
"AUDIENCE FILTER", "admin-only vs all members",
117+
"EMAIL GATE", "per-org opt-in · bounce suppression · motion cooldown 15 min",
118+
"IN-APP INBOX", "bell icon · SSE · real-time",
119+
"EMAIL", "Resend · opt-in · cooldown",
120+
"INCIDENTS TAB", "if filed as incident",
121+
"MCP ACTIVITY LOG", "admin dashboard · audit",
122+
"MOTION DIGEST", "1 immediate + 1 summary, capped at 2 / cycle / camera",
123+
"ADMIN ONLY"
124+
],
125+
"do_not_change_text": true,
126+
"do_not_misspell_anything": true,
127+
"do_not_render_metadata": "Do NOT render any color hex codes, rgba() values, x_pct/y_pct positioning values, JSON field names, or any other JSON metadata as visible text on the canvas. Visible text must come ONLY from the exact_text array.",
128+
"do_not_show_logos": "Do NOT render any company logos (no real Resend logo, no Gmail icon, no Slack mark). Text labels alone.",
129+
"rendering_notes": "Premium technical-doc style matching the existing dashboard-ia and mcp-workflow diagrams. The fan-out reads left-to-right: EVENT → AUDIENCE FILTER → 4 channels stacked on the right. The EMAIL GATE is an inline gate that sits ON the line going to the EMAIL channel, NOT a separate node. Channel boxes are rounded rectangles, accent border per channel. The 'examples' panel under EVENT lists the seven event types as a clean stacked list with NO bullet symbols. Gate shapes are visually distinct from channel shapes — diamonds/hexagons read as decisions, rectangles read as destinations. Aspect ratio 16:8.3. NOT photographic."
130+
}
131+
}
132+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"diagram_spec": {
3+
"meta": {
4+
"spec_version": "1.0.0",
5+
"title": "CloudNode Setup Wizard — 5-step flow",
6+
"description": "Left-to-right pipeline showing the 5 wizard steps a user walks through after running install.sh / the MSI. Two annotation branches: FFmpeg fallback path above step 1 (winget / brew / apt), encoder auto-detect options below step 3 (NVENC / QSV / AMF / libx264)."
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. Premium technical-doc aesthetic — crisp typography, generous whitespace, soft glow on accents."
14+
},
15+
"main_pipeline": [
16+
{"step": 1, "label": "Prerequisites", "subtitle": "platform · cameras · FFmpeg", "accent": "cyan", "x_pct": 0.08},
17+
{"step": 2, "label": "Configuration", "subtitle": "node_id · API key", "accent": "cyan", "x_pct": 0.27},
18+
{"step": 3, "label": "Install", "subtitle": "encrypted config · encoder", "accent": "cyan", "x_pct": 0.46},
19+
{"step": 4, "label": "Verify", "subtitle": "round-trip Command Center", "accent": "purple", "x_pct": 0.65},
20+
{"step": 5, "label": "Launch", "subtitle": "node online", "accent": "green", "x_pct": 0.84}
21+
],
22+
"main_arrows": [
23+
{"from": 1, "to": 2},
24+
{"from": 2, "to": 3},
25+
{"from": 3, "to": 4},
26+
{"from": 4, "to": 5}
27+
],
28+
"node_styling": "Each main step is a rounded rectangle with a circled white step-number badge top-left, a bold title, and a muted-grey monospace subtitle. Accent border colour per step (cyan for steps 1-3, purple for verify, green for launch). Soft glow matching the accent.",
29+
"ffmpeg_branch": {
30+
"lane_label": "IF FFMPEG MISSING",
31+
"lane_color": "#f59e0b",
32+
"position": "above_step_1",
33+
"explanatory_text": "wizard offers to install via OS package manager",
34+
"nodes": [
35+
{"label": "winget", "subtitle": "Windows", "x_offset_from_step_1": -0.04},
36+
{"label": "brew", "subtitle": "macOS", "x_offset_from_step_1": 0.00},
37+
{"label": "apt / dnf / pacman", "subtitle": "Linux", "x_offset_from_step_1": 0.05}
38+
],
39+
"connections_style": "thin dashed amber curved line from step 1 up to a small junction, then three short branches to each pill",
40+
"node_styling": "small pill-shaped rounded rectangles, amber border, JetBrains Mono label + Inter subtitle below"
41+
},
42+
"encoder_branch": {
43+
"lane_label": "ENCODER AUTO-DETECT",
44+
"lane_color": "#3b82f6",
45+
"position": "below_step_3",
46+
"explanatory_text": "wizard picks the best available, falls back left-to-right",
47+
"nodes": [
48+
{"label": "NVENC", "subtitle": "NVIDIA", "x_offset_from_step_3": -0.06},
49+
{"label": "QSV", "subtitle": "Intel", "x_offset_from_step_3": -0.02},
50+
{"label": "AMF", "subtitle": "AMD", "x_offset_from_step_3": 0.02},
51+
{"label": "libx264", "subtitle": "fallback","x_offset_from_step_3": 0.06}
52+
],
53+
"connections_style": "thin dashed blue curved line from step 3 down to a junction, then four short branches to each encoder pill. The first three pills (NVENC / QSV / AMF) share the same subtle blue accent; libx264 has a slightly muted grey accent to read as the always-available fallback.",
54+
"node_styling": "small pill-shaped rounded rectangles, blue border, JetBrains Mono label + Inter subtitle below"
55+
},
56+
"constraints": {
57+
"layout_lock": true,
58+
"exact_text": [
59+
"Prerequisites", "platform · cameras · FFmpeg",
60+
"Configuration", "node_id · API key",
61+
"Install", "encrypted config · encoder",
62+
"Verify", "round-trip Command Center",
63+
"Launch", "node online",
64+
"IF FFMPEG MISSING", "wizard offers to install via OS package manager",
65+
"winget", "Windows", "brew", "macOS", "apt / dnf / pacman", "Linux",
66+
"ENCODER AUTO-DETECT", "wizard picks the best available, falls back left-to-right",
67+
"NVENC", "NVIDIA", "QSV", "Intel", "AMF", "AMD", "libx264", "fallback"
68+
],
69+
"do_not_change_text": true,
70+
"do_not_misspell_anything": true,
71+
"do_not_render_metadata": "Do NOT render any color hex codes, rgba() values, x_pct/x_offset positioning values, JSON field names, or any other JSON metadata as visible text on the canvas. Visible text must come ONLY from the exact_text array.",
72+
"do_not_show_logos": "Do NOT render any company logos (no real Intel/NVIDIA/AMD/Apple/Microsoft/Linux logos). The text labels alone identify each platform.",
73+
"rendering_notes": "Premium technical-doc style matching incident-lifecycle and motion-fsm diagrams. Step 1-3 cyan, step 4 purple, step 5 green. Numbered step badges read '1' through '5'. The two branches (ffmpeg above, encoder below) are visually subordinate — smaller pills, dashed connectors, lane labels in spaced caps. Aspect ratio 16:7. NOT photographic."
74+
}
75+
}
76+
}
273 KB
Loading
114 KB
Loading
404 KB
Loading
149 KB
Loading

frontend/src/pages/docs/CloudNodeSetup.jsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,23 @@ function CloudNodeSetup() {
1313
backend, which serves them to viewers from an in-memory cache.
1414
</p>
1515

16+
<figure className="docs-diagram">
17+
<picture>
18+
<source srcSet="/images/setup-wizard.webp" type="image/webp" />
19+
<img
20+
src="/images/setup-wizard.jpg"
21+
alt="CloudNode setup wizard 5-step flow: Prerequisites, Configuration, Install, Verify, Launch — left to right. Annotation branches: 'IF FFMPEG MISSING' (winget on Windows, brew on macOS, apt/dnf/pacman on Linux) above step 1; 'ENCODER AUTO-DETECT' (NVENC/NVIDIA, QSV/Intel, AMF/AMD, libx264 fallback) below step 3."
22+
className="docs-diagram-image"
23+
width="2752"
24+
height="1536"
25+
loading="lazy"
26+
/>
27+
</picture>
28+
<figcaption className="docs-diagram-caption">
29+
The wizard runs once per machine. Steps 1–3 set you up, step 4 round-trips a credential check against Command Center, and step 5 hands the node off to live operation. The two annotated branches show where the wizard makes choices for you — installing FFmpeg via the OS package manager and picking the best available hardware encoder.
30+
</figcaption>
31+
</figure>
32+
1633
<h3>Installation</h3>
1734
<OsTabs id="cn" />
1835
<p style={{ marginTop: '0.75rem', fontSize: '0.9rem', color: 'var(--text-muted)' }}>

frontend/src/pages/docs/Notifications.jsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,23 @@ function Notifications() {
99
the MCP tool activity log.
1010
</p>
1111

12+
<figure className="docs-diagram">
13+
<picture>
14+
<source srcSet="/images/notifications-fanout.webp" type="image/webp" />
15+
<img
16+
src="/images/notifications-fanout.jpg"
17+
alt="Notifications fan-out: a single platform event passes through the audience filter (admin-only vs all members), then fans out to four channels — In-app inbox (SSE, real-time), Email (Resend, with per-org opt-in, bounce suppression, and 15-minute motion cooldown), Incidents tab (when filed as incident), and MCP activity log (admin only). Motion digest behavior is surfaced near the email channel: 1 immediate + 1 summary, capped at 2 per cycle per camera."
18+
className="docs-diagram-image"
19+
width="2752"
20+
height="1536"
21+
loading="lazy"
22+
/>
23+
</picture>
24+
<figcaption className="docs-diagram-caption">
25+
One event, four destinations. The audience filter decides whether the event goes to admins only or to every member. The email gate adds per-org opt-in, bounce suppression, and motion-event cooldown — so the in-app inbox can be loud while email volume stays bounded.
26+
</figcaption>
27+
</figure>
28+
1229
<h3>What triggers a notification</h3>
1330
<ul>
1431
<li><strong>Node offline</strong> — Command Center hasn't received a heartbeat from a node for 90 seconds.</li>

0 commit comments

Comments
 (0)