A medieval fantasy settlement map generator for Node.js. TypeScript reimplementation of watabou's Medieval Fantasy City Generator.
- Procedural settlement generation from hamlets (pop 10) to metropolises (pop 200k+)
- Deterministic output — same seed always produces identical results
- Zero runtime dependencies — all algorithms ported directly (Voronoi, A*, polygon operations, PRNG)
- SVG and GeoJSON output — render to vector graphics or geospatial features
- Tile-ready — built-in SVG-to-tile slicing for map integration
- 8 colour palettes — default, blueprint, black & white, ink, night, ancient, colour, simple
- Walled cities with towers and gates
- Citadels, castles, markets, temples, parks
- Ward types: craftsmen, merchants, patriciate, slums, administration, military
- Road networks connecting gates to the city center
- Farmlands with strip fields, furrows, and farmstead buildings
- Harbour/dock wards with warehouses and piers for port cities
- Sinusoidal farm/wilderness boundary for organic countryside
npm install settlemakerimport { generateFromBurg } from 'settlemaker';
const result = generateFromBurg({
name: 'Thornwall',
population: 5000,
port: false,
citadel: true,
walls: true,
plaza: true,
temple: true,
shanty: false,
capital: false,
});
// result.svg — SVG string
// result.geojson — GeoJSON FeatureCollection
// result.model — raw Model for further inspectionconst result = generateFromBurg(burg, { seed: 42 });const result = generateFromBurg({
name: 'Harborton',
population: 12000,
port: true,
citadel: true,
walls: true,
plaza: true,
temple: true,
shanty: false,
capital: false,
oceanBearing: 180, // ocean to the south
harbourSize: 'large', // large harbour with more piers
roadBearings: [0, 90, 270], // roads from N, E, W
});import { generateFromBurg, PALETTES } from 'settlemaker';
const result = generateFromBurg(burg, {
svg: { palette: PALETTES.night },
});Available palettes: default, blueprint, bw, ink, night, ancient, colour, simple.
For full control over the generation pipeline:
import { GenerationParams, Model, generateSvg, generateGeoJson } from 'settlemaker';
const params = new GenerationParams({
seed: 42,
nPatches: 15,
plazaNeeded: true,
citadelNeeded: true,
wallsNeeded: true,
});
const model = new Model(params).generate();
const svg = generateSvg(model);
const geojson = generateGeoJson(model);The AzgaarBurgInput interface maps from Azgaar's Fantasy Map Generator burg data:
| Field | Type | Description |
|---|---|---|
name |
string |
Settlement name |
population |
number |
Population count (drives patch count and ward distribution) |
port |
boolean |
Is this a port settlement? |
citadel |
boolean |
Has a citadel/castle |
walls |
boolean |
Has defensive walls |
plaza |
boolean |
Has a central plaza/market |
temple |
boolean |
Has a temple/cathedral |
shanty |
boolean |
Has shanty town areas |
capital |
boolean |
Is a regional capital |
culture |
string? |
Culture name (future use) |
roadBearings |
number[]? |
Compass bearings of approaching roads |
oceanBearing |
number? |
Bearing to nearest ocean (enables coastline) |
harbourSize |
'large' | 'small'? |
Harbour scale for port cities |
Population determines settlement size:
| Population | Type | Patches |
|---|---|---|
| < 100 | Hamlet | 3-4 |
| 100 - 1,000 | Village | 5-9 |
| 1,000 - 5,000 | Town | 10-15 |
| 5,000 - 20,000 | City | 16-25 |
| 20,000 - 100,000 | Large city | 26-36 |
| > 100,000 | Metropolis | 36+ |
Three-layer pipeline:
- Input mapping —
AzgaarBurgInputtoGenerationParams - Generation core — 6-phase pipeline:
- Build Voronoi patches
- Optimize junctions
- Build walls
- Classify water + place harbour
- Build streets (A* pathfinding)
- Create wards + build geometry (farmlands, buildings, alleys)
- Output rendering — SVG string builder, GeoJSON feature builder, tile slicer
All geometry algorithms (Voronoi via Bowyer-Watson, polygon cutting, oriented bounding box, PRNG) are implemented from scratch with no external dependencies.
Requires Nix with flakes:
nix develop
# Run tests
npx vitest run
# Run smoke test
npx tsx smoke-test.ts
# Type check
npx tsc --noEmitGPL-3.0-only (SPDX-License-Identifier: GPL-3.0-only). Full text in LICENSE;
attribution and provenance in NOTICE.
settlemaker is a derivative work of watabou's TownGeneratorOS,
which is GPL-3.0. Upstream grants no "or any later version" option, so settlemaker is
GPL-3.0-only, not -or-later.
The hosted build at settlemaker.com ships this program's compiled code to your browser; the corresponding source is this repository.
Two things are not covered by that license:
- The SVG symbol library (
web/public/symbols/) is original artwork under CC BY 4.0 with a rendered-output exception. Maps you render with the symbols are yours and owe nothing — no credit, no notice. Attribution applies only if you redistribute the library itself (the SVGs, the sprite, or a set derived from them), in which case credit the authors in CREDITS. Contributions are accepted on those terms. - Azgaar's Fantasy Map Generator (MIT) consumes settlemaker at arm's length over the URL API. Separate programs exchanging data, not a combined work — neither license reaches into the other.