Skip to content
Design
Skill

/iso-figure

Build an interactive isometric line-art "figure" (Fig N style) of an object in a single HTML/SVG file: monochrome technical-illustration look, parts you can press that produce real output, live state readout. Use for hero illustrations, interactive diagrams, product figures, and

From plugin
iso-figure
3531 skill

Claude Code

$ npx -y skills add MrBongoC/ai-iso-skill --skill iso-figure --agent claude-code

SKILL.md

iso-figure.SKILL.md
name: iso-figure
description: Build an interactive isometric line-art "figure" (Fig N style) of an object in a single HTML/SVG file: monochrome technical-illustration look, parts you can press that produce real output, live state readout. Use for hero illustrations, interactive diagrams, product figures, and playable desk objects (computer, synth, calculator).

Interactive isometric figure

Produces one self-contained HTML file: a rounded panel captioned like a textbook plate, holding an isometric line drawing of an object whose parts actually work. A switch toggles, keys depress, a screen shows what was typed, a synth key makes sound. No libraries, no canvas, no 3D engine, just plain SVG generated by about 15 lines of projection code.

The object must do something real. A figure that only animates is decoration; a figure where pressing a part produces output (text, a number, a sound, a changed display) is the point. Decide what the output is before drawing anything.

The four things that make it work

1. **Everything is a flat 2D shape placed on a 3D plane.** Never hand-compute skewed polygons. Draw ordinary `<rect>`, `<text>`, `<path>` in a face's local coordinates and let one SVG `matrix()` put it on the plane. Text, glyphs and rounded corners then sit in correct perspective for free. 2. **Objects are boxes; a box is its three visible faces.** Complex objects are boxes plus flat detail drawn on their faces (vents, slots, bezels, LEDs, labels). 3. **Interaction is class toggles on SVG groups.** One `state` object, one `render()`; CSS does the motion. 4. **The frame sells it.** Four monospace corner captions: `Fig N` (top-left), OBJECT NAME (top-right), the instruction (bottom-left), a live state readout (bottom-right).

Kernel (copy verbatim, then build the scene)

const C = Math.cos(Math.PI/6), S = Math.sin(Math.PI/6), OX = 465, OY = 300; // where the 3D origin lands in the viewBox
const P = (x,y,z) => [(x-y)*C + OX, (x+y)*S - z + OY];   // point: 3D -> screen
const D = (x,y,z) => [(x-y)*C, (x+y)*S - z];              // direction only
// plane = origin O + in-plane axes U,V. Anything inside a <g> with this transform lies flat on that plane.
const plane = (O,U,V) => { const o=P(...O), u=D(...U), v=D(...V);
  return `matrix(${u[0]} ${u[1]} ${v[0]} ${v[1]} ${o[0]} ${o[1]})`; };
const TOP   = (x,y,z) => plane([x,y,z],[1,0,0],[0,1,0]);   // z = const
const FRONT = (x,y,z) => plane([x,y,z],[1,0,0],[0,0,-1]);  // y = const (faces lower-left); pass its top-left corner
const SIDE  = (x,y,z) => plane([x,y,z],[0,-1,0],[0,0,-1]); // x = const (faces lower-right); pass its top-left corner
const rect = (t,w,h,r=0,cls='face') =>
  `<g transform="${t}"><rect class="${cls}" width="${w}" height="${h}" rx="${r}"/></g>`;
// box at (x,y,z), size w along x, d along y, h along z
const box = (x,y,z,w,d,h,r=0) =>
  rect(SIDE(x+w,y+d,z+h), d,h,Math.min(r,h/4)) +
  rect(FRONT(x,y+d,z+h), w,h,Math.min(r,h/4)) +
  rect(TOP(x,y,z+h), w,d,r,'face top');

Axes: +x runs down-right, +y runs down-left, +z is up. The viewer sees the top, the `y = max` face (left) and the `x = max` face (right). Put the "front" of the object (screen, display) on a FRONT face and anything the user reaches for (keys, buttons, dials) at larger `y`, in front of it.

Detail on a face: open a group with that face's transform and draw in face-local units, origin at the face's top-left.

svg += `<g transform="${FRONT(70,190,240)}">
  <rect class="face glass" x="28" y="31" width="124" height="104" rx="12"/>
  <text x="38" y="112" font-size="8.5">&gt; hello</text>
</g>`;

Required CSS

.face   { fill:var(--body); stroke:var(--line); stroke-width:1; vector-effect:non-scaling-stroke; stroke-linejoin:round; }
.face.top { fill:var(--deck); }
.detail { fill:none; stroke:var(--detail); stroke-width:1; vector-effect:non-scaling-stroke; }
.press { cursor:pointer; transition:transform 60ms ease-out; }
.press.down { transform:translateY(4px); }
.press.down .face { stroke:var(--live); }

`vector-effect:non-scaling-stroke` is not optional. Without it the matrix skews stroke widths and the hairline look is lost. Faces must have an opaque fill: painter's-order occlusion depends on it.

Procedure

1. **Name the output.** What does pressing a part produce? Typed text, an arithmetic result, a note, a toggled light. Everything else serves that. 2. **Decompose the object** into 3-8 boxes. Write their `(x,y,z,w,d,h)` as a small table first. Pick the pressable parts and the one surface that displays state. 3. **Emit back to front.** Paint order is the only depth sorting: smaller `x+y` first, lower `z` first. For grids (keys, buttons) loop rows by increasing `y`, then columns by increasing `x`. Parts that sit on top of others (black piano keys over white) go after everything beneath them. 4. **Wrap each pressable part in its own `<g class="press" data-…>`** containing its box and its label. A label drawn on the part's TOP plane inside the same group moves with it when pressed. 5. **Frame it numerically.** Project the scene's extreme corners with `P`, then set `OX/OY` and `viewBox` for roughly 8-15% margin on every side. Eyeballing clips tall objects. 6. **Wire state.** One `state` object, one `render()` that toggles classes and rewrites the display and readout. Pointer and keyboard input call the same functions. 7. **Motion in CSS only.** Pressed part: `translateY(4px)` (straight down on screen is −z in iso) over about 60ms, stroke flashing to the live colour. Honour `prefers-reduced-motion`. 8. **Readout** in the bottom-right, terse and lowercase, dot-separated: `off` → `on · 9 chars · key t`. It changes on every interaction. 9. **Verify in a browser.** Load it headless, drive it with real key presses and mouse presses at projected coordinates, read back the readout, and screenshot one interacted state. Check nothing is clipped, nearer parts cover farther ones, and there are no console errors.

Input patterns

Ke

Read more
Stats
357
Stars
24
Forks
Maintained
Maintenance
MIT
License
Last commit
Created
Added

Repo: MrBongoC/ai-iso-skill

@mrbongoc
Ships withiso-figure

A skill for Claude that draws interactive isometric figures. Name an object and you get back one HTML file: a hairline isometric drawing on a numbered plate, with parts that work when you press them. Both were made with the skill.

Stars on GitHub

Momentum

stars in total
353
Star history of MrBongoC/ai-iso-skill on GitHub, a chart by star-history.com

More skills from other plugins.

impeccable

impeccable

Use to design, redesign, critique, audit, polish or animate a frontend: websites, landing pages, dashboards, app UI, components,…

@pbakaus@pbakausInstall Skill

Questions about iso-figure.

Which coding agents can use iso-figure?
iso-figure installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.