Diorama / Dither

A yard.
In hard pixels.

Build an isometric miniature on the Pixel kernel, then finish it as a dithered yard: 360 by 280, five close tones, a 4 by 4 ordered dither, a hard shadow and one tap that toggles a state. One offline HTML file of at most 70 KB.

What it is

Dither is a skill for one small place. The picture is a yard or a shore that fills the frame, one structure, one or two people doing one looping action, and a tap that changes something you can see. There is no score and no audio. The camera does not move.

The drawing is the Pixel kernel, unchanged. New helpers live in the dither finish, not in that kernel. A pixel page never loads this finish, so the three Pixel scenes stay as they are.

How it differs from Pixel

PixelDither
KernelPixel, on its ownThe same Pixel kernel, plus the dither finish
Frame320 x 240, 24 fps360 x 280, 12 fps
Dither8 x 8 Bayer matrix4 x 4 ordered dither, five close tones
ShadowA shadow map and contact shadowsOne hard shadow that darkens the ground's own colour
GroundAn outline that dissolves into the pageA yard or a shore that fills the frame
TapA small answer: a wave, a strike, a pourOne toggled state, large enough to read
PageAbout 55 KBAt most 71680 bytes, and at most 260 lines of scene

Worlds is a different renderer: Three.js, articulated people, four finishes. Dither does not use it. For crisp vector figures, use Diorama SVG.

Install

npx skills add educlopez/diorama --skill diorama-dither -g

--skill diorama-dither selects Dither. The others are --skill diorama (SVG), --skill diorama-worlds and --skill diorama-pixel. All four live under skills/ in the same repository. Add -a claude-code or -a codex to target one agent. Omit -g for a project-local install.

Node.js 20+ runs the build and the validator. The look (browser screenshots and checks) needs Chrome or Chromium and the skill's one dev dependency, installed once with npm ci --ignore-scripts --prefix <skill-folder>. Built pages need nothing: no WebGL, no CDN, no network.

Ask for a yard

/diorama-dither a stone forge in a mountain yard. The smith strikes the anvil, smoke leaves the chimney, and a mule waits with the cart.

In agents without slash commands, ask “Use the diorama-dither skill…”. Name the yard, the one action, and the one thing a tap toggles. The agent writes the picture in four lines (ground, mass, people, life), builds the scene, validates it, runs the support check and opens the captures before handing it over.

What you get

PartWhat it does
frame360 x 280 internally, enlarged by a whole number with square pixels. 12 fps. An 8 second loop.
materialsNamed ramps: meadow, earth, stone, tile, timber, water, sail, paper. Five close tones each. A report checks the ramp before a custom one is invented.
ditherA 4 x 4 ordered matrix between those tones. A ray uses a flat face, with a darker dithered tone on alternate segments so it does not read as one bar.
shadowOne sun, a hard shadow on the ground's own colour, lit ground past the shadow. Not a flat grey bar.
peopleOne or two figures from the finish's person helper, with three cloth colours far apart. The pointer names them.
tapToggles one state. The still frame starts with that state clear, and the other state has to change a mass you can see.
lamp and rayA lamp is a post, a paper box and a cap. A beam is thin hard pixels. Neither is a soft wrap of light.

Support

A piece either meets a surface or names why it does not. npm run support from the skill folder audits every example. One scene is node scripts/support.mjs examples/<name>.js. Both the script and the look check the still and the frames at a quarter, a half, three quarters and the end of the loop.

CallWhat it claims
Dither.seat(node, name)The bottom face is within one voxel of the ground.
Dither.seat(node, name, other)The two solids meet within one voxel. A bed on an axle, a screen on a floor.
Dither.seat(wheel, name, 'ground', axle)A wheel meets the ground and its axle. The bed sits on the axle.
Dither.seat(node, name, 'water')The water plane cuts the body. A hull sits in the water, not on it.
Dither.afloat(node, name, reason)The only leave-the-ground. The reason is a non-empty string: a carried sack, smoke, a ray.

