Diorama Skill
The skill teaches your agent to build a small animated 3D world in one file: the kernel, five themes, eleven examples, a validator and a browser check.
Installation
npx skills add educlopez/diorama -gInstalls the skill for every agent the skills CLI knows. Add -a claude-code to target Claude Code alone. Node.js 20 or later runs the scripts; Chrome or Chromium runs the look (Playwright's browser is found, or playwright-core is installed once).
git clone https://github.com/educlopez/diorama.git ~/.claude/skills/dioramaThe same, with git. Nothing is needed at runtime: a finished page loads three.js r128 from cdnjs, or carries it inline with --inline.
Prompts
Type /diorama and describe the place. Say where it will live (a hero, a card, a small figure), name the place or the product, and give a colour if you have one. The agent offers two or three concepts, builds the one you pick, runs the validator and the look, and hands you diorama-<name>.html.
/diorama a hero for our logistics landing page: a yard with trucks docking/diorama an empty state for the inbox, small and quiet, line-drawing style/diorama a card for the docs: jobs wait in line, one runner takes them/diorama a harbour at dusk for the top of our README, brand colour #5b4ae0Sizes
The size sets the stage, the budget and the tempo.
| Size | Lives | Stage | Moves | Lines |
|---|---|---|---|---|
| hero | the top of a landing page or a README | 3:2, full width | three or four loops with different periods, one pointer answer | ≤ 420 |
| card | beside text in docs or a post | 4:3, about 500px | one process, one pointer answer | ≤ 240 |
| mini | a small spot: an empty state, a feature list, a sidebar, a 404, an icon-sized hero | 1:1, 160 to 240px | one quiet ambient motion | ≤ 150 |
Themes
A theme is a set of fields the kernel applies to every primitive; a figure never branches on it, so the same file draws five ways. Pick it from where the figure will live.
| Theme | Reads as | Keeps | Use it for |
|---|---|---|---|
| toy | pastel blocks, one warm sun, a cool fill, soft shadows | every colour | product pages, READMEs, anything warm |
| soft | the same on cream, gentler light, desaturated accents | every colour, shifted warm | editorial pages, paper backgrounds |
| mono | tints of ink on white | one accent | docs, product UIs with their own accent, text-heavy pages |
| line | a hairline drawing: white fills, ink edges, silhouettes, no shadows | one accent, as a stroke | minimal or technical pages, small quiet figures |
| night | dusk: dark base, cool sky, warm lamps and windows | every colour, darker | dark pages, hero sections on black |
theme: { base: 'mono', accent: '#f2c230', shadows: false }
theme: { base: 'toy', palette: { coral: '#5b4ae0', grass: '#d8ead0' } }
theme: { base: 'line', round: true, strokeWidth: 1.4 }
theme: { base: 'night', glow: 3, lights: { sun: ['#ffd6a0', .3] } }| Field | What it does |
|---|---|
| bg | the stage colour, or 'transparent' |
| palette | overrides of any palette entry: base, ground, grass, water, paper, ink, coral, mustard, teal, plum, … |
| accent | the one colour mono and line keep |
| lights | { hemi: [sky, ground, i], sun: [c, i], fill: [c, i] | null, ambient: [c, i] } |
| shadows | true or false |
| finish | { roughness, metalness } |
| tone, tint | { paper, ink } makes any theme monochrome; tint 0..1 lets colour back in |
| edges, outline | ink lines on flat solids, silhouettes on round ones |
| stroke, strokeWidth | the line colour and width in css px |
| round | every box becomes a rounded solid |
| glow | a multiplier on every emissive |
Minis
A mini is a small figure, 160 to 240px square: one object and one quiet motion. Use it wherever a page needs a small picture: an empty state, a feature in a list, a settings section, a 404, a sidebar. Its still frame is the picture and the ambient motion is the bonus. The canvas is transparent, so whatever sits behind it shows through. The words around it, a heading, a line, a button, are yours to write in your own UI.
The figure file
One Diorama.figure call: a declaration, a build that makes the scene once with the toolkit and returns the parts that move, and a tick that poses them from ctx.t. No timers, no new THREE.*, no words inside the scene.
Diorama.figure({
name: 'mailbox',
size: 'mini', // hero | card | mini
theme: 'toy', // or { base: 'line', accent: '#cf6a4c' }
means: 'An open letterbox with nothing inside. The flag lifts now and then.',
title: 'Mailbox',
still: 1, // the second reduced motion shows
build: function (o) {
var D = o.D, pal = o.pal;
D.slab(3, 3, pal.grass, 0, 0, 0, null, { h: .5, r: .45, side: pal.base });
var post = D.group(.15, 0, -.1);
D.cyl(.07, .09, 1.1, pal.wood, 0, .55, 0, post, 8);
var body = D.group(0, 1.15, 0, post);
D.box(.95, .5, .6, pal.coral, 0, .25, 0, body);
var flag = D.group(.1, .5, .32, body);
D.box(.26, .16, .03, pal.mustard, .1, .02, 0, flag);
D.props.tree(1, -.8, null, { r: .42 });
return { flag: flag };
},
tick: function (ctx) {
var D = ctx.D, t = ctx.t, check = D.smooth(D.pulse(t, 7, .36));
ctx.parts.flag.rotation.z = D.lerp(.2, 1.45, check);
}
});The toolkit: D.box, D.rbox, D.cyl, D.cone, D.ball, D.dome, D.wedge, D.slab, D.torus, D.wheel, D.label; the props tree, bush, rock, cloud, person, lamp, crate, pallet, cone, flag; for motion phase, pulse, wave, the eases, spring, path, place, spin, stagger. The index at the top of kit/diorama.js lists them all.
Scripts
node ~/.claude/skills/diorama/scripts/build.mjs mailbox.jsWrites diorama-mailbox.html: three.js from cdnjs, the kernel, the figure and the bench page. Add --inline to paste three.js in.
node ~/.claude/skills/diorama/scripts/validate.mjs diorama-mailbox.htmlNine checks: the declaration, the length, the clock, self-containment, the kernel, the words, the colours, the base and the pointer.
node ~/.claude/skills/diorama/scripts/look.mjs mailbox.js --theme lineOpens the page in headless Chromium and writes one sheet: the still frame, three moments, the pointer, the tilt, the thumbnail and the page, plus the console, the fill, the motion and the answer as numbers.
Embed
The built page can be served as is or framed. For a product, keep the kernel and the figure and drop the bench. The kernel sizes the canvas to the element’s width, watches resizes, sleeps offscreen and honours prefers-reduced-motion with one still frame. Remount to change the theme.
<div id="hero" style="width:100%"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="/diorama/kit/diorama.js"></script>
<script src="/diorama/island.js"></script>
<script>
var fig = Diorama.figures[Diorama.figures.length - 1];
var ctx = Diorama.mount(fig, { el: document.getElementById('hero'), theme: 'night' });
</script>"use client";
import { useEffect, useRef } from "react";
import * as THREE from "three"; // npm i three@0.128
import Diorama from "./diorama.js";
import "./island.js"; // registers the figure
export function Hero({ theme = "toy" }) {
const el = useRef<HTMLDivElement>(null);
useEffect(() => {
const fig = Diorama.figures[Diorama.figures.length - 1];
const ctx = Diorama.mount(fig, { el: el.current!, THREE, theme });
return () => ctx.destroy();
}, [theme]);
return <div ref={el} style={{ width: "100%", aspectRatio: "3 / 2" }} aria-hidden />;
}Craft rules
Ten rules separate a diorama from a pile of cubes: the world stands on a rounded base with its zones inside the corners; the camera is true isometric, subject front-left; the palette is pale with two or three accents and one named accent; materials are matte blocks, no textures; every object is a few primitives with the two or three features that give it away; one sun and soft shadows under everything; all motion comes from the clock in tick; vehicles ride paths on a schedule with stops that have a cause; a few loops with different tempos and one rare thing; and no words inside the scene. The long form, with recipes, is in references/craft.md.
What is in the skill
| File | What it is |
|---|---|
| SKILL.md | the workflow: size and concept, build, check, hand over, adjust |
| kit/diorama.js | the kernel: camera, lights, shadows, themes, primitives, props, paths, springs, the loop |
| bench.html | the page a figure is built into; a theme switcher and a still-frame toggle |
| scripts/build.mjs | writes diorama-<name>.html; --inline pastes three.js in |
| scripts/validate.mjs | nine checks: declaration, length, clock, self-contained, kernel, words, colours, base, pointer |
| scripts/look.mjs | a sheet of eight pictures and the numbers, in headless Chromium; --theme for another theme |
| references/ | concepts, the ten craft rules and the themes, motion, the look, React |
| examples/ | eleven figures across sizes and themes, the format to write |
npx skills add educlopez/diorama -g