---
name: resin-diorama
description: Build an interactive 3D resin-block diorama web scene from a theme, a reference image and must-have elements, with a slot-filled meta prompt, rendering lessons, headless checks and a runnable sample.
version: 0.2.0
---

# Resin diorama

## Example

Open `results/sea-train/index.html` in a desktop browser and hold the mouse (or Space) to depart. A little red tram leaves its stop and runs laps through a clear turquoise resin block. The light turns to dusk while you hold, the lamp-lit windows glow on the water, and one perched gull and two flying gulls react. Release, and the tram brakes back to its stop. All sound is synthesized after your first click; the button at the bottom right mutes it.

The same file holds a second scene: open it with `?scene=resin-island` for Resin Island, a cliff island with a beach bay cast in clear resin. Drag across the water for ripples that stop at the shoreline; click, tap or press Space to wobble the block and splash. Both scenes have a **Tune** button (bottom right) that opens a bilingual tuning panel: water colours, clarity, caustics, waves, sun, train or tide, jelly stiffness, depth of field, glow, ambient light and the quality mode (automatic, high, low), plus Reset.

- The file is one self-contained HTML page (about 1.7 MB) with no network access and no storage, built from `assets/sea-train/` (the folder holds both scenes).
- `results/sea-train/report.en.html` and `report.zh-CN.html` hold its headless verification record (console errors, CSP violations, gull counts, the clipping-cap and caustics checks, the tuning panel, audio state, frame rate per scene).

## When to use

- Someone wants a "miniature world in a resin block" web scene: a theme, a reference image and a few must-have elements, turned into a live WebGL page with an interaction, sound and a product-photo look.
- You need one self-contained HTML file that runs inside a strict sandbox (no network, no storage).

When not to use: photoreal rendering, scenes that need model or texture files, or server-side generation. This Skill calls no model; an agent does the work locally.

## Inputs (slots)

Required: `theme`, `subject`, `mustHave`. Optional, with defaults: `referenceImage`, `interaction` (default "free design"), `sounds`, `medium`, `floor`, `underwater`, `disturbance`, `bigMove`, `background`, `params`, `extraPrompt`. Every value is a string of at most 2000 characters. `references/prompt-slots.md` explains each slot; `assets/prompts/examples/sea-train.json` and `resin-island.json` are the slots files of the two scenes.

## Workflow

```
node <skill>/scripts/fill-prompt.mjs --slots slots.json --lang en --out prompt.md
node <skill>/scripts/new-project.mjs --out my-diorama
cd my-diorama && npm ci
npm run dev                      # live preview; stop it with Ctrl+C
npm run build:single             # → dist-single/index.html
npm run shoot -- --file dist-single/index.html   # needs local Chrome; --scene sea-train|resin-island|all
```

1. Fill the slots and render the meta prompt (`fill-prompt`). Give the prompt and the reference image to the coding agent.
2. Start from the reference app (`new-project`): pick the closer of its two scenes (`src/scenes/sea-train/` or `src/scenes/resin-island/`). It already has the resin block, clear water, caustics, heightfield ripples, jelly wobble, procedural environment, synthesized sound, the tuning panel (`src/lib/controls.mjs`), the `inspect()` hooks and the single-file build. Replace the subject and the must-have elements.
3. Between `dev` and `build:single`, iterate: read `references/lessons.md` before writing materials, and run `shoot` after each round to compare the screenshots with the reference image.
4. Deliver `dist-single/index.html` once `shoot` passes. `references/verification.md` describes every check; `references/hosting.md` the sandbox it must pass.

## Language

`fill-prompt --lang en|zh-CN` picks the prompt language (`zh` is accepted; anything else falls back to English). The scene UI follows `?lang=en|zh-CN` (default English). The CLIs print English by default; `new-project` and `fill-prompt` take `--lang`, and the app scripts (`notices`, `inline-build`, `shoot`, `record`) take `--lang` or the `DIORAMA_LANG` environment variable.

## Keys

None. Nothing in this Skill calls a model or a network service. `npm ci` downloads the pinned packages from the public npm registry.

## Failure boundaries

- Real-time WebGL, not photoreal parity with a rendered reference image.
- Phones (coarse pointer, small screen) start on the low tier and are not device-tested. Desktop starts high; after a 3 s warm-up a sustained low frame rate drops it to low.
- `shoot` and `record` need Node 22.4 or newer and a local Chrome; `record` also needs ffmpeg. Headless capture has no audio, so listening is a manual check.

## FAQ

- **Does it need an API key?** No.
- **Why one HTML file?** It can be opened from disk, hosted anywhere and embedded in a sandboxed iframe without a server.
- **Can I change the theme?** Yes: fill the slots with your theme and must-have elements, then replace the subject components in the new project.
- **Why is there no drei `Environment`?** It ships a CDN preset table; the sandbox blocks network access. `src/components/ProceduralEnv.tsx` builds the environment in code.
- **Where are the third-party licences?** `npm run build:single` embeds `THIRD_PARTY_NOTICES.txt` as an HTML comment in the file's `<head>`; never strip it.
