← Work

Work / Tool Prototype

Urban Atlas Studio: print-ready city map posters from open map data

Urban Atlas Studio turns OpenStreetMap data into print-ready city map posters: 26 themes, four layouts and three approved sizes, drawn as vector PDFs to the exact size a print-on-demand product needs. The engine is deterministic, and it refuses a size it cannot tie to a real product.

Demonstration data. Public map data with invented poster text and an invented date.

One command turns a stretch of Galway’s coast into a poster file ready to print at 30 by 40 centimetres.

urbanatlas render "Galway, Ireland" --lat 53.2707 --lon -9.0568 --theme crimson_coast \
  --size 30x40 --layout panel --span 5 --subtitle Ireland --proof

Galway_crimson_coast_30x40_panel.pdf
  roads 2,034 · water 50 · parks 1,046 · sea 1
  trim 300x400 mm · bleed 308x408 mm · sRGB intent
A Galway map poster in claret and blush with the sea in deep blue, titled GALWAY, IRELAND, with coordinates beneath
Figure 1. The poster from that command, shown as a PNG proof: claret streets, a deep blue sea and the place name and coordinates beneath. Map data © OpenStreetMap contributors, available under the Open Database Licence.

At a glance

  • Status: Prototype.
  • Platform: a Python command-line tool, with a Claude skill that can drive it.
  • Stack: Python, osmium for OpenStreetMap files, GeoPandas and Shapely for the geometry, Matplotlib for drawing, pikepdf for the PDF page boxes.
  • Built with: Claude Code and Codex.
  • AI inside the product: none. The engine calls no model. A Claude skill can run the commands for me, but the posters are drawn by ordinary code.

What it makes

Posters for an Etsy shop fulfilled by Gelato, which prints and posts on demand. The engine produces the part that has to be right before any money is involved, the artwork.

There are 26 themes, and I decided they all ship. Here is one place in six of them.

Six posters of Galway side by side: Duotone Ink, Mono White, Ancient Map, Neon, Terracotta and Blueprint
Figure 2. One place in six themes, from Duotone Ink and Ancient Map to Neon and Blueprint, all at the same size. Map data © OpenStreetMap contributors (ODbL).

Four layouts cover the formats: a full-bleed map with no type, a map inset in a margin with the city name and coordinates beneath, a map cropped to a disc, and a personal layout with a headline, a date and a pin.

Four posters of Galway in Duotone Ink: Panel, Bleed, Circle and Personal, the last with a red pin and an invented personal headline
Figure 3. The four layouts on one place. The personal layout carries an invented headline and date. Map data © OpenStreetMap contributors (ODbL).

The same engine draws other cities from the regions I have ingested: Ireland and Northern Ireland, the Paris region, Tokyo’s Kanto region and Catalonia.

A Paris poster in the Ancient Map theme: parchment ground, engraved sepia streets, the Seine and a compass rose
Figure 4. Paris in the Ancient Map theme at a 5 km span, with the Seine and a compass rose. Map data © OpenStreetMap contributors (ODbL).

An engine that refuses to guess

Real print costs sit downstream of every file, so the engine is built to say no. Ask for a size that does not match a product and it stops:

urbanatlas render "Galway, Ireland" ... --size 45x60
error: "'45x60' is not an approved poster size. Valid sizes: 30x40, 50x70, 70x100.
Sizes must correspond to a verified Gelato product - the product determines the
artwork, not the other way round."

Build decision. Sizes come from a short approved list, each tied to a print product, not from whatever number I type. Two more sizes exist in the code but are held out of the launch catalogue until I decide the listing structure.

Two more decisions shaped the output file.

Exactly the size asked for. The prototype let the plotting library size the file from its contents, so a request for 3600 by 4800 pixels produced 3630 by 4830. For a manufacturing file that is a wrong-sized product. The rebuild lays the page out in millimetres, so a 12 mm margin is 12 mm at every poster size, and it writes the trim and bleed boxes into the PDF.

Vector glow, not a bloom. The night-lights theme gets its glow from layered vector strokes. A raster bloom would look more photographic, but it would force the print file to be a picture, and a vector file is what lets one design print at 30 by 40 and at 70 by 100.

A contrast check keeps themes readable, and I recalibrated its thresholds against rendered output because brightness alone cannot judge colour separation. Every theme still gets a look from me before it ships.

Under the hood

I built Urban Atlas Studio with Claude Code and Codex as a Python command-line tool, designing the product, the themes and the print rules myself.

Map data comes from regional extracts downloaded on demand and ingested once per region, because the file reader has no spatial index and slicing a small box still means reading the whole country. Ingested features are cached by bounding box, and a request that fits inside a cached box reuses it. Sea comes from a separate prepared coastline dataset, because OpenStreetMap stores a coastline as a line and not as an area.

LayerWhat I used
InterfaceA Python command-line tool, plus a Claude skill that can run the commands
LanguagePython
Map dataOpenStreetMap regional extracts read with osmium, ingested once per region and cached by bounding box
Geometry and drawingGeoPandas and Shapely for geometry, Matplotlib for drawing, laid out in millimetres
OutputVector PDF with trim and bleed boxes written by pikepdf, an sRGB colour intent, and an optional PNG proof
Runtime AINone
Tests359 tests
FulfilmentEtsy shop with Gelato printing on demand
Diagram: Geofabrik extracts, ingest and cache, coastline polygons, the renderer with themes, layouts, sizes and borders, then a print PDF and an optional PNG proof
Figure 5. The pipeline, drawn from the code. Dashed boxes are optional or separate inputs.

The test suite has 359 tests.

A native-resolution crop of the Galway proof showing the harbour: fine street lines, the quay and the sea edge in claret, blush and navy
Figure 6. A crop of the 30 by 40 proof at its native 300 dpi, around the harbour, where the fine street lines, quay and sea edge stay crisp. Map data © OpenStreetMap contributors (ODbL).

What it shows

Urban Atlas Studio is one engine with one deterministic path from open data to a file a printer can use at its exact size, with an approved list standing between me and a wrong-sized product. The same engine draws a coastline in Galway, a river in Paris and a personal poster from a pin on a map, in 26 themes and four layouts, and every size it will accept is tied to a real print product. That is the part of a print-on-demand shop that cannot be allowed to drift, and it is the part I have made dependable.