Skip to content
Documentation menu

Build with MapMap

Every page is also served as raw markdown. Append .md to the URL. Agents: /llms.txt · /pricing.json

Prefer to watch? The video library covers the same ground in 49 short videos.

MapMap in 90 seconds · 1:36 · all videos

Get started

Mint a key, make the first call, and learn the rules every endpoint shares.

Routing and analysis

Routes with lorry dimensions and ADR constraints, plus the analysis endpoints around them.

Maps and data

Tiles, styles and Studio, your own data on the map, and the file formats behind both.

Maps, tiles & Studio

Hosted vector tiles, TileJSON and styles, the Studio style editor, fonts and sprites, and the @mapmap/maps web SDK.

Vehicle avatars

Draw the user's vehicle as one of MapMap's own 3D-rendered cars: AvatarPuck in the web SDK, the hosted sprite and model contract for native apps, self-hosting and the artwork licence.

Add your own data

Your data on a MapMap map: clustered pins with PlacesLayer, choropleths and heatmaps through the raw MapLibre escape hatch, PMTiles you host on your own bucket, raster, image and video sources, hover and selection with feature-state, insertion points, custom WebGL layers, MapLibre Native snippets for iOS and Android, reachability rings with IsochroneLayer, GeoJSON overlays on static map images, and the honest limits.

Buses: positions, stops and timetables

England's buses as display data: live positions, NaPTAN stops and BODS lines on a map with TransitStopsLayer, stops near a point and timetabled departures at a stop, the label that says what a live entry is, coverage and the OGL credits.

Leaflet, OpenLayers, deck.gl, Cesium & QGIS

Render MapMap tiles in the clients that are not MapLibre GL JS: a verified snippet each for Leaflet, OpenLayers and deck.gl, what Cesium genuinely cannot do, and the two ways QGIS reads our tiles.

File formats

The channel-index JSON schema, the installed territory package's on-disk layout, and the .drive.jsonl replay-corpus line schema, with a sample corpus.

Data collection & the probe flywheel

How on-device aggregation turns navigation into road-segment statistics without a trajectory ever leaving the vehicle: what a ProbeBatch holds, the three guarantees enforced in code, and the opt-in gate.

SDKs and apps

Web, Android and iOS packages, in-car surfaces, and the Nav reference app.

Agents and machine payments

Connect an assistant over MCP, teach it with skills, and let it pay for its own calls.

Worked recipes

Whole jobs end to end, including moving across from another provider.

Run it yourself

The Docker distro on your own hardware, and signed offline territory packages.

Reference

The endpoint surface, generated from the gateway's own OpenAPI document.

Licensing

What each of the three legal surfaces covers, and the ODbL boundary.

Troubleshooting

The web SDK's error messages link straight to the entries below.

Container element not found

The element you pass to the map constructor must exist in the DOM before the map is created. In React, create the map in an effect (after first render), pass a ref's current, and clean up with map.remove().

Map renders 0px tall

MapLibre sizes the canvas from its container, and a container with no explicit height collapses to 0px: a blank “working” map. Give the container (or its parent) a fixed height, and beware absolute inset-0 with Tailwind: MapLibre's own .maplibregl-map { position: relative } rule can win the cascade over the single-class .absolute utility. Size the map div directly off a fixed-height parent instead.

Two copies of maplibre-gl

If your bundle contains maplibre-gl twice (a direct dependency alongside the SDK's), protocol registrations and instanceof checks silently miss each other, and tiles stop loading with no error. De-duplicate: keep one maplibre-gl version, and check with npm ls maplibre-gl.

WebGL unavailable or context lost

Map rendering needs a WebGL context. Headless browsers, virtual machines and very old GPUs may not provide one, and browsers cap how many live contexts a page can hold: destroy maps you no longer show (map.remove()) rather than hiding them. In CI, run Chromium with --use-gl=swiftshader (or Playwright's default software GL) to get a software context.

401 from the hosted API

The gateway rejected your key. Send it as Authorization: Bearer snk_… (or ?api_key=snk_…), check its state with the quota-free GET /v1/keys/self, and remember provisional keys expire after 72 hours until you click the verification email. No key yet? One call, free tier.