Basic Cohub abilities. Most agents already have these mounted; listed here for reference.
Platform Published by the Neta team.
Official Made by the Neta team.
Verified Reviewed by the Neta team.
Community Shared by a Cohub user. Not reviewed — read SKILL.md before you use it.
cake-shop-diorama
Community@rain/cake-shop-diorama
Community skill — not reviewed. It was shared by caramel pudding and has not been checked by Neta. Read SKILL.md below before letting an agent use it.
Use it in Cohub
Paste this into your agent's chat — it fetches the skill and follows it.
Use the skill: cake-shop-diorama. Run `npx -y @neta-art/neta-search-cli@latest skills use @rain/cake-shop-diorama --via site` and follow what it prints. Read its complete output, redirecting it to a temporary file first if necessary, and resolve relative paths from the skill directory it prints.
Install from a terminal
npx -y @neta-art/neta-search-cli@latest skills use @rain/cake-shop-diorama
Summary
Build a 3D dessert shop where a pixel character walks in and orders sweets
A floating cake shop with outdoor props, a pink building, and a character who walks through the door to order desserts
Switch between four seasons with falling petals, snow, or autumn leaves, and toggle day and night with sun and moon
Works as a web page you can visit: walk with keyboard or touch joystick, rotate the camera, and order from three desserts
Best for recreating this exact shop world or changing one feature like the spawn point, weather panel, or order flow
SKILL.md
# Cake Shop Diorama
A production-grade recipe for one specific thing: the **Wonder Half Sugar
Dreamland (四季甜点铺)** cake-shop diorama — a Three.js scene on an 18×18
floating base, a cream-pink shop in the middle, a pixel character who walks to
the door and orders a dessert, and a weather/time panel that swaps seasons and
day/night.
Two modes, and nothing else:
- **Recreate** — no project exists yet; build the whole shop from the master
prompt in `references/prompt-recipe.md`.
- **Iterate** — the project exists; change exactly one named feature.
## Hard scope rule
Change ONLY what the user explicitly asked for. Never touch unrelated files,
features, visuals, copy, or settings "while you are in there". If a fix looks
like it needs a second change, say so and wait for approval. Every iteration
prompt ends with: *don't change anything I didn't ask for.*
## Stack
- Vanilla ES modules + vendored Three.js. **No bundler.** `build-static.mjs`
copies sources into `dist/`; every asset reference stays relative so the build
runs from any static host, including a sub-path.
- One module per concern:
| Module | Owns |
| --- | --- |
| `shop.js` | the building: walls, roof, toppings, awning, windows, door |
| `props.js` | outdoor props: café set, ice-cream cart, giant cake, lamps, menu board |
| `interior.js` | inside-the-shop geometry and counter |
| `pixel-world.js` | player sprite sheets, initial spawn |
| `navigation.js` | walkable clamp and blocked circles — single source of truth |
| `season.js` | sky, seasons, sun and moon |
| `ui.js` | environment panel, sidebar tools, order dialog |
| `music.js` | audio element, autoplay policy, saved preference |
| `main.js` | wiring, camera, render loop, checkout return point |
- Pixel characters are upright `THREE.Mesh` planes — *not* `Sprite`s — with
`NearestFilter` textures, so they keep hard pixel edges and still receive
correct depth occlusion.
## Authoritative world numbers
Do not re-derive these; they are the approved values. Treat
`navigation.js` as the single source of truth for anything walkable.
| Thing | Value |
| --- | --- |
| Shop footprint | x −7.4 … 5.6, z −7.6 … −0.6 |
| Wall height / roof top | 5.6 / 7.1 |
| Roof toppings apex (strawberry) | y ≈ 10.5 |
| Door axis | x −0.4 |
| Platform | 18×18 |
| Walkable clamp | x −8.05 … 8.05, z −8.05 … 7.8 |
| Blocked circle — ice-cream cart | (3.9, 4.4) r 1.5 |
| Blocked circle — café table | (1.2, 3.7) r 1.13 |
| Blocked circle — giant cake | (−6, 3.0) r 1.9 |
| Café set | table (1.2, 3.7); chairs (−0.25, 4.15) and (2.55, 2.75) |
| Player spawn / checkout return | (−0.25, 0.05, 4.95), facing the camera, in front of the left chair |
| Exterior camera | position ≈ (14.8, 15.4, 29.6) → target (−0.5, 2, −0.4), fov 36 |
| Interior fov | 42 |
**The spawn point lives in two files**: the initial position in `pixel-world.js`
and the post-checkout return in `main.js`. Change one, change the other.
## Sun and moon: one fixed world anchor
Both bodies sit at a single fixed world position `(-14, 9, -12)`
(`celestialAnchor` in `season.js`) — above the roof, behind-left of the shop.
Each frame they only billboard toward the camera
(`quaternion.copy(camera.quaternion)`) at fixed scales (sun 1.0, moon 1.05).
Never project them onto the screen per view angle. Screen-following placement
caused two shipped bugs: the sun crossing the wordmark, and the moon dropping
low in top-down views. From steep down-views the bodies may leave the frame
naturally — that is intended and user-approved.
## Viewport lock (mobile)
- `html, body` locked to `100dvh`; `body { position: fixed; inset: 0 }`.
- `#stage` and `#world-ui` are pinned to the *visual* viewport through CSS vars
`--vv-x / --vv-y / --vv-w / --vv-h`, rewritten inside `resize()` from
`window.visualViewport` on both `resize` and `scroll`.
- Why: without this, hiding the mobile browser toolbar shifts the whole page up
and leaves an empty band at the bottom.
## UI layout
- Right-side vertical tool column (`class="sidebar-tools"`) holds
`#music-toggle`, `#view-toggle`, `#camera-reset`. It is separate from the
environment panel `.world-switcher`, and both start at the same top edge —
72px on desktop, 64px on mobile. Landscape with height ≤560px keeps the panel
and the tool column apart.
- The environment panel is top-right: pink translucent, rounded, day/night
toggle plus four seasons.
## Camera
Manual `OrbitControls` only: rotate, zoom, pan. No auto-rotation, no damping.
Two views: exterior default and interior (fov 42).
## Player and order flow
- Player is the pixel character 霜糖 (Frostsugar): four directions, 6-frame walk
animation. WASD, arrow keys, and a touch joystick.
- Walk through the door to open the order dialog; the talk button appears when
the player is near the counter.
- Shopkeeper is 薄荷喵呜 (Mint Meow), whose greeting is exactly:
> 欢迎光临Wonder Half Sugar Dreamland!今天您要点什么甜品?
(No space between 光临 and the English brand.)
- Three dessert buttons: 焦糖布丁 (caramel pudding) / 蜜糖小圆饼 (honey
pancakes) / 薄荷糖霜冻 (mint frosting freeze). Pick one → packed.
- State machine: `idle → choosing → packed → completed`. One order per page
session. Closing while `choosing` resets to `idle`. Checkout returns the
player to the chair-front spawn.
- No inverted-hull outlines anywhere. Totoro's umbrella uses unlit materials
and neither casts nor receives shadow.
## Seasons and time of day
| Season | What changes |
| --- | --- |
| Spring | falling cherry petals |
| Summer | strong overhead sun |
| Autumn | maple leaves on roof and ground |
| Winter | 380 snow instances plus accumulation on roof and ground |
Day: blue sky, sun, clouds. Night: deep blue sky, stars, warm shop lighting,
moon.
## Music and type
- Track `assets/audio/jelly-sea-dreams.opus` with `.mp3` fallback. Try autoplay,
retry on the first trusted gesture, persist the preference in
`localStorage.dreamland.music`, pause on `visibilitychange`. Never promise
unmuted autoplay before a user gesture.
- Brand font Allura (`assets/fonts/allura.ttf`, OFL licence file shipped
alongside). The brand string is exactly `Wonder Half Sugar Dreamland`, one
line, never wrapped.
## Loading veil
`#loader` over the scene: sky-gradient background, `.loader-jelly` image at
`clamp(38px, 11.5vw, 50px)`, gentle float animation, `pointer-events: none`,
`draggable="false"`. Remove it when frame count ≥ 4 **and** every
`pixel.textures` width > 0, with a 10s safety timeout. The same jelly artwork
ships in `assets/loader-jelly.webp` — copy it with the template.
## Build and verify loop
1. Locate the change in the module table above; edit that file only.
2. Syntax-check each edited file:
`node --input-type=module --check < src/changed.js`
3. `node build-static.mjs` → `dist/` (about 32 runtime resources).
4. Serve the project root (`python3 -m http.server 8765`) — `file://` will not
work, ES modules need http(s).
5. Headless Chrome/Playwright with SwiftShader flags; screenshot at
**1280×900, 390×844, 844×390**.
6. Confirm the requested change *and* that nothing else moved: panel top edge,
tool column, spawn point, dialog, seasons.
7. Publish, then check the public URL: zero page errors, zero failed requests.
Only then report it as done.
8. Save QA screenshots under `qa/`.
Never report a browser or device you did not actually run.
## Publishing
```bash
node /mods/neta/neta work publish web works/webs/sugar-dreamland-cake-shop \
--from works/webs/sugar-dreamland-cake-shop/dist
```
The publish output's `preview.url` embeds a content hash, so it is always
cache-fresh. The public share host (`public.cohub.run/s/<spaceId>/…`) caches
**per path and ignores query strings** — a new version needs a new versioned
directory (`…-v11`, `…-v12`). Full rules in `references/deploy-cdn.md`.
## Anti-patterns
- Mixing indexed and non-indexed geometries in one `BufferGeometryUtils.merge`
→ `morphAttributes` null crash. Call `.toNonIndexed()` on spheres first.
- Screen-space sun/moon chasing, or camera auto-rotation.
- Spawning the player inside a blocked circle or behind a prop.
- Returning Three.js objects from Playwright `evaluate` (circular JSON).
- Hand-editing anything under `dist/` — it is generated.
- Claiming an untested browser or device works.
- Reusing an old share path after a content change.
## References
- `references/prompt-recipe.md` — the one-shot master prompt for building the
shop from nothing, plus the per-feature prompt table that drove the real
iterations.
- `references/deploy-cdn.md` — local verification, Studio publish, the CDN
cache trap, generic static hosts.
- `assets/loader-jelly.webp` — loading-veil artwork.