Skip to content

Geo Conventions

Geo has a few conventions that everyone trips over once. Adopt the established defaults instead of inventing your own — it keeps schemas interoperable and spares the model a class of silent mistakes.


A bounding box is [ minLon, minLat, maxLon, maxLat ]longitude first (RFC 7946 / GeoJSON order). Swapping the pair sends a query to the wrong hemisphere and returns plausible-but-wrong results, with no error to warn you. A bbox around Berlin:

// [ minLon, minLat, maxLon, maxLat ]
const berlin = [ 13.088, 52.338, 13.761, 52.675 ]

If a schema must accept the other order, make it explicit — never guess:

{ position: { key: 'axisOrder', value: '{{USER_PARAM}}', location: 'query' },
z: { primitive: 'enum(lonlat,latlon)', options: [] } } // no silent default

Geo tools that accept several ways to locate a place (free text, coordinates, a postal code, an OSM id) should take exactly one per call. Two selectors is ambiguous — reject it rather than picking one silently:

// caller sends exactly one of: text | latlon | postalCode | osmId
if( selectorCount !== 1 ) { throw new Error( 'GEO-RESOLVE-001: provide exactly one location selector' ) }

Use a stable administrative code as the join key between datasets, and a human-friendly code only as a display anchor. For German data, that means joining on the municipality key (AGS) and showing the postal code (PLZ) — not the other way around:

join on: ags = "11000000" (stable, 1:1 with the municipality)
show as: plz = "10115" (familiar, but many PLZ per municipality)
  • Events are not in OpenStreetMap. Querying OSM for concerts, markets, or exhibitions returns nothing useful — reach for a dedicated events/culture source instead.