OSM City Online: a multiplayer OpenStreetMap editor

HDT CoLab · Fall 2026 · Node.js 22 · node:sqlite · canvas vectors

OSM City Online: a multiplayer OpenStreetMap editor

A multiplayer OpenStreetMap editor that runs against its own local mirror of the map. Roads, buildings, land use, waterways and relations are all editable together in the browser — and nothing is ever written back to OpenStreetMap.

  • 2.07 Mnodes
  • 320 kways
  • 10 krelations

the local mirror

The editor never touches the public database and never asks anyone to authorise an OAuth application.

The server keeps its own extract instead. Importing the Beijing package takes about a minute and produces a single SQLite file — no tile server, no external service, no npm dependencies. Editing is therefore free of consequences for the real map, which is what makes the tool usable in a classroom.

nodes
2.07 M
ways
320 k
relations
10 k
database
478 MB
import
60 s
peak memory
214 MB

drawing a city without tiles

No tile server is involved.

The map is drawn on a canvas from the vector data itself, with 819 styling rules in the spirit of OSM Carto and buildings extruded so that a street reads as a street and a block as a block. The spatial index is the R*Tree built into SQLite, so panning and querying stay instant on a laptop.

viewport at z1613,411 ways · 79,596 nodes
SQL for that viewport523 ms
payload8.5 MB
features rendered2,817 + 141 labels
render time101 ms
styling rules819

editing together

Several people edit the same city at once, from the same local network.

Every edit is checked on the server and then broadcast; the client only previews. An element you select is softly locked for 120 seconds so two people cannot rewrite the same road, versions are compared before a write, and a change set can be downloaded as osmChange or rolled back.

  • 1selectinspect and edit every OSM tag
  • 2nodedrag a node, shift-drag a whole road
  • 3pointnew POI, 159 presets
  • 4linedraw, enter to finish
  • 5areaclosed ways share their first node
  • 6splitcut a road at a node
  • 7mergejoin two roads at their ends
  • 8joincollapse two nodes into one
  • 9deletewith optional cascade
  • 0rectangularisesquaring a building outline
  • Ctrl+F searches by name, by key=value, or by key alone.
  • Twelve layer groups can be switched on and off live.
  • Undo and redo keep 100 steps per person; a bulk move counts as one.
  • Cursors, the element a collaborator is editing, and a chat channel are all visible.

running a network

On top of the real map, you can also run a transport company.

Stations snap to the nearest network node, lines are routed along the real network, and vehicles are simulated on the server. Population and jobs are derived from the buildings themselves, so adding a floor to a building changes the demand around it.

rail network
4,491 ways · 34 k nodes · built in 280 ms
bus road network
91,245 ways · 529 k segments · 3.6 s
population
16.93 M across 32 k grid cells
jobs
4.83 M
fare
¥3 + ¥0.5 per km
clock
paused · ×1 · ×5 · ×20

the payload

Making a fast map is mostly a payload problem.

Below the editable zoom the server sends lines and areas merged into compact geometry with no way ids — enough to draw, not enough to select. Reworking what that geometry carries cut the low-zoom payload by roughly half.

  • z9 2405 KB 916 KB water rings and area members moved to compact geometry
  • z10 2476 KB 1009 KB 104 k node coordinates no longer sent
  • z12 1804 KB 917 KB
  • z14 693 KB 453 KB
  • z15 622 KB 408 KB now a full editable band

before · after

the stack

Zero dependencies: no npm packages, no network at runtime.

The storage engine is the node:sqlite module built into Node 22, the WebSocket server is written from scratch against RFC 6455, and the browser uses Leaflet only as a geometry and interaction engine — never as a tile client.

  1. browserLeaflet · OSM model · canvas renderer · 819 style rules · 159 presets · 11 tools
  2. serverroutes · auth (scrypt) · RFC 6455 WebSocket · geometry, tags, references, versions, locks, undo, changesets
  3. sqlitenodes · ways · way_nodes · relations · relation_members · R*Tree indexes · changesets · changes

how it is checked

verified

Roughly 370 assertions run across six suites: the importer (82), the style table and presets (133), the protocol end to end (77), the browser through CDP (28), boot robustness (18) and the transit protocol (29).

next

The project's own notes name the next step: binary vector tiles, which should cut the payload by about another ten times.

limits, stated plainly

  • This is a local mirror editor, not an upload tool: changes live in one SQLite file and never reach OpenStreetMap.
  • OpenStreetMap in China is unevenly mapped, and the page shows raw WGS-84 coordinates rather than GCJ-02.
  • Below z15 the map is view-only by design; picking and editing start at the editable band.
  • Undo lives in memory — 100 steps per person, cleared when the server restarts.
  • A country-wide extract is not a few gigabytes: the project measures 25–40 GB and one to two hours of import.