Every kit now builds itself, lights itself and grows into a town
One call places every part of a kit the way it was composed. One lights it at the hour you choose. One lays a bigger town from the same buildings. Then we measured what that does for an agent building a game.
Every Polyfork kit is composed as a place, by hand, before it is photographed: Cozy Farm is 617 placements of its 60 parts, Little Tokyo is 524 of its 46. Until this month that composition shipped as a list, and using it meant reading the list, joining each row to a model, importing sixty modules and writing the loop. Most people, and every agent we watched, skipped that and placed twenty parts by eye instead.
So the loop is written once. Three helpers ship inside every kit zip and at /cdn/: kit.mjs builds the place, stage.mjs lights it, city.mjs lays a bigger town out of it. The picture above is the Medieval Village kit: built by the first call from the composition its maker placed it in, lit by the second at golden hour, with its own hills and trees past the edge from one line more.
One call, the whole place
import { buildKit } from './kit/kit.mjs'; // from the unzipped kit; or https://polyfork.dev/cdn/kit.mjs
const place = await buildKit({ folder: './kit/', params: { season: 'autumn' }, keep: ['pumpkin-crop'] });
scene.add(place.group); // every placement, as the kit was composedThat is the arrangement the kit was photographed and filmed in, with the knob values each part was built with. params reaches every part that declares a scene-wide knob, so season: 'winter' is safe to pass to a kit where 59 of 60 parts have it. keep names the parts you will move, hide or pick up; everything else is merged into one draw call per material. Cozy Farm placed part by part is 880 draw calls; merged it is about a dozen, and it loads in under two seconds.
The place then answers the questions a scene is usually built around:
place.blocked(x, z, radius): the part a body there would touch, or null. It tests a convex outline of each placement's ankle-to-head slab, so a car parked at an angle, a round fountain and a chamfered corner are the shapes they look, and overhead wires and tree crowns are not walls.place.spots(n, { from, road }): n clear, reachable, spread-out points, flooded outward from where you start so nothing lands in a fenced yard.place.surfaceAt(x, z): the ground tile under a point.place.groundAt(x, z): the terrain height.place.vista(): a camera that frames the whole place from its best side.place.of('barn'),place.where('tipping-trailer'): the objects and where they stand.
No physics engine, no navmesh, nothing you have to derive from six hundred rows.
Lit the way it was made, at the hour you choose
These models are authored for no tone mapping under a hemisphere, a warm key and a cool rim. Put the usual tutorial rig over them, ACES at exposure 1 with two lights, and they come out a third darker and muddy: we measured it, because the first pairs of agents lost on lighting to games whose author had tuned their own colours by eye.
import { stage } from './kit/stage.mjs';
const look = stage(renderer, scene, { time: 'golden' }); // noon | day | golden | dusk | night | moonlit | dawn | overcast | space | 0..1
look.shadows(place.group); look.ground(place); await place.surround();
look.follow(player); // look.update() each framestage() is that rig, with soft shadows that follow whatever you follow, a sky, and fog that stays behind your subject. Nine named setups, from noon to moonlit to the black sky over a moon base, and a day-to-night line you can animate. Nothing recommends one: the hour is yours.
After dusk the place lights itself. Every part already names its lit zones and the colour each burns; buildKit carves those faces out before the merge and gives each lamp a pool of light on the ground, so 'dusk' and 'night' arrive with the windows on and the street lamps pooling, in one draw call for all the pools.

A bigger town from the kit's own buildings
A kit is composed once, as two blocks or so. A driving game wants more, and every agent that wanted more laid its own street grid and dressed it by eye, which is the expensive, worse-looking thing this whole loader exists to prevent.
const place = await buildKit({ folder: './kit/', city: { seed: 7, blocks: [4, 3] } });Nothing is invented. The generator takes the composed layout apart into lots, each building with everything the composer put on it and in front of it: the awning, the sign, the air-con units, the vending machine and the bicycles on its pavement, the lamp at its kerb, the water tower on its roof. It learns which side of each building faces the street. Then it lays a grid of streets, drawn in the road tile's own colours with a centre line, kerb lines, zebra crossings and stop lines, rings each block with pavement at the pavement tile's own size, and packs the block edges with lots shoulder to shoulder, never the same building twice running, repeats repainted in another of their colourways. Some blocks become parks around whatever the kit has one of, a shrine or a subway kiosk. Cars park along the blocks. People stand on the pavements, and two in three of them walk their block. The ring road's outer side gets a row of facades facing in, so every street ends on a building rather than a field.
Little Tokyo at four blocks by three is 168 by 104 metres, about two thousand placements, built in 1.6 seconds. New York at three by three is 224 by 176 metres, from a kit whose composition is one block. And the town comes back as data: place.city.streets, place.city.junctions, and place.city.lots, each with the way it faces and a door point on the pavement in front of it, where a parcel is left or a quest-giver stands.
What we do not do
A game. There is no controller, chase camera, HUD, pickup rule or sound in any of this, on purpose: every game is different, and a world builder that decides how the player moves has decided too much. These helpers build a place, light it, grow it and answer questions about it. What you do in it is yours.
Measured
We ran the same brief through two headless coding agents at the same moment, one connected to Polyfork and one with only the open web, and put the same five screenshots of both games in front of three blind judges, a different model from the builders. Two briefs on the product exactly as it ships:
| brief | with Polyfork | without | first build that passed | judges |
|---|---|---|---|---|
| a farm, on foot | $1.63, 11 min | $3.08, 26 min | 7 min against 18 | Polyfork on all five criteria, 3-0 |
| a night delivery, driving | $3.02, 28 min | $2.85, 27 min | 9 min against 19 | Polyfork on all five criteria, 3-0 |
On the farm the whole place, its light and its collision are no longer written by hand, and the bill halves. On the delivery the cost is level and the looks are not: the judges' words for the other game were "extruded boxes with painted-on window grids", and for ours "a place someone lives". The method, the transcripts and every run are in the bench notes.
Frequently asked questions
Do I need Polyfork's servers at run time?
No. The kit zip carries every part, the composition, the ground program and the helpers, and buildKit({ folder }) builds from that folder with nothing fetched from us. The one exception is the free walk cycles for the placed people, which clips.mjs fetches from our CDN; a folder with no network still builds, with its people standing still.
Does buildKit work outside three.js?
The helpers are three.js modules. Every part is also a plain GLB, and the composition is LAYOUT.json, a list of placements with positions, rotations and knob values, so the same loop is a few lines in Unity, Godot or Blender. The town generator is three.js only for now.
Which kits can generate a town?
Kits with street tiles: Little Tokyo, New York City and Neighborhood Pathways today. A farm or a space base builds its composed place and answers the same questions about it, but city needs roads to lay.
How is lighting decided?
By you. stage() offers nine named setups and a 0 to 1 line from day to night, and nothing in the API or in what our MCP tells an agent recommends one. After dusk the place's own windows and lamps come on, because every part already says which of its faces glow.
Is any of this a game engine?
No. It builds, lights and describes a place. There is deliberately no player controller, camera, HUD or game loop in it.


