| name | demo |
| description | Use when the concept needs ANIMATION or INTERACTIVITY to be understood — step-by-step protocol flows, sorting algorithm traces, state machine transitions, network packet journeys, or anything where static images fall short. Generates a self-contained .html file with Canvas/SVG + JavaScript. Opens in any browser, zero dependencies. For static diagrams use /ascii (simple) or /excalidraw (complex). |
Demo — Interactive Animated Diagrams
Generate .html files with animated, interactive visualizations. Uses a template with built-in engine, drawing library, and Preact UI — you only write the steps and draw functions.
Invocation
/demo <concept description>
When to Use This
/demo | /excalidraw | /ascii |
|---|
| Needs animation (packets moving, sort steps) | Complex but static (architecture, data structures) | Quick inline terminal visual |
| Step-by-step walkthrough with play/pause | Student wants to edit/rearrange the diagram | Simple sequence or flowchart |
| Timing matters (race conditions, event loops) | Diagram will be exported as image | Just needs a quick look |
Template Architecture
The template at skills/demo/template.html ships with:
| Layer | Technology | What it provides |
|---|
| UI | Preact + HTM (CDN) | Reactive controls, step navigation, keyboard shortcuts |
| Styling | Bootstrap 5 + Icons (CDN) + custom dark theme | Pretty buttons, icons, responsive layout, utilities |
| Canvas | Native Canvas 2D + drawing library | Drawing helpers, animation math, color theming |
| Engine | Built into template | Animation loop, step progression, speed control |
You only fill in the content section between __CONTENT_START__ and __CONTENT_END__.
Process
- Research the concept using WebSearch — verify accuracy
- Read the template at
skills/demo/template.html
- Copy the template to
docs/<concept-name>.html
- Replace placeholders:
__TITLE__ → concept name (appears in 3 places: <title>, <h1>, and Preact html)
__SUBTITLE__ → one-line description (appears in 2 places)
__SOURCE_HTML__ → source link, e.g. Source: <a href="https://...">RFC 793</a>
__CUSTOM_CSS__ → any concept-specific CSS (usually empty — use Bootstrap utilities first)
- Replace the content section (
__CONTENT_START__ to __CONTENT_END__) with your STEPS array and optional drawBackground/drawOverlay functions
- Save and tell the student how to open it
What You Write: The STEPS Array
const STEPS = [
{
title: "Short step name",
explain: "What's happening.",
draw(ctx, progress, W, H, stepIndex) {
drawArrow(ctx, x1, y1, x2, y2, opts);
drawMovingPacket(ctx, x1, y1, x2, y2, progress, 'SYN');
},
drawResult(ctx, W, H, stepIndex) {
drawArrow(ctx, x1, y1, x2, y2, opts);
}
},
];
IMPORTANT — draw vs drawResult:
draw() renders the full animation including transient elements (moving packets, popups, detail panels)
drawResult() renders ONLY what should stay visible after the step is done
- Without
drawResult, ALL elements from draw() persist — this causes overlap bugs in protocol flows where moving packets and header boxes pile up
- Always define
drawResult for steps that have transient animated elements
Optional: drawBackground(ctx, W, H)
Static elements drawn every frame behind everything. Attach to window:
window.drawBackground = function(ctx, W, H) {
};
Optional: drawOverlay(ctx, W, H, currentStep, progress)
Drawn on top every frame. Attach to window:
window.drawOverlay = function(ctx, W, H, step, progress) {
};
Drawing Library Reference
All functions are globally available. Every shape function takes ctx as first argument.
Shapes
drawBox(ctx, x, y, w, h, { fill, stroke, lineWidth, radius, opacity })
drawCircle(ctx, x, y, r, { fill, stroke, lineWidth, opacity })
drawDiamond(ctx, cx, cy, w, h, { fill, stroke, lineWidth, opacity })
Text
drawText(ctx, text, x, y, { size, weight, fillColor, align, baseline, maxWidth, opacity })
drawPill(ctx, text, x, y, { fill, textColor, size, px, py })
Lines & Arrows
drawArrow(ctx, x1, y1, x2, y2, { strokeColor, lineWidth, headSize, dash, opacity })
drawDashedLine(ctx, x1, y1, x2, y2, { strokeColor, lineWidth, dash, opacity })
drawLine(ctx, x1, y1, x2, y2, { strokeColor, lineWidth, opacity })
drawCurvedArrow(ctx, x1, y1, cpx, cpy, x2, y2, { strokeColor, lineWidth, headSize, opacity })
Animation
drawMovingPacket(ctx, x1, y1, x2, y2, progress, label, { fill, textColor, size, width, height })
withGlow(ctx, drawFn, glowColor, blur)
pulse(time, speed)
Math
lerp(a, b, t)
easeInOut(t)
easeOut(t)
easeIn(t)
clamp(val, min, max)
subProgress(progress, start, end)
Colors (CSS variables)
color('--node-a')
color('--node-b')
color('--node-c')
color('--data')
color('--accent')
color('--success')
color('--warning')
color('--error')
color('--info')
color('--text')
color('--text-muted')
color('--surface')
color('--primary')
Sequencing Animations Within a Step
Use subProgress() to split one step's 0→1 progress into phases:
draw(ctx, progress, W, H) {
const arrowP = subProgress(progress, 0, 0.4);
if (arrowP > 0) {
drawArrow(ctx, x1, y1, x1 + (x2 - x1) * easeOut(arrowP), y1, ...);
}
const packetP = subProgress(progress, 0.3, 0.9);
if (packetP > 0) {
drawMovingPacket(ctx, x1, y1, x2, y2, packetP, 'SYN', ...);
}
const labelP = subProgress(progress, 0.8, 1);
if (labelP > 0) {
drawPill(ctx, 'SYN_SENT', x1, y3, { ...opts, opacity: labelP });
}
}
Available CDN Libraries
The template loads these from CDN — you can use them for custom UI if needed:
- Bootstrap 5 CSS — full utility classes (
d-flex, gap-2, rounded, text-muted, etc.)
- Bootstrap Icons —
<i class="bi bi-*"></i> icon font
- Preact + HTM — reactive components (the engine uses these, you can too for custom overlays)
For extra HTML sections (tables, accordions, tabbed views alongside the canvas), you can add Bootstrap-styled elements in the __CUSTOM_CSS__ area or extend the Preact App component.
Layout Guidelines
- Use relative positions:
W * 0.25 not 200. Responsive by default.
- Actor positions: 2 actors →
W * 0.25, W * 0.75. 3 actors → W * 0.2, W * 0.5, W * 0.8.
- Vertical flow: Start at
H * 0.1, gaps of H * 0.08 between rows.
- Font scaling:
Math.max(12, W * 0.015) for labels.
- 5-15 steps is the sweet spot.
Style Recipes
Protocol Flow
window.drawBackground = function(ctx, W, H) {
drawBox(ctx, W*0.15, H*0.05, W*0.2, H*0.08, { fill: color('--node-a'), radius: 6 });
drawText(ctx, 'Client', W*0.25, H*0.09, { size: 16, weight: '600' });
drawBox(ctx, W*0.65, H*0.05, W*0.2, H*0.08, { fill: color('--node-b'), radius: 6 });
drawText(ctx, 'Server', W*0.75, H*0.09, { size: 16, weight: '600' });
drawDashedLine(ctx, W*0.25, H*0.14, W*0.25, H*0.95);
drawDashedLine(ctx, W*0.75, H*0.14, W*0.75, H*0.95);
};
const step1 = {
title: "Client sends SYN",
explain: "Client initiates with SYN packet.",
draw(ctx, progress, W, H) {
drawArrow(ctx, W*0.25, H*0.25, W*0.75, H*0.25, { strokeColor: color('--accent') });
drawMovingPacket(ctx, W*0.25, H*0.25, W*0.75, H*0.25, progress, 'SYN');
const lp = subProgress(progress, 0.8, 1);
if (lp > 0) drawPill(ctx, 'SYN_SENT', W*0.25, H*0.32, { fill: color('--warning') });
},
drawResult(ctx, W, H) {
drawArrow(ctx, W*0.25, H*0.25, W*0.75, H*0.25, { strokeColor: color('--accent') });
drawPill(ctx, 'SYN_SENT', W*0.25, H*0.32, { fill: color('--warning') });
}
};
Algorithm Trace
drawBackground: array cells as boxes in a row
- Steps: highlight comparing cells, animate swaps, mark sorted
drawResult: show cells in their new positions after swap, sorted cells in green
State Machine
drawBackground: all state circles + transition arrows (dimmed)
- Steps:
withGlow to highlight current state, animate pulse along transition
drawResult: highlight the new current state (no pulse animation)
Quality Checklist
DB Integration
After creating the visualization:
- Save
.html file to docs/<concept-name>.html
- Save/update explanation in
docs/<concept-name>.md — mention the interactive visualization
- Save to global docs at
~/.local/share/claude-education/docs/<concept-name>.html (for general concepts)
- Append to session log
~/.local/share/claude-education/sessions/[date].jsonl:
{"time": "[now]", "event": "demo", "topic": "[concept-slug]", "file": "docs/[concept-name].html", "saved_to": "global|project|both"}
- If the concept corresponds to a tracked topic, update
last_reviewed in its topic file
Integration with Other Skills
/ascii — quick terminal diagrams (simplest tier)
/excalidraw — static but editable diagrams (middle tier)
/demo — animated interactive visualizations (richest tier)
/quiz-me — after watching a demo animation, quiz the student on the steps
/challenge — "predict what happens at step 5" before revealing it