← Back to the lab

How I built this

The home page is a small room on a hill, and a meadow round it that anyone can build a village in. It's one Blender scene with baked light, drawn by Three.js inside a Next.js app, and a lot of small systems that react to each other. I built it alongside Claude Code. Here's what's going on underneath.

The room, lit once in Blender

Everything in the room is modelled by a Python script that runs inside Blender, so the whole diorama can be rebuilt from scratch with one command. Cycles then bakes the light twice, once for night and once for day, into the vertex colours of every object.

The browser never computes any of that light. It reads the baked colour, multiplies it by each object's flat colour, and eases between the night and day sets. That's why a phone can show a room with soft bounce light and warm lamp pools.

The scientist's room at night: bookshelf, chalkboard, telescope, a desk with a monitor and a sleeping cat.
about 40 minutes of baking for both lighting sets
  • Blender 5.1
  • Cycles
  • Draco-compressed GLB

A softer finish

On top of the baked light, a finishing pass does the things that make it feel like a toy on a table: soft contact shadows where objects meet, thin pencil lines on the edges, a glow round anything bright, and a tilt-shift blur above and below whatever you're looking at.

It all runs in a few small render targets after the scene is drawn. The lines fade as you pull the camera back, so the whole map stays clean instead of turning into scribble.

  • Three.js
  • custom GLSL
  • half-float render targets

A meadow you can build on

Outside the room is a meadow in the spirit of Tiny Glade. You draw and the pieces work out the rest: close a loop of wall and it becomes a building, and a path through a fence opens a gate. Run a path into a house and it gets a door; cross a stream or pond and you get a bridge.

Unlike the room, built things get real light: the sun or moon with soft shadows, and after dark every street lamp and lantern lights the houses and the grass around it. Surprise me grows a whole village in one of seven layouts.

A cottage on a hill, a hedge, a market stall, a fountain, a bench, a garden arch and a windmill beside a stream and a path.
everything here is generated from a few strokes
  • procedural geometry
  • VSM shadows
  • per-lamp lighting

People, animals and a clock

Every house brings someone to live in it, and every other house brings a kid. They walk the paths and pet the dogs, and the kids chase the calves. At night they go home and the windows light up one by one. Otters swim in the ponds. Everyone has a name and a job, and clicking someone starts a little conversation.

Day and night come round every 20 minutes: ten minutes of day, a warm sunset, seven minutes of night and a sunrise. Birds cross the sky in the daytime and butterflies find the flowers in spring. Now and then someone wishes for something, a bench or a pond, and building it makes their day.

They have lives of their own, too. The baker keeps a smoking bread oven by the market stall, fishers fish, kids fly kites on the hills, and when it snows everyone builds snowmen. When night falls, the lamplighter walks round lighting the street lamps one by one, and the village gathers at the fountain. Villagers who chat on a bench become friends and visit each other, and you can ask them for things: the baker will bake you a loaf and bring it over.

You can also step in as a little person of your own and walk the village at their height. Paths lead you through gates, over bridges and through gaps in hedges, and walking into a front door takes you inside, where whoever lives there is pottering by the table. Footsteps change on paths, and the village murmurs louder where more people are.

A village at night seen from above: lit windows, street lamps along stone paths, a frozen pond with a bridge.
  • simple steering
  • hit proxies for clicks
  • third-person camera

Snow and rain

Snow and rain fall on the GPU inside a box that follows the camera, so there are thousands of flakes at almost no cost. The shaders read the season: snow settles on whatever faces up, ponds freeze, and snowmen appear by the cottages. When it rains, the ground darkens, puddles collect along the paths and umbrellas open.

The room on its hill at night in winter, snow settled on the tiers and falling in front of a sleepy moon.
  • GPU particles
  • shader-driven snow cover

Villages other people made

A village can be shared as a link, with the whole thing compressed into the URL. It can also be published with a name, a thumbnail and likes. A small API on Vercel keeps them in Redis. Visitors are only known by a salted hash, owner codes are stored as hashes, and every village is unpacked and checked before it's kept. There's a report button, and a word filter on names.

There's also one shared village that everyone builds together, one piece each a day, and a guestbook on a signpost by the cherry tree. The counter in the corner is the time everyone has spent here, added together.

  • Next.js route handlers
  • Upstash Redis
  • rate limits

Photo mode

The Photo button hides everything but the scene. You can set the time of day and the season, then save a picture of your village with the sky behind it, a framed poster with its name, a 3D model to open in Blender, or a video of it growing piece by piece. Shared villages get their own short link whose preview shows the village.

A snowy village at dusk with lamps lit, saved from photo mode.
saved straight from the site
  • canvas
  • PNG export
  • glTF export

It's all on the home page. Scroll to walk round the room, or build a village in the meadow and publish it for others to see.