Builds figures that move or respond to the reader, in three tiers: SMIL animations and slider widgets inside lessons, interactive mechanism figures that show the named parts of a real system with a computed verdict, and ordered dither bands in the course palette. Triggers: "animated figure", "add a slider widget", "interactive figure", "show how this system works", "make this diagram move", "dither masthead", "mechanism figure", "figure fence".
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
The canonical home for this skill is motion-figure in rohitg00/ai-engineering-from-scratch
This skill makes figures that move or respond to input. It has three tiers. Use this skill with Claude, Cursor, Codex, OpenClaw, Hermes, or any agent that reads SKILL.md.
| Tier | What it makes | Where it goes |
|---|---|---|
| 1. Lesson figure | Declarative SMIL animation, or a slider widget that redraws an SVG. Both mount from a ```figure fence. | Course lessons |
| 2. Mechanism figure | An HTML panel that shows the named parts of a system. The reader drives one control and reads a computed verdict. | Standalone pages, READMEs, essays, the course site outside lessons |
| 3. Dither field | A WebGL band of ordered dither dots in the paper, accent, and ink colours, with four seeded motions. | Page mastheads and section breaks |
Tier 1 has the most rules, because the lesson runtime has hard limits. Tiers 2 and 3 have their own reference files.
blueprint-figure covers static figures.isometric-explainer covers that.course-style holds those. This skill copies the parts it needs into references/tokens.md.Write one sentence that names the single change the figure shows. If you need two sentences, make two figures.
Pick the tier. Inside a lesson, use tier 1. For tier 2, read references/mechanism-figures.md and start from templates/mechanism.html. For tier 3, read references/dither-fields.md and copy templates/dither.js. The steps below are for tier 1. In tier 1, use an animated figure when time is the variable. Use a slider widget when a number is the variable.
Pick a name in kebab case, for example request-path or context-budget. Search the registry for that name first. A later module that registers the same name replaces the earlier figure.
Put the code in a module file named figures-<topic>.js. Wrap it in an IIFE, read window.LF, and return early if it is missing.
Write a figure function function (host, cfg). It appends one .lf card to host and can return a dispose function.
Build the card: .lf-head with an uppercase .lf-label and a short hint, .lf-body, and .lf-cap with the caption.
Use viewBox="0 0 520 H" for the SVG. Most course figures use an H from 200 to 250. A single bar needs less.
Add a <title> and a <desc> with ids that you create once, outside any render function.
For an animated figure, add entries first, then one slow loop. Follow references/smil-rules.md line by line.
For a slider widget, define state._render before you call LF.slider or LF.select. Then call state._render() once at the end.
Call LF.register({ 'your-name': fn }) at the end of the module.
In the lesson Markdown, add the fence. Put the name on the first line and optional JSON config after it:
```figure
context-budget {"windowK": 32}
```Run the checks in "Check before you finish". Look at the figure in light theme, dark theme, at 375 px width, and with reduced motion on.
<div class="lesson-figure" data-figure="name {json}">.cfg.role="img", and control labels if they are missing. It adds a Pause button when the figure has SMIL animation, and a Replay button when any animation plays once.references/toolkit.md describes every runtime function and has two complete example modules.
Animated figures:
<animate>, <animateTransform>, and <animateMotion>. Do not use setInterval or requestAnimationFrame in a figure.calcMode="spline" and keySplines="0.23 1 0.32 1". Entry duration is 0.5 to 0.6 s.repeatCount="indefinite". Do not set fill="freeze" on a loop, because the runtime then plays it once.keyTimes list has as many entries as values. It starts at 0, ends at 1, and never decreases.keySplines list has one entry fewer than keyTimes. Use it only with calcMode="spline".animateMotion with keyPoints uses calcMode="linear". Its keyPoints count equals its keyTimes count. It has no values.var() in an animated fill or stroke value. Animate the opacity of a second element that has the target colour.stroke-dashoffset, or motion along a path. The runtime makes any animation of x, y, x1, y1, x2, y2, width, height, r, cx, cy, rx, or ry play once.data-static-time (default 1.5 s) is complete and readable. Set the attribute on the host when a later moment shows the full state.translate. Add the scale with additive="sum".Slider widgets:
var, function expressions, string concatenation. No arrow functions, let, const, or template literals.state._render before the first LF.slider or LF.select call. The slider wraps the render function when you create it.state._render, remove all SVG children and add them again. Do not edit nodes in place.state._render. The runtime removes attributes that the new nodes do not have, ids included.stroke-dasharray on a path. Do not grow bars with scale, because reconciled nodes scale from their centre.chunk size (tokens).Both kinds:
var(--blueprint,#3553ff). Use literal hex only when no variable works.--blueprint) for the main subject and --warn for one second state. Use ink and rule tokens for the rest.var(--font-mono). If labels must be smaller, give the SVG a minimum width of 500 px and let it scroll sideways..lf-label in uppercase, two to four words.Mechanism figures (tier 2):
item 1 or a grey bar with no name.transform and opacity only, with cubic-bezier(0.23, 1, 0.32, 1). Press 120 to 160 ms, reveal 200 to 300 ms, fold 380 to 500 ms.Dither fields (tier 3):
--bg, --blueprint, and --ink, and redraw when data-theme changes.aria-hidden="true" and put no text on the dots except the label chip.=>, let, const, or backtick strings.setInterval and no requestAnimationFrame.references/smil-rules.md returns an empty list for the mounted host.NaN, no negative widths, and no console errors.references/mechanism-figures.md passes.references/dither-fields.md passes.references/smil-rules.md: the twelve SMIL rules in full, what each rule prevents, and a validator you can run in the browser console.references/toolkit.md: the LF functions and the mount sequence. It also has a complete slider widget, a complete SMIL figure, and a preview page for use outside the course site.references/tokens.md: colour tokens for light and dark themes, fonts, and motion timing values.references/mechanism-figures.md: tier 2. Real names, rejected figures, mechanism shapes, anatomy, verdict, motion budget, and checks.references/dither-fields.md: tier 3. How the shader draws, the four motions, markup, rules, dithered bars, and checks.templates/mechanism.html: a complete tier 2 figure, an LRU cache with a size control, that opens in any browser.templates/dither.js: a complete tier 3 script. Load it and add <div class="dither" data-seed="...">.Inside the AI Engineering from Scratch repo, also see site/lesson-figures.js for the runtime and site/figures-*.js for more figures.
rohitg00/ai-engineering-from-scratch
fe6c657
Canonical home
since Oct 30, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.