A mesh with no support fails as has no support. Sitting inside a group's box is not enough: the nearest mesh has to be within one voxel, unless the bottom is already on the ground. A blank float reason fails as floats without a reason. A figure whose body passes through a solid that is not the ground fails as stands inside. Feet on open water fail. A missing foot coordinate fails as has no place to stand, and does not silently stand at the origin.

Walls, gates, fences, lamps, trees and the person helper already seat themselves. Wheels, posts, hulls and anything you add by hand still need a seat or a reason.

Byte budget

The scene file stays at or under 260 lines. The built page stays at or under 71680 bytes. node scripts/validate.mjs examples/<name>.js assembles that page and, on a pass, prints the bytes left. The kernel takes most of the file. A longer title spends some of the rest, because the page shell writes it. When the page is over, cut decoration before the action.

SceneLinesBuilt pageLeft of 71680
The mountain forge15071675 bytes5 bytes
The lighthouse12670115 bytes1565 bytes
The tea house14371083 bytes597 bytes
The windmill13370948 bytes732 bytes

These counts come from the pages the site builds. The gallery on /dither shows the same size next to each scene.

Examples

Four yards ship with the skill. Each is one Pixel.scene file under skills/diorama-dither/examples/. Open them live, or read the source.

SceneWhat happens
The mountain forgeA smith strikes the anvil by a stone forge. Smoke leaves the chimney, and a mule waits with the cart. Hover the smith or the mule; tap the smith to rest.
The lighthouseA plaster tower on a rocky islet. A hard ray crosses the water, and a small boat rocks beside the rocks. Hover the keeper or the boat; tap the keeper to toggle the beam.
The tea houseA timber tea house by a koi pond. Carp circle in the near water, and a tap shifts the hour from day to dusk. Hover the host or a lantern; tap the host to change the hour.
The windmillA stone mill under a conical tile cap. The sails turn on the front shaft while the miller holds a sack. Hover the miller or the carter; tap the miller to brake the sails.

Build and check

node <skill-folder>/scripts/build.mjs examples/forge.js
node <skill-folder>/scripts/validate.mjs examples/forge.js
npm run support
node <skill-folder>/scripts/look.mjs examples/forge.js work/forge-look

Run the commands from the skill folder, or pass paths that reach it. npm run support audits every example, then the cases that must fail (a lifted wheel, a floating box, a figure in water) and the cases that must pass (a figure on rock). The look opens the page with the network blocked and writes the still, four loop moments, hover, press, mobile and figure zooms. It checks fill, the loop seam, picking, the tap, reduced motion, a hidden tab, off-screen pause, hard shadows and a median frame at or under 83.3 ms. Open the images too: a pass is not a picture.

Embed

<iframe
  src="/dither-forge.html?embed"
  title="A smith striking the anvil at a mountain forge"
  style="width:100%;aspect-ratio:360/280;border:0"
></iframe>

?embed fills the frame with the canvas and leaves the words to your page; the read-out stays in a corner. The frame is 360 by 280, so the box is wider than Pixel's 4:3. To mount without a frame, load the built kernel and the scene and call Pixel.mount on the last scene. Primitives and the tick contract are the Pixel scene API. Do not copy Pixel's dissolving ground or its 320 x 240 frame into a dither scene. The finish's helpers (Dither.mat, Dither.seat, Dither.folk and the rest) are in the Dither skill.

Know the tradeoffs

The loop runs at 12 fps, sleeps offscreen and in hidden tabs, and holds the still frame under reduced motion and ?still. Do not start a timer. Pose from the clock only, and close the loop so the first frame matches the last.

People are small figures on the pixel rig, not the articulated adults of Diorama Worlds. The camera is fixed. A second light is out of the finish: evening is dark cloth, paper screens and a small hard core you show and hide, not a pool of light. Do not set glow on a material. It lifts that face to a flat brightness. Sizes, the yard recipe and the shadow checks are collected in the yard reference.

Read the Dither skill source