Creates interactive educational MicroSims using the best-matched JavaScript library (p5.js, Chart.js, Plotly, Mermaid, vis-network, vis-timeline, Leaflet, Venn.js). Analyzes user requirements to route to the appropriate visualization type and generates complete MicroSim packages with HTML, JavaScript, CSS, documentation, screen capture, and metadata.
Version: 1.0
This meta-skill routes MicroSim creation requests to the appropriate specialized generator based on visualization requirements. It consolidates 17 individual MicroSim generator skills into a single entry point with on-demand loading of specific implementation guides.
Six Python batch utilities in src/microsim-utils/ automate the repetitive parts of MicroSim generation (parsing specs, scaffolding files, inserting iframes, fixing iframe heights, validating quality, updating navigation), saving ~430K tokens per batch run. The agent's creative work is focused on writing the .js file.
When the microsim generator skill us used on all of the #### Diagram elements of a chapter, always run the microsim generator tasks sequentially unless the user specifically uses the phrase "execute in parallel".
Use this skill when users request:
Before any generation work, establish paths and determine scope.
# Python utilities live in the ibook-skills repo
UTILS="$HOME/Documents/ws/ibook-skills/src/microsim-utils"
# Detect project root (directory containing mkdocs.yml)
PROJECT=$(python3 -c "
import os, sys
d = os.path.abspath('.')
while d != os.path.dirname(d):
if os.path.isfile(os.path.join(d, 'mkdocs.yml')): print(d); sys.exit()
d = os.path.dirname(d)
print('ERROR: mkdocs.yml not found', file=sys.stderr); sys.exit(1)
")
If the scripts are not found at $UTILS, check for them in the project's own src/microsim-utils/ directory.
| User Request | Route | |-------------|-------| | "Generate MicroSims for chapter 11" | Chapter batch → Step 1 | | "Create a MicroSim for inscribed angles" | Single sim → Step 1B | | "Build a timeline of Unix history" | Single sim → Step 1B |
MANDATORY for chapter-level generation. Do NOT manually parse chapter markdown.
python3 $UTILS/extract-sim-specs.py \
--project-dir $PROJECT \
--chapter <chapter-dir-name> \
--output /tmp/ch-specs.json \
--status-file /tmp/sim-status.json \
--verbose
What this does:
#### Diagram: and #### Drawing: headers from the chapter's index.md<details> block content, iframe paths, sim IDs, Bloom levels, and library hintssim-status.json with lifecycle states: specified → scaffolded → implemented → validated → deployedRead the output:
cat /tmp/ch-specs.json | python3 -m json.tool | head -60
Check the status file to see which sims need work:
python3 -c "
import json
with open('/tmp/sim-status.json') as f:
for e in json.load(f):
if e['status'] != 'deployed':
print(f\" {e['status']:12s} {e['sim_id']}\")
"
After extracting, proceed to Step 2.
For a single MicroSim request (not a full chapter batch):
cat > /tmp/ch-specs.json << 'EOF'
[{
"sim_id": "inscribed-angle-theorem",
"title": "Central vs Inscribed Angles Interactive",
"summary": "Demonstrates the inscribed angle theorem",
"heading_type": "Diagram",
"chapter": "",
"element_type": "microsim",
"bloom_level": "Analyze",
"library": "p5.js",
"iframe_src": "",
"iframe_height": "",
"spec_text": "",
"status": ""
}]
EOF
python3 $UTILS/generate-sim-scaffold.py \
--spec-file /tmp/ch-specs.json \
--sim-id inscribed-angle-theorem \
--project-dir $PROJECT \
--verbose
MANDATORY for batch generation. Do NOT manually create main.html, index.md, or metadata.json.
python3 $UTILS/generate-sim-scaffold.py \
--spec-file /tmp/ch-specs.json \
--project-dir $PROJECT \
--verbose
What this does:
docs/sims/<sim-id>/ directory for each specmain.html with correct CDN links, <main> tag, and schema meta tagindex.md with frontmatter, iframe embed, fullscreen link, lesson plan skeletonmetadata.json with Dublin Core fields and educational metadata--force is used)Using --force for partially-built sims:
When sim directories exist (with main.html + .js) but lack index.md or metadata.json, the scaffold script skips the entire directory by default. Use --force to regenerate all scaffold files. This is safe because the creative work lives in the .js file, which the scaffold never overwrites.
python3 $UTILS/generate-sim-scaffold.py \
--spec-file /tmp/ch-specs.json \
--project-dir $PROJECT \
--force \
--verbose
After scaffolding, the agent ONLY writes .js files from here on.
Before writing any .js file, you MUST complete this checkpoint.
Extract from the specification:
| Bloom Level | Appropriate Patterns | Inappropriate Patterns | |-------------|---------------------|------------------------| | Remember (L1) | Flashcards, matching, labeling | Complex simulations | | Understand (L2) | Step-through worked examples, concrete data visibility | Continuous animation, particle effects | | Apply (L3) | Parameter sliders, calculators, practice problems | Passive viewing only | | Analyze (L4) | Network explorers, comparison tools, pattern finders | Pre-computed results | | Evaluate (L5) | Sorting/ranking activities, rubric tools | No feedback mechanisms | | Create (L6) | Builders, editors, canvas tools | Rigid templates |
Before proceeding, answer these questions:
What specific data must the learner SEE?
Does the learner need to PREDICT before observing?
What does animation add that static arrows don't?
Is continuous animation appropriate for this Bloom level?
If the specification requests animation/effects for an UNDERSTAND level objective:
Add to your response:
Instructional Design Check:
- Bloom Level: [level]
- Bloom Verb: [verb]
- Recommended Pattern: [pattern]
- Specification Alignment: [aligned/modified]
- Rationale: [why this pattern supports the learning objective]
This is where the agent's creative work happens. For each sim that needs implementation:
Scan the spec for trigger keywords and match to the appropriate generator guide.
| Trigger Keywords | Guide File | Library |
|------------------|------------|---------|
| timeline, dates, chronological, events, history, schedule, milestones | references/timeline-guide.md | vis-timeline |
| map, geographic, coordinates, latitude, longitude, locations, markers | references/map-guide.md | Leaflet.js |
| function, f(x), equation, plot, calculus, sine, cosine, polynomial | references/plotly-guide.md | Plotly.js |
| network, nodes, edges, graph, dependencies, concept map, knowledge graph | references/vis-network-guide.md | vis-network |
| flowchart, workflow, process, state machine, UML, sequence diagram | references/mermaid-guide.md | Mermaid.js |
| venn, sets, overlap, intersection, union, categories | references/venn-guide.md | Custom |
| chart, bar, line, pie, doughnut, radar, statistics, data | references/chartjs-guide.md | Chart.js |
| bubble, priority, matrix, quadrant, impact vs effort, risk vs value | references/bubble-guide.md | Chart.js |
| causal, feedback, loop, systems thinking, reinforcing, balancing, CLD, systems archetype | references/causal-loop-guide.md | vis-network |
| comparison, table, ratings, stars, side-by-side, features | references/comparison-table-guide.md | Custom |
| matrix, framework comparison, clickable cells, detail panel, expandable | references/html-table.md | Custom |
| animation, celebration, particles, confetti, effects | references/celebration-guide.md | p5.js |
| classify, classifier, categorize, sort scenarios, identify types, recognize patterns | references/concept-classifier-guide.md | p5.js |
| diagram overlay, callout labels, anatomy, labeled illustration, infographic overlay, explore/quiz modes | references/infographic-overlay-guide.md | Custom (diagram.js) — interactive sim; labels live in data.json, image carries no text |
| python lab, code runner, runnable code block, interactive python exercise, docker | references/docker-python-lab-guide.md | Custom (docker-lab.js) |
| verified infographic, statistics poster, fact-checked poster, cited data, sourced claims, evidence-based comparison | references/verified-infographic-guide.md | Custom (text-verify → image) — static PNG; numbers baked into pixels, never the final deliverable on its own |
| custom, simulation, physics, interactive, bouncing, movement, p5.js | references/p5-guide.md | p5.js |
infographic RoutesBoth routes have "infographic" in the name and they are routinely confused. Pick by asking where the words live:
| | infographic-overlay-guide.md | verified-infographic-guide.md |
|---|---|---|
| Produces | A MicroSim in docs/sims/{sim-id}/ | A static PNG + audit trail in docs/posters/<slug>/ |
| Problem solved | Making an image explorable and measurable | Keeping baked-in numbers from being fabricated |
| Text in the image | None — not even a title | Text and numbers are the content |
| Where labels live | data.json, rendered at runtime by diagram.js | Inside the pixels, locked before rendering |
| Web search / citations | Not used | Mandatory (2+ searches per claim, source_id per element) |
| Emits interaction events | Yes (hover, quiz attempts) | No — a flat image emits nothing |
Rule of thumb: numeric claims that could be wrong → verified guide; structures that need naming → overlay guide. They are not alternatives — see the two policies below, which make them a pipeline rather than a fork.
Never generate a static image as a deliverable unless the user specifically requests one.
A flat PNG is a Level 1 artifact: it emits no interaction events, so it tells us nothing about
whether readers understood it. This library targets Level 2+ (see the root CLAUDE.md), which
means the default answer to "make an infographic" is an interactive one. When a request could
be served either way, route to the overlay guide, not the poster route.
When a static poster carrying verifiable facts is generated — because the user asked for one — it must always be given an interactive overlay afterward. This is not optional and not a follow-up suggestion to offer; it is the second half of the poster route.
The reason is measurement. The poster's value is its verified claims, but a bare PNG cannot tell
us whether anyone engaged with those claims. Wrapping it in a grid-diagram.js overlay turns
each poster region into an instrumented zone: hovers, zone opens, and quiz attempts become
interaction events that let us predict, in aggregate, whether readers have mastered the concepts
the infographic teaches. Per the "2.99" target in the root CLAUDE.md, aggregate those events
across all readers to estimate concept understanding — never retain per-student performance
history tied to an identifiable reader.
Mechanically: after Phase 8, follow the Grid Overlay Workflow in
references/infographic-overlay-guide.md, pointing data.json.image at the rendered
poster.png and keeping showLabels: false (the poster already has printed column titles).
Carry each claim's source_id into the zone facts[] so the citation stays visible.
Numeric claims that must be verified against sources?
→ YES: run Phases 1–4 of verified-infographic-guide.md to lock a cited claim set, then:
· user explicitly asked for a static poster/image/PNG?
→ render it (Phases 5–8), THEN always add a grid overlay on top (see Exit Route)
· otherwise → carry the verified claims into the matched sim guide below.
Never ship a static image the user did not ask for.
Has dates/timeline/chronological events?
→ YES: timeline-guide.md
Has geographic coordinates/locations?
→ YES: map-guide.md
Mathematical function f(x) or equation?
→ YES: plotly-guide.md
Nodes and edges/network relationships?
→ YES: vis-network-guide.md (or causal-loop-guide.md if systems thinking)
Flowchart/workflow/process diagram?
→ YES: mermaid-guide.md
Sets with overlaps (2-4 categories)?
→ YES: venn-guide.md
Priority matrix/2x2 quadrant/multi-dimensional?
→ YES: bubble-guide.md
Standard chart (bar/line/pie/radar)?
→ YES: chartjs-guide.md
Comparison table with ratings/stars?
→ YES: comparison-table-guide.md
Matrix comparison with clickable cells/detail panels?
→ YES: html-table.md
Celebration/particles/visual feedback?
→ YES: celebration-guide.md
Students classify scenarios into categories (sorting quiz)?
→ YES: concept-classifier-guide.md
Labeled illustration with interactive callout markers or hover zones?
→ YES: infographic-overlay-guide.md
Runnable Python code block executed in Docker?
→ YES: docker-python-lab-guide.md
Custom simulation/animation/physics?
→ YES: p5-guide.md
Gate this route first. Only take it when the user has specifically asked for a static poster, image, or PNG. If they asked for an "infographic" without naming a static format, do not render a poster — run Phases 1–4 for the verified claim set and hand it to an interactive guide instead (see "Policy: Interactivity Is the Default" above).
references/verified-infographic-guide.md is the one route in this skill that does not produce a
sim directory by itself. It produces a static poster PNG in docs/posters/<slug>/ alongside its
verification report and source sidecar — which is then always wrapped in an overlay (see below).
When a request matches it:
.js, no CANVAS_HEIGHT, no iframe
insertion, no quality validator, no docs/sims/ entry.MANDATORY Phase 9: wrap the poster in an interactive overlay. A rendered poster is never the
final deliverable. As soon as Phase 8 passes, build a grid overlay MicroSim over it by following
the Grid Overlay Workflow in references/infographic-overlay-guide.md:
data.json.image at the rendered poster.pngshowLabels: false — the poster already has printed column titlessource_id into the zone facts[]Why this is mandatory: the poster's numbers are verified, but a flat PNG emits no interaction
events, so nothing tells us whether readers actually engaged with those claims. The overlay turns
each region into an instrumented zone whose hovers, opens, and quiz attempts let us predict — in
aggregate across all readers, per the "2.99" target in the root CLAUDE.md — whether the concepts
in the infographic have been mastered. Never retain per-student histories tied to an identifiable
reader.
Reusing the verification phases for a real MicroSim. Phases 1–4 (claim plan → source discovery →
per-claim verification → verification report) are output-format agnostic. When a sim must carry
sourced facts — a comparison table of real products, a chart of published measurements, a timeline of
dated events — run Phases 1–4 first, then hand the locked claim set to the matched sim guide and carry
each source_id into the sim's data file so the citation is visible to the student. Skip Phases 5–8;
those are poster-rendering steps.
Read the corresponding guide file from the references/ directory and follow its workflow for writing the .js file.
The scaffold (Step 2) already created main.html, index.md, and metadata.json. You only need to write docs/sims/<sim-id>/<sim-id>.js.
Each guide contains:
Every .js file MUST include a // CANVAS_HEIGHT: comment on its own line near the top of the file (within the first 10 lines). This is the primary source of truth for iframe height across all library types. The sync-iframe-heights.py utility and manual height-fixing rely on it.
No-
.jssims: if a sim is rendered entirely bymain.htmland ships no<id>.js(some projects author Mermaid, vis-network, or custom-HTML sims this way), there is no.jsto hold the comment. Store the height in the sim'smetadata.jsoninstead, as"canvasHeight": <integer>— the consistent structured fallback that downstream tooling reads next after the.jscomment. See the microsim-utils skill'sreferences/canvas-height-strategy.mdfor the full resolution order. Everything else in this step (how to calculate the number, the+2iframe rule) is identical.
Format: // CANVAS_HEIGHT: <integer>
The value is the total pixel height the iframe needs to display the entire MicroSim without clipping — canvas, controls, legends, info panels, titles, and any padding.
| Library | Formula | Example |
|---------|---------|---------|
| p5.js | drawHeight + controlHeight + graphHeight (the canvasHeight variable) | // CANVAS_HEIGHT: 695 |
| vis-network | container height + title (~35px) + info panel (~60px) + legend (~30px) + controls (~40px) | // CANVAS_HEIGHT: 685 |
| Chart.js | chart container height + title (~35px) + controls (~40px) + legend (~30px) | // CANVAS_HEIGHT: 505 |
| Plotly.js | plot div height + title (~35px) + controls (~40px) | // CANVAS_HEIGHT: 475 |
| vis-timeline | timeline container height + title (~35px) + controls (~40px) | // CANVAS_HEIGHT: 475 |
| Leaflet.js | map container height + title (~35px) + controls (~40px) + legend (~40px) | // CANVAS_HEIGHT: 515 |
| Mermaid.js | diagram container height + title (~35px) + controls (~40px) | // CANVAS_HEIGHT: 475 |
| Custom HTML (comparison table, html-table, venn) | total rendered height of all DOM elements | // CANVAS_HEIGHT: 600 |
| Interactive Infographic Overlay | image container height + toolbar (~40px) + info panel (~60px) | // CANVAS_HEIGHT: 620 |
p5.js:
// Predator-Prey Population Dynamics Simulator
// CANVAS_HEIGHT: 695
let drawHeight = 400;
let graphHeight = 180;
let controlHeight = 115;
let canvasHeight = drawHeight + graphHeight + controlHeight;
vis-network:
// Climate Feedback Loops - vis-network
// CANVAS_HEIGHT: 685
document.addEventListener('DOMContentLoaded', function() {
Chart.js:
// Air Quality Trends Dashboard - Chart.js
// CANVAS_HEIGHT: 505
document.addEventListener('DOMContentLoaded', function () {
Leaflet.js:
// Watershed Map - Leaflet
// CANVAS_HEIGHT: 515
document.addEventListener('DOMContentLoaded', function() {
Interactive Infographic Overlay:
// Ecosystem Components Overlay
// CANVAS_HEIGHT: 620
document.addEventListener('DOMContentLoaded', function() {
px suffix, no expressions).sync-iframe-heights.py utility adds this automatically.drawHeight + controlHeight (plus graphHeight if present). Keep the existing named variables — the comment is a redundant-but-authoritative declaration for tooling.If the request could match multiple generators:
references/routing-criteria.md for detailed scoring methodologyBased on your request, I recommend:
1. [Generator A] (Score: 85) - Best for [reason]
2. [Generator B] (Score: 70) - Alternative if you need [feature]
3. [Generator C]
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer