Jelly Ghost

jellyghost

OpusAstra
Opus$18.19 · 1h11m40s
Claude Opus 5.5$18.19 · 1h11m40s
Claude Opus 5.5 $18.19 · 1h11m40s
Winner
Astra$7.84 · 20m00s
ChatGPT-6 Astra$7.84 · 20m00s
ChatGPT-6 Astra $7.84 · 20m00s
CheapestFastest

Opus wins. Opus's ghost is the one you'd screenshot: clear glowing jelly you can see the candles through, big glossy eyes and a proper open-mouthed BOO; Astra's mint ghost was ready in 20 minutes for less than half the price, but its jelly looks matte and it barely glows when the lights go out.

Remix in Claude

Scorecard

Opus4Astra2

CriterionOpusAstra
Jelly lookTranslucent and glossy, the scene shows through it, backlit edges glowMatte mint jelly, reads more like soft clay
CharacterRound ghost with stubby arms, rosy cheeks, big shiny eyesCute blob ghost with a smile, a little too big for the frame
Lights offCandles go out and the ghost glows a little brighterCandles go out, the ghost doesn't light up
BooPuffs up, big O mouth, light ring, candles blown sidewaysPuffs up with eyes shut, smaller payoff
DemoA tool hint stays visible in the demo loopClean demo with no UI
Size197 KB43 KB, one full-screen ray-marched shader
Cost$18.19$7.84
Time1h11m40s20m00s
OverallWinner–

The prompt

Build **"Jelly Ghost"**: a real-time, interactive 3D **cute ghost made of glowing translucent jelly**, floating over a cozy Halloween table at night. People **poke** it, **stretch** it, **pick it up**, **shake** it, turn the **lights off** so it glows, and hold **Boo** so it puffs up and spooks the candles, with **synthesised sound**, as ONE self-contained HTML file rendered with **WebGPU (WGSL)** and an automatic **WebGL2** fallback.

**This is part of a series called Jelly Monsters, and the most important thing is that it looks stunning.** Every frame should look like a high-end product photo of a gummy candy character: glowing, glossy, wobbly, adorable. Someone scrolling past a still frame should stop and want to touch it. Spend your effort on the look and the jelly feel first, features second.

## Priorities

Build it in this order, and finish each tier properly before starting the next. A polished tier 1 beats a broken everything.

1. **Must be stunning:** the character (cute, readable, plush-toy proportions), the glowing jelly material, the night table scene and its lighting, the wobble, the base interactions (Poke, Stretch, Grab, idle life), the demo mode.
2. **Must work:** the special trick (Lights and Boo), colour flavours, Shake, Reset, sound, both renderers, the control card, the secret.
3. **Polish:** soft fog near the table, candle flicker reflected in the jelly, slow motion, Cinema mode extras.

Never ship a feature half-working: if something from tier 3 can't be done well, leave it out cleanly.

## Deliverable

- One self-contained `.html` file with all JavaScript, WGSL, GLSL and CSS inline. Start it with `<!doctype html>`, `<meta charset="utf-8">` and a viewport meta.
- **No external requests of any kind**: no libraries, CDNs, web fonts, images, textures or audio files. Generate everything procedurally in code (sound included). Use system font stacks.
- It must run inside a sandboxed iframe (`sandbox="allow-scripts allow-pointer-lock"`). Do not use `localStorage`, cookies, `alert`, pop-ups or top-level navigation, and wrap any storage access in `try/catch`.
- This must be a live simulation, not a video, a pre-baked animation or a 2D fake.
- **Test hook:** if the URL has `?test=1`, expose `window.__toy` (no visible change) with `setTool(name)`, `poke(x, y, strength)`, `drag(x0, y0, x1, y1, ms)` (through the same code path as a real pointer drag with the current tool, in canvas pixels), `shake()`, `reset()`, `set(name, value)` for every slider, switch and flavour, the special-trick calls listed below, and `state()` returning `{ backend, tool, mode, volume, kinetic, busy, fps }` plus the special-trick fields listed below.

## The series look (same for every Jelly Monster)

