threejs-city: Grow a whole town from a seed.
Settlements where people would live, placed and sized by a population model on an H3 hex grid, with roads that follow the terrain, blocks, lots and buildings that match the climate. One call to City.create() or one <City />, and the ground is flattened under all of it.
Found a town in one call.
Plan where people live on a threejs-biomes world, then build the largest place. The city adds itself to the scene, updates its LOD whenever the scene renders, and registers terrain edits on the world so roads and buildings sit flat.
import { World } from 'threejs-biomes'
import { City, generatePopulation, planCities } from 'threejs-city'
const world = new World({ seed: 11 })
const people = generatePopulation(world, { radius: 10_000 })
const [site] = planCities(people) // largest first
const city = await City.create({
world, camera, scene,
center: [site.x, site.z],
size: site.size,
radius: site.radius,
seed: site.seed,
})
city.set({ facade: { night: 1 } }) // lights on
city.set({ weather: { roofs: { snow: 1 } } }) // snow on every roof
import { useWorld } from 'threejs-biomes/react'
import { City } from 'threejs-city/react'
function Town({ night, rain }) {
const world = useWorld({ seed: 11 })
return (
<City
world={world}
size="village"
center={[200, -50]}
facade={{ night }}
weather={{ roads: { wetness: rain } }}
/>
)
}
Everything a settlement needs.
Placement, streets, plots, houses and the ground they stand on. Every feature below is live in the demo, and every setting can change at runtime.
Sited where people live
Planned by the population.
The settlement planner below decides where people live and how many. planCities turns each settlement into a size class and a radius from its head count, and each class builds its own way: farmsteads get a farm and its fields, hamlets a junction, villages a road of houses, towns a main street, cities and metropolises towers. <Settlements> builds them all.

Roads that grow
Along a tensor field.
Arterials grow from the centre and branch into collectors and local streets, following grid patches, a radial centre and the terrain gradient. They avoid water and steep grades, snap to junctions, refuse acute angles and bridge narrow rivers.

Three street layouts
Grid, radial or organic.
Pick a style or let the size class choose. Each preset tunes the tensor field and road lengths; all of it stays open to override.
- grid
- radial
- organic
- farmstead
- hamlet
- village
- town
- city
- metropolis
grid
organicBlocks, lots and districts
Every building has a plot.
Blocks are faces of the road graph, inset by road and sidewalk, then split into lots that keep street frontage. Downtown, residential, industrial, park and farmland districts set block size, setbacks and floors.

Buildings for the climate
Six architectures.
Towers, apartment blocks, houses and sheds, with gable, hip, skillion, flat and saw-tooth roofs, chimneys, balconies and stilts. Materials and roofs come from the climate at the centre, or set architecture yourself.
- temperate
- cold
- arid
- mediterranean
- tropical
- wetland

Procedural facades
Windows that light up at night.
Facades are a TSL shader: window grids, frames, shopfronts and procedural plaster, brick, wood, stone, glass and adobe. Window lights are hashed per window and glow with facade.night, a uniform you can fade every frame.

Weather hooks
Wet, snowy, burnt or damaged.
Walls, roofs and roads each take wetness, snow, burn and damage. Wet roads get puddles, snow stays out of tyre tracks, and setBuildingWeather sets one building on fire.
Ground that fits
Graded roads, level pads.
Each road gets a graded profile, and flatten modifiers along roads and under buildings are registered on the world in one batch. Terrain, grass and scatter follow; dispose() removes them.

Data for everything else
Roads, lots and buildings as JSON.
city.data() returns road edges with lanes and speeds, lots with frontage and buildings with entrances. roadAnchors places street lights; graph.shortestPath with routeCost routes cars, bikes and people.

Where people live.
A population model on H3's hexagonal grid, read from the world: habitability, settlements, density, land use and networks, all from a seed, as plain data plus a PopulationOverlay hex map. Everything below except the last row is live in the settlement planner demos.
Habitability from the world
Where people would choose to live.
Every fine cell reads the threejs-biomes world: biome fertility, gentle slope, a comfortable temperature, and a river valley or coast nearby. Water and avoided biomes (deep ocean, glacier, peaks, volcanic) score zero.

Central places
Christaller on H3.
At each tier's resolution, cells whose habitability is a local maximum become settlements. Each higher-tier place claims its market area, so towns fall between cities and villages between towns, one H3 resolution (about 7× the area) apart.

Sized by rank
Zipf, then classes.
The r-th settlement gets P₁ / rzipf people, scaled so they sum to the urban share of totalPopulation. Its class comes from thresholds; farmland cells may hold a farmstead. Classes map onto city size classes with citySize.
- metropolis
- city
- town
- village
- hamlet
- farmstead

Density that fades out
Integer people per cell.
Each settlement spreads its people over nearby cells with a Gaussian of its radius. Rural people fill habitable land, denser along rivers and coasts (corridor) and near towns (ruralDecay). Cell counts are integers that sum to the total.

Land use
Five classes per cell.
Urban and suburban by density, farmland by habitability, everything else wilderness, plus water from the world. Thresholds live in landUse.
- urban
- suburban
- farmland
- wilderness
- water

Night lights
Cities seen from orbit.
Brightness is 1 − exp(−density / lightDensity). nightLights(data, res) returns typed arrays of centres and intensities at any resolution, with sample(x, y, z) for a glow pass or an orbit view.

Roads, rail and power
Routed over the terrain.
A spanning tree reaches every settlement, plus gravity-model links where the tree forces a detour. Each link is an A* route over the hex graph, costed by slope and water and cheaper where earlier routes run, so roads merge into trunks. Rail avoids hills harder; power lines span straight.
- highway
- road
- track
- rail
- powerline

Hexagons at every scale
Coarser cells are exact sums.
H3 nests resolutions, so the same people show at 400 m, 3 km or 22 km cells. With resolution: 'auto' the overlay steps coarser as the camera pulls away; aggregatePopulation(data, res) gives the sums as data. Flat worlds and planets both map onto H3.

Data and maps without a GPU
Plain objects and RGBA.
generatePopulation and generateNetworks are pure and seeded. renderPopulationMap returns RGBA pixels for a minimap, a worker or a test, in the same colours as the overlay.

Traffic from people
Sized by who lives where.
Next, the population will size the traffic on each road and railway, from the people at either end.
Found your town.
Try every size, layout and weather in the live demo, or go straight to the API reference.