Tiny Planet
Built in one 25-minute session: grow bare rock into a city planet whose lights switch on at night, with seasons, a meteor, a volcano, a second planet and a rocket to the moon. Estimated cost from tokens.
The prompt
Build "Tiny Planet", a playable miniature world: a small round planet floating in space that the player grows from bare rock into a living, glowing city planet, as ONE self-contained HTML file. It must be **beautiful above everything**, like a premium animated film: soft, toy-like, rounded and warm, with great animation on everything that moves. Nothing ever pops, snaps or teleports: things grow, ease, overshoot a little and settle. It should be calm and satisfying to play, and spectacular to watch. ## Tech * three.js r170 with WebGPURenderer (automatic WebGL2 fallback). Load it with an importmap from jsDelivr: map "three", "three/webgpu" and "three/tsl" to `three@0.170.0/build/three.webgpu.min.js`, and "three/addons/" to `three@0.170.0/examples/jsm/`. * Use TSL node materials (MeshStandardNodeMaterial, MeshPhysicalNodeMaterial for water and atmosphere, MeshBasicNodeMaterial, SpriteNodeMaterial), OrbitControls from the addons, and a subtle BloomNode pass (strength ~0.4, threshold ~1.5) so only the sun, city lights, lava, the rocket flame and meteors glow. * No external assets. Every texture is drawn on a canvas or generated as pixel data at startup. Every sound is synthesized with WebAudio. The only network requests are three.js from jsDelivr and the Fredoka font from Google Fonts; if the font fails to load, fall back to a system rounded sans-serif without breaking anything. * Start the HTML with `<!doctype html>` and `<meta charset="utf-8">`. * It must run inside a sandboxed iframe (`sandbox="allow-scripts allow-pointer-lock"`, no `allow-same-origin`). There, `localStorage` and cookies throw a SecurityError: wrap every storage access in `try/catch` and keep values in memory instead. Do not use `alert`, pop-ups or top-level navigation. * Neutral tone mapping, soft 2048 shadow map. * Note: in three r170's WebGPURenderer the scene background is drawn after transparent objects, so transparent sky objects (atmosphere glow, nebula, aurora-like effects) need `depthWrite: true` or they disappear. Use DataTexture (raw RGBA) rather than cloned CanvasTextures for anything you clone. * The simulation runs on a fixed 60 Hz timestep and is frame-rate independent. At low frame rates, drop simulation time instead of exploding. * A quality scaler lowers the pixel ratio, then particle counts, when frames get slow. * Respect prefers-reduced-motion: softer shake, slower camera and spin. ## Priorities Build in this order and finish each tier properly before the next. A polished tier 1 beats a broken everything. 1. **Must be excellent:** the planet itself (terrain, water, atmosphere, day/night terminator), spinning it with momentum, the tools that shape it (Water, Raise/Lower, Plant, Rain), green spreading, the night side with city lights, the demo mode. 2. **Must work:** the people and the growth from village to city, the stage progress and milestones, the meteor, seasons, the moon, sound, the card UI, camera. 3. **Polish:** volcano, tornado, ice age, animals, birds, clouds with shadows, the rocket Easter egg, the second planet and the bridge of light. Never ship a feature half-working: if a tier-3 feature can't be done well, leave it out cleanly. ## The scene * **Space:** a deep blue-violet backdrop (gradient #1a2350 at the top to #07091a at the bottom) with a few hundred stars of different sizes that twinkle softly, a faint pastel nebula band (pink and teal), and a slow parallax when the camera turns. * **The sun:** a warm glowing sphere off to the upper left (emissive, with a soft corona and bloom). It is the only key light: a strong warm directional light from its direction plus a faint cool ambient, so the planet has a clear **day side and night side** with a soft, slightly orange **terminator** line between them. * **The planet:** radius 1 (about 60% of the frame height at the default view), floating in the centre, tilted 20° on its axis, spinning slowly on its own (one turn per ~90 s) unless the player spins it. * **The atmosphere:** a thin glowing shell slightly larger than the planet (Fresnel rim glow, light blue on the day side, warm orange near the terminator, faint on the night side). * **The moon:** a small grey cratered sphere on a tilted orbit (one orbit per ~60 s), casting a small shadow on the planet when it passes in front of the sun. * **A thin glass orbit ring** around the planet's equator at 1.6× radius, very subtle, like the glass of the other dioramas (it is the "frame" of this world). ## The planet surface * **Geometry:** a subdivided icosphere (about 40k triangles on desktop, 20k on phones, 12k in demo mode) whose vertices are displaced by a **height field stored per vertex**. Keep a vertex adjacency list so tools and spreading can run on the sphere directly. * **Per-vertex state:** height (sea floor to mountain top), water depth, moisture, vegetation (0 bare rock → grass → bushes → forest), temperature (from latitude, height and season), snow, burn/scorch, and a building/zone id. * **Starting state (seed 0001 default):** bare grey-brown rock with gentle noise relief, a few dry basins, two small shallow lakes, no plants, no people. "New planet" makes a random seed with different relief. * **Colouring** (computed per vertex, smoothly blended, with procedural noise so it never looks flat): * bare rock: warm grey-brown with darker cracks; * sand/shore near water; * grass: fresh green, more saturated with moisture, yellowing when dry; * forest: deep green, slightly bumpy; * snow on high peaks and cold latitudes (more in winter); * scorched black after fire or meteor, slowly recovering. * **Water:** a separate sphere-shaped surface at sea level, shown only where water depth > 0 (or a shader that reads water depth): transparent, turquoise in the shallows to deep blue, Fresnel reflection of the sky, a sharp sun glint, animated small ripples, white foam along shores. * **Trees and plants:** instanced meshes (cone or round-canopy trees, bushes, grass tufts, flowers in spring) placed on vertices with vegetation, scaled by growth, swaying gently, all aligned to the planet's surface normal. Up to ~4000 trees on desktop. * Everything placed on the surface (trees, houses, people, animals) must stand along the surface normal and follow the terrain height. ## Simulation (runs on the sphere) * **Water flow:** water moves downhill between neighbouring vertices, fills basins into lakes and seas, evaporates slowly in the heat, and is refilled by rain. Seas settle flat at a common level. * **Moisture:** spreads from water and rain to nearby land and dries over time. * **Plant growth:** vegetation grows where moisture and temperature are right (not on snow, not underwater, not on scorched ground), and **spreads on its own** to neighbouring vertices, so green creeps out from lakes and rivers in visible fronts. Forests take time to become forests. * **Seasons:** a **Season** cycle (spring → summer → autumn → winter, about 2 minutes each, or set by a slider) changes temperature and colours: spring flowers dot the grass, summer is lush, **autumn turns forests orange and red** with falling leaves, **winter brings snow** down from the poles and freezes small lakes; it melts back in spring. The hemisphere tilt makes seasons opposite in north and south. * **People and settlements:** * A house placed with the Life tool spawns 2–3 tiny people. * People wander, fish at lakes, gather near trees, and **build new houses** on flat green land near water and trees. Settlements grow in stages: **village** (houses) → **town** (roads between houses, a small tower, a harbour if there is a sea) → **city** (taller buildings, a glowing centre, bridges over rivers). * Roads are drawn on the surface as soft lines between neighbouring buildings. * At night, windows and streetlights light up (warm yellow emissive), so the **night side of the planet sparkles with city lights**. Lights switch on gradually as each spot crosses the terminator into night. * People are cute and readable at close zoom: small rounded figures with a coloured body and a head, walking with a little bob, waving at the camera when zoomed in near them. * **Life progress:** a stage meter: **Rock → Water → Green → Village → Town → City**, computed from water coverage, green coverage, number of buildings and population. Show population as a number. * **Animals (tier 3):** deer in forests (instanced, grazing and hopping), fish jumping in seas, and a **flock of birds** that flies around the planet in a loose V. * **Clouds:** a cloud layer slightly above the surface: soft puffy clouds (sprite clusters or noise on a shell), drifting with a gentle wind, casting soft shadows on the surface, thicker where it rains. ## Tools (card, keys 1–6) * **Spin (default):** drag to spin the planet; it keeps spinning with momentum and slowly settles back to its idle spin. A quick tap on the surface shows a small ripple of light and, if zoomed in, makes nearby people wave. * **Water:** tap or hold to pour water at that spot; it spreads into low ground and fills lakes. A soft splash ring. * **Shape:** drag to **raise** land (mountains push up, with a little dust); hold Shift (or toggle Raise/Lower in the card) to **lower** and dig valleys. Water reacts immediately. * **Plant:** tap to plant; a patch of grass sprouts with a little burst of leaves, then grows on its own. Hold to plant a small forest. * **Rain:** a small cloud follows the pointer and rains where you hold: drops, puddles, faster growth, rising lakes, and a **rainbow** arcs over the spot when it stops raining in sunlight. * **Life:** tap green land to place a house (it rises from the ground with a bounce); people pop out and start living. Tapping water near a town places a small boat. * A press that ends within 6 px and 450 ms counts as a tap. Dragging with Spin rotates the planet; dragging with other tools paints; right-drag or two fingers always orbit the camera. ## Events (card buttons and keys) * **Meteor (M is mute, so use `T` for meteor):** a glowing meteor streaks in from space toward the tapped spot (or a random spot), with a fiery trail; on impact a flash, a **crater** carved into the height field, a shockwave ring that ripples across the surface, a dust ring, scorched ground, and a short camera shake. People run away from the impact and later rebuild. Never kills anyone. * **Volcano (`V`):** a mountain at a random high spot (or the tapped spot) erupts: glowing lava flows downhill on the height field, cools into new dark land, smoke rises; plants regrow on it later. * **Tornado (`G`):** a swirling funnel crosses the land for ~8 s, lifting leaves and a few trees, then fizzles out. * **Ice age (slider "Climate", cold ↔ warm):** cold pushes snow and ice from the poles toward the equator and freezes seas; warm melts it back and grows deserts at the equator if very hot. ## The second planet and the bridge (tier 3) * When the first planet reaches **Town**, a **second, smaller planet** drifts into view on a wide orbit (bare rock, different colours: reddish desert). * The player can shape and grow it with the same tools (tap it to switch focus; the camera eases over). * When both planets have a town, a **bridge of light** (a glowing arc of tiny moving lights) forms between them, and little ships fly along it. ## Easter egg * When the first planet reaches **City**, a tiny **rocket** launches from the city with a flame and smoke trail, circles the planet once, flies to the moon and lands with a little puff; a tiny flag pops up. Toast: "One small step." Never hint at it before. ## Milestones (toasts, once each) "First lake", "First rain", "First forest", "First village", "Lights at night", "First autumn", "Survived a meteor", "Town", "City planet", "Two worlds" (bridge built), and the rocket. ## Camera Same family as the other worlds: * OrbitControls with damping and zoom to cursor, orbiting the camera around the planet (separate from spinning the planet itself). * Zoom from the full view (planet, moon and sun in frame) down to a close-up where the people are clearly visible on the surface, without clipping into the ground (the minimum distance follows the terrain height under the camera). * **Follow:** double-click a person, a boat, a bird flock or the rocket to follow it; Esc or 0 stops. * Camera bar (floating pill, bottom right of the scene area): zoom −, a zoom % readout, zoom +, rotate left, rotate right, reset. * Keys: arrows orbit, + and − zoom, 0 resets the view. * The default framing fits the planet and its moon orbit into the free area, accounting for the card and title, with the sun just in frame at the upper left and the terminator crossing the planet (so both day and night show). * **Cinema (`C`):** hides all UI and slowly orbits the camera while the planet spins. ## Interface A light, playful UI that never covers the planet. On phones the card becomes a compact bottom sheet. * Top left: * small caps "POKEABLE · WORLD"; * a big chunky rounded heading on two lines, "Tiny" / "Planet", in Fredoka from Google Fonts, light-coloured on the dark space background, with a tiny orbiting dot circling the "o"; * caption "Grow a world. Watch the lights come on." * Top right: a live status dot with "WEBGPU · LIVE" (or "WEBGL2 · LIVE"), a speaker pill button (ON / MUTED), and "PAUSED" when paused. * Right card "Planet": about 240 px wide, off-white, 20 px corners, soft shadow, no hairlines, warm sunset-orange accent (#f08a4b), collapsible to a small pill. Contents: * the **stage meter**: six small icons (Rock, Water, Green, Village, Town, City) with the current one highlighted and a progress bar to the next; **Population** as a big rolling number; water % and green %; * tool picker: Spin, Water, Shape (with a Raise/Lower toggle), Plant, Rain, Life, each with a drawn icon and its key number; * event buttons: Meteor, Volcano, Tornado; * sliders with monospace value chips: Spin speed, Season (auto / fixed season), Climate (cold ↔ warm), Sound (master volume); * switches: Clouds (on), Animals (on), Second planet (on once unlocked), Slow motion (¼ speed), Cinema; * buttons New planet and Reset planet, a dark full-width Pause/Resume pill, and the planet's name "Planet No. 0001". * Bottom left: a one-line hint that changes with the tool: * Spin: "Drag to spin. Spin into night to see the lights." * Water: "Tap to pour water. It finds the low ground." * Shape: "Drag to raise mountains. Shift to dig." * Plant: "Tap to plant. Hold for a forest." * Rain: "Hold to rain. Stop in the sun for a rainbow." * Life: "Tap green land to build a house." * Bottom right: a collapsible "How it works" panel, 5–6 plain lines covering the sphere height field, water flowing downhill, plants spreading with moisture, how towns grow, seasons, the camera controls, and synthesized sound. * Toasts at the top centre for milestones and events. * Other keys: 1–6 tools, T meteor, V volcano, G tornado, Space pause, R reset, N new planet, M mute, S slow motion, C cinema, K clouds, A animals. ## Sound * WebAudio only. Create the AudioContext on the first gesture and never before. * Master gain feeds a compressor, so rapid actions never clip. Limit voices (about 16) and wrap every call in try/catch so a failing audio call never breaks the world. * Loops: a soft, warm **space pad** (slowly moving chords), a gentle wind that rises with clouds and the tornado, rain when it rains, birdsong on the day side and crickets on the night side when zoomed in, a faint city hum that grows with population. * One-shots: * spin: a soft airy whoosh scaled by spin speed; * water: pouring trickle, splash ring; * shape: a low earthy rumble while raising or digging; * plant: a soft pop and a rising "grow" tone, pitched differently each time; * life: a little wooden knock when a house rises, tiny cheerful chirps from people; * stages and milestones: a short warm chime (higher for each stage); * meteor: a rising whistle, a deep boom, a rolling rumble; * volcano: rumble, pops and sizzle; tornado: a swirling howl; * rocket: ignition roar, then a distant whoosh, and a tiny "ding" when the flag pops on the moon. ## Demo mode (required) If the URL has `?demo=1` (or `#demo`), auto-play a deterministic 4.0 s loop: * Rules: * Hide all UI and the cursor; never create an AudioContext. * Fixed quality, default seed, a **pre-grown planet** (green continents, seas, three towns, forests, clouds) so the clip is beautiful from the first frame; default camera, no OrbitControls. * Drive the simulation from real elapsed time with the fixed timestep, and restart from the identical state every 4.0 s. * Start moving within 1 s of load, and stay readable at 15 fps. * Timeline: * 0.0–1.6 s: the planet spins slowly from the day side towards night; clouds drift; a bird flock crosses. * 1.6–2.6 s: the night side rotates into view and the city lights switch on, spot by spot, across a town. * 2.6–3.2 s: a meteor streaks in and hits an empty plain on the day edge: flash, shockwave ring, small crater, dust. * 3.2–4.0 s: the dust settles, the lights twinkle, the planet keeps spinning. ## Before you finish, check * Spinning with momentum feels smooth and natural on mouse and touch; the camera orbit and the planet spin never fight each other. * Water flows downhill and fills basins; raising and digging reshapes it live; plants spread from water in visible fronts; rain grows things and makes rainbows. * Growth from Rock to City works in normal play within about 10 minutes; houses, roads, harbours and bridges appear in sensible places; people never float or sink. * Night side lights switch on and off across the terminator. * Seasons cycle with spring flowers, autumn colours and winter snow; the climate slider makes an ice age and a warm desert. * Meteor, volcano and tornado all work repeatedly without breaking the terrain; people always survive and rebuild. * The second planet and the bridge of light; the rocket to the moon. * Every tool, slider, switch, button and key; follow mode; Cinema; pause and resume; resizing to phone width. * Sound behaviour. * It works inside `<iframe sandbox="allow-scripts allow-pointer-lock">` with no errors (storage blocked). * `?demo=1` matches the timeline. * No console or WebGPU validation errors, and it stays smooth on a mid-range laptop. Put the beauty of the planet and the moment the city lights come on at night first. It should feel like holding a tiny living world in your hands.