**Character style**
- **A plush toy made of gummy candy.** Chunky, round, soft proportions: a big body, a big head (or one shape that is both), short stubby limbs if any. Nothing thin, spiky, sharp or realistic. No teeth beyond one tiny cute fang if the monster needs it.
- **Big glossy eyes** (each about a quarter of the face's width), glossy near-black candy with **one big soft white highlight** high up and a small second one, always visible whatever the lighting. Eyes **blink** now and then and **follow the pointer**. A **tiny smile**.
- **One or two strong colours** per flavour, plus a lighter face area. It must read at a glance as what it is (here: a ghost) from its silhouette alone.
- **Every part is attached to the body.** Nothing hovers or floats detached around the character (the ghost itself floats, but all its parts belong to it).

**The jelly**
- **Translucent all the way through**, never plastic: colour comes from absorption through the volume (Beer-Lambert), deep where it is thick and pale and bright at thin edges; the background is visible through it, bent by refraction (IOR about 1.35, like water). Small sharp wet highlights with a strong Fresnel sheen at grazing angles; no broad plastic clearcoat; tiny suspended air bubbles at different depths; faint internal grain.
- **It glows when backlit.** The moonlight from behind makes its edges and thin parts glow in its own colour. This is the signature look of the series.
- **It moves like jelly:** slow heavy jiggle (2 to 4 Hz), the top lags behind the base, it keeps its volume (squashed it bulges, pulled it thins), squashy dead bounces, never a rubbery boing.

**The scene**
- **A cozy Halloween tabletop at night**: a dark warm wooden table, three church candles of different heights on the left and back (real flickering flames, warm light that moves), a large window behind with a big pale moon and a deep blue-violet night sky, a little soft fog near the table surface. Two or three tiny props at the edges (a small pumpkin, scattered candy corn) that never compete with the character.
- **Lighting:** warm flickering candle key from the front-left, cool strong moon rim light from behind so the jelly glows at its edges, soft coloured shadows and a coloured light patch on the table where light passes through the jelly. Filmic tone mapping, gentle bloom on the candle flames and the jelly's highlights, a soft vignette.
- **Camera:** a slightly low three-quarter front view, close, like a food photo: the character fills about 55% of a square frame and looks into the camera. Orbit and zoom within limits; **no automatic follow cam that drifts**. The UI never covers the character on desktop.

## The monster (this monster)

- **A ghost**: one soft rounded teardrop of jelly, like a sheet ghost but made of gummy: a round dome head flowing into a wider wavy skirt that ends in **three or four soft rounded scallops** (the tail), with **two tiny stubby arms** on the sides. It **floats** about a head-height above the table, bobbing slowly, its skirt rippling, with a soft round glowing shadow on the table under it.
- **Face:** the series eyes and a small "o" mouth (it becomes a big "O" for Boo). Faint rosy cheeks.
- **The glow:** the ghost is lit **from inside** by a soft pale light, strongest in the middle of the body, so it reads as a glowing ghost even in a dark room.
- **Flavours** (round swatches): **Milk** (default: milky white-blue jelly, glows pale cyan), **Lime** (glow-stick green), **Grape** (violet), **Peach** (warm pink-orange), **Midnight** (deep indigo with tiny glittering stars inside).

## Base interactions (same for every Jelly Monster)

A tool picker with **Poke**, **Stretch** and **Grab**. The default tool is Poke. A press that ends within 6 px and 450 ms counts as a tap. Right-drag or two fingers orbit the camera with any tool. Pointer events with **pointer capture**, mouse, pen and touch.

- **Poke:** a tap presses a deep rounded dent that springs back with a wobble rippling over the whole body; it **flinches** (eyes squeeze shut, body ducks), then shakes it off. Holding presses deeper and the jelly bulges around the finger. Poked many times in a row, it gets a little grumpy (frowns, turns away), then forgives you.
- **Stretch:** grab any point and pull: the jelly stretches out locally like taffy, thinning near the finger and bulging back at the body, and on release **snaps back** with a big satisfying wobble. Never tears, never moves the whole body rigidly. The further you pull, the bigger the snap.
- **Grab:** pick the whole monster up by the point you grabbed; it dangles and sways with weight, its eyes go wide; release to drop it (a squashy splat and wobble), or release during a fast drag to toss it a little way. It always ends up back in its spot, happy.
- **Shake** (button and `S`): the whole monster jiggles hard for a second like a plate of jelly being shaken, then settles.
- **Idle life:** it breathes, blinks, follows the pointer with its eyes and body, and every few seconds does a small cute idle animation of its own. Never perfectly frozen.
- **Reset** (`R`): back to its spot, settled.
- **Physics:** a volumetric soft body (a lattice of about 500 to 1,500 cells, XPBD or shape matching with volume preservation) skinned to a smooth high-resolution surface, with a fixed timestep (about 1/120 s) and bounded substeps. Deformation clamped so it always reads as itself; back to exact rest within 2 to 3 seconds; no jitter at rest, no explosions, no creep, nothing passing through the table.

## Special trick (this monster)

- **Lights** (switch, `L`): blows the candles out and the room goes dark blue: the moon still rims everything, and the ghost **glows much brighter** from inside, lighting the table and the props around it in its flavour colour (a soft moving pool of light under it). Turning the lights back on relights the candles one by one.
- **Boo** (button, or press and hold `B`): the ghost takes a breath and **puffs up** (about 30% bigger, jelly stretching thin and glowing brighter) while you hold, its eyes squeezed shut, then on release goes **"BOO!"**: it pops back to size with a big wobble, its mouth a big O, a soft shock-ring of light and air spreads over the table and **blows the candle flames sideways** (a bigger Boo can blow them out), and the props hop. Then it giggles (a quick happy wiggle).
- **It is ticklish:** poking it from below (its skirt) makes it giggle and spin once instead of flinching.
- **Test hook:** `lights(on)`, `boo(holdSeconds)`; `state()` adds `lightsOn` and `puff` (0 to 1).

## Secret (this monster)

- If the lights are off and nobody touches anything for **20 seconds**, the ghost gets lonely: it floats to the window, presses its face against the glass (squishing flat), and **two tiny baby ghosts** (little copies in other flavours) float in from the night outside and join it. They bob around it in a little circle until the user touches anything, then wave and fade out through the window. A small badge: "It just wanted company." Never hint at it in the UI.

## Sound

Every action has a **synthesised sound**, generated live with the **Web Audio API** (oscillators, filtered noise, envelopes). **No audio files, no samples.** Soft, cute, wet: squishes, bloops and creaks for the jelly; a short squeak for the flinch; a rising wet stretch and a satisfying snap-back bloop for Stretch; a splat for a drop; a jiggly rattle for Shake; and for this monster: an airy inhale while Boo builds, a cute "boo" (a formant-filtered tone sliding down), candle whooshes, a soft hum when the lights go out and a giggle.

Rules: create the `AudioContext` only on the first user gesture and never before; resume a `suspended` context on interaction; master gain into a compressor, no clipping; cap at about 16 voices; wrap every audio call in `try/catch`. Sound on by default; a **speaker button** and `M` mute it.

## Rendering (WebGPU with a WebGL2 fallback)

**WebGPU (WGSL) when available, with an automatic WebGL2 fallback that looks the same.** Detect at start; if WebGPU is missing, or adapter or device creation fails, use WebGL2. **If the WebGPU device is lost at any time (`device.lost`), switch to WebGL2 on the spot and keep rendering**: the toy must never end up on a blank screen. No libraries: write both paths yourself, sharing the scene data and the simulation. Show which one runs in the status pill.

- **Jelly:** back faces into a thickness buffer, then front faces, absorption from the distance light travels through the jelly, screen-space refraction of the scene behind (IOR about 1.35, offset scaled by thickness), a wrap-around subsurface term for the backlit glow, wet specular with Schlick Fresnel and a tight highlight, internal grain and bubbles. Opaque shading with an alpha value is not acceptable.
- **Eyes:** glossy dark candy domes with the white highlight painted in plus a real specular glint, so they always read as big cute eyes.
- **Scene:** candle flames as flickering additive sprites with a warm point light each; the moon as a soft disc with a rim light; soft shadows; table wood grain procedural; fog as a few soft sprites near the table.
- Preallocate all buffers and build every pipeline at start; never create shaders, pipelines or geometry during interaction. DPR capped at 2. An automatic **quality scaler** lowers resolution and bloom before it ever touches the jelly feel. It must stay smooth on a mid-range phone.
- Only if neither WebGPU nor WebGL2 exists, show a clear, well-designed message.

## Interface

A dark, cozy interface that stays out of the way; the monster is the hero and UI never covers it.

**Top left:** small caps `POKEABLE · JELLY MONSTERS 2 / 15`, a large italic serif heading on two lines: *Jelly* / *Ghost.*, and caption lines "Poke it." / "Stretch it." / "Turn the lights off."

**Top right:** a live status dot with `WEBGPU · LIVE` or `WEBGL2 · LIVE`, a **speaker icon button** (`ON` / `MUTED`), and `PAUSED` when paused.

**Right panel: control card "Ghost"**, a floating card about 240px wide with 20px corners, dark charcoal with a hint of violet, soft shadow, no hairlines, plain system sans, bold sentence-case labels, and an accent colour taken from the active flavour's glow. Tools as rounded tiles with small drawn icons and key numbers (`1` Poke, `2` Stretch, `3` Grab), the special-trick controls as big accent buttons (**Boo**) and a switch (**Lights**), **Shake** and **Reset** as chips, flavours as round swatches, sliders for **Softness**, **Wobble** and **Sound** (6px rounded track, round white thumb, monospace value chips), switches for **Slow motion** and **Cinema**, and **Pause / Resume** as a full-width pill. Collapsible to a small button; a bottom sheet on narrow screens.

**Bottom left:** a one-line hint per tool ("Tap to poke. Hold to squish.", "Grab and pull. Let go to snap it back.", "Pick it up. Let go to drop it.").

**Cinema** (`C`) hides all UI and the cursor; a tap without drag, `C` or Esc brings it back. Respect `prefers-reduced-motion` for UI transitions and camera moves; the jelly still responds fully. Keys: `1` to `3` tools, `S` Shake, `L` Lights, hold `B` Boo, `P` next flavour, `C` Cinema, `M` mute, Space pause, `R` reset, `0` reset view.

## Demo mode (required)

If the URL has `?demo=1`, auto-play a 4-second loop with no user input: the object drops in, wobbles, gets poked or sliced once, then settles.

For this toy that means:
- **Hide all UI** and the cursor. One fixed quality preset (no quality scaler), the default flavour, lights **off** from 1.6 s, the fixed default camera.
- **Never create an `AudioContext`**, play nothing.
- Deterministic, no randomness; restart every 4.0 s of real time from the identical state; drive the simulation from real elapsed time with the fixed timestep so the loop lasts 4 s at any frame rate.
- Timeline:
  - **0.0 to 0.7 s:** the ghost drifts down into its spot from above, bobs and wobbles, candles lit.
  - **0.9 s:** a poke dents its body: it flinches and ripples.
  - **1.3 to 1.9 s:** an invisible hand stretches its tail out to the side and lets go: it snaps back with a big wobble.
  - **1.6 s:** the candles go out, the ghost glows brighter and lights the table.
  - **2.2 to 3.2 s:** Boo: it puffs up glowing, then pops back with its mouth in a big O, the light ring spreads and the props hop. The most striking moment.
  - **3.2 to 4.0 s:** the candles relight one by one and it settles into the exact pose of 0.0 s.
- Start moving within 1 s. It is recorded in a slow software renderer: **the glow, the stretch and the Boo must read clearly at 15 fps**.
- Support `?demo=1&t=<seconds>` to freeze the demo at that time (for screenshots).

## Before you finish

Self-check against this list and fix anything that fails:
- **The scroll-stop test:** take still frames at rest, mid-stretch, mid-Boo, lights on and lights off, in every flavour. Each must look like a premium photo of a glowing gummy candy character: cute, glossy, translucent, backlit, with readable eyes. If any frame looks like plastic, glass, a flat cartoon or something creepy, fix the look before anything else.
- **The cute test:** from the default view it reads instantly as a friendly ghost with big shiny eyes; nothing sharp, nothing detached floating around it.
- Poke every part 50 times fast, stretch from every side as far as possible, grab and toss it, shake it, Boo while stretching, switch flavours mid-wobble: never an inverted or exploded body, jitter at rest, a part through the table or a crash.
- Every tool, button, switch, slider and key; pause and resume; Slow motion; Cinema; resizing to phone width with touch.
- The secret by hand.
- Sound: every action has its effect, nothing before the first gesture, mute works, no clipping.
- `?demo=1` matches the timeline, loops cleanly, shows no UI and plays no sound; `?demo=1&t=2.9` freezes mid-Boo.
- No console errors or WebGPU validation errors on WebGPU AND on the WebGL2 path, the device-lost fallback works (simulate it with `device.destroy()`), and it stays smooth on a mid-range phone.

Make it the most beautiful jelly toy you can. It should be the ghost people screenshot before they even poke it.

More like this