---
name: obsidian-shards
description: Build an interactive 3D scene where tens of thousands of glossy shards morph between forms over a sunset sea, with a slot-filled meta prompt, a runnable sample, headless checks and one HTML file.
version: 0.1.1
---

# Obsidian shards

## Example

Open `results/sunset-loop/index.html` in a desktop browser. About 32,000 dark glass shards stand as a monolith in a sunset sea. Gold Voronoi seams light up across its face, it bursts into a spinning storm, and the shards fly on into a cathedral, a whale swimming across the sky, a rain onto the water and back into the monolith. Drag to orbit, click or press Space for the next form, and press 1–5 (or the chips) to pick monolith, cathedral, whale, storm or arch. All sound is synthesized after your first click; the button at the top right mutes it.

- The file is one self-contained HTML page with no network access and no storage, built from `assets/sunset-loop/`.
- `results/sunset-loop/report.en.html` and `report.zh-CN.html` hold its headless verification record (console errors, CSP violations, interaction proofs, shard count, audio state, frame rate).

## When to use

- Someone wants a "particles become things" web scene: one swarm of small pieces that flies between named forms, with an orbit camera, sound and a cinematic sky.
- You need one self-contained HTML file that runs inside a strict sandbox (no network, no storage).

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

## Inputs (slots)

Required: `theme`, `subject`, `shapes`. Optional, with defaults: `palette`, `interaction`, `sounds`, `background`, `extraPrompt`. Every value is a string of at most 2000 characters. `references/prompt-slots.md` explains each slot; `assets/prompts/examples/sunset-loop.json` is the slots file of the example.

## Workflow

```
node <skill>/scripts/fill-prompt.mjs --slots slots.json --lang en --out prompt.md
node <skill>/scripts/new-project.mjs --out my-scene
cd my-scene && 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
```

1. Fill the slots and render the meta prompt (`fill-prompt`). Give the prompt and any reference to the coding agent.
2. Start from the reference app (`new-project`). It already has the instanced shards, the GPU morph, the shape generators, the crack shader, the sunset sky, the mirror sea, synthesized sound, the `window.__scene` capture API and the single-file build. Replace the generators in `src/shapes/` and the palette for the new theme.
3. Between `dev` and `build:single`, iterate: read `references/lessons.md` before changing the shaders, and run `shoot` after each round to compare the phase screenshots with the reference.
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 `SCENE_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: the shards are instanced prisms, not a physical simulation, and the forms are sampled primitives.
- Phones run the low tier (fewer shards, no mirror pass) and are verified under headless touch emulation only, not on devices.
- `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 use other forms?** Yes: add a generator in `src/shapes/` that returns one target slot per shard, add it to `SHAPES` in `src/config.ts` and give it a chip label in `src/i18n/strings.json`.
- **Why is there no drei `Environment`?** It ships a CDN preset table; the sandbox blocks network access. `src/components/ProceduralEnv.tsx` renders the sky into the environment map 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.
