Migrate from Mapbox to Maptoolkit
Most of a Mapbox integration ports over. Maptoolkit serves the same kinds of things Mapbox does, in the same formats, to the same libraries, so the basemap is usually a style URL swap and the service APIs are a rewrite of request and response shapes rather than a rethink.
The two parts that are real work are replacing Mapbox GL JS with MapLibre GL JS, and anything built on Mapbox Studio or the Tilesets API. Both are covered below.
What maps to what
| Mapbox | Maptoolkit | What differs |
|---|---|---|
| Mapbox GL JS | Maps JS or plain MapLibre GL JS | MapLibre is the open fork of Mapbox GL JS v1, so most code is unchanged |
| Mapbox Streets vector tiles | Vector Tiles | Different schema. See the Schema Reference for layer and field names |
| Raster Tiles API | Raster Tiles | Same XYZ scheme |
| Static Images API | Static Maps API | Different parameter names |
| Mapbox Terrain-RGB | Terrain Tiles | Terrarium encoding, not terrain-rgb. See below |
| Directions API | Routing API | Car, bike, foot and transit profiles |
| Isochrone API | Isochrone API | Same idea, different response envelope |
| Matrix API | Matrix API | Travel times and distances between origins and destinations |
| Geocoding API | Geocoding API | Forward and reverse |
| Mobile SDKs | MapLibre GL Native | Open source, and the same style URLs work |
Maptoolkit also has no Mapbox counterpart for two things you may want anyway: a Weather API, and Route Enhancement, which adds elevation profiles and surface tags to an existing track.
What does not map
Read this section before planning the work.
- Mapbox Studio. There is no self-service visual style editor on a Maptoolkit account. Custom cartography is an Enterprise arrangement. If your product depends on end users designing their own styles, this is the blocker, not the tiles.
- Tilesets API, Uploads API and Datasets API. There is no path for uploading your own data and having Maptoolkit serve it back as tiles. Your own data stays on your side, added to the map as GeoJSON or as your own tile source.
- Navigation SDK. No Maptoolkit equivalent. The MapLibre Navigation SDK, itself a fork of Mapbox’s, works with Maptoolkit routes.
- Optimization API. No equivalent. Vehicle routing and stop ordering are not offered.
- Tilequery API. No equivalent. Query features from the rendered map on the client instead.
- Boundaries, Movement and the other Mapbox data products. No equivalent.
- Search Box and Places-style autocomplete. The Geocoding API resolves addresses and place names. It is not a drop-in replacement for a session-based autocomplete product.
The library change
There are three options, and only two of them actually leave Mapbox.
Move to Maps JS. This is the one to pick. Maps JS is MapLibre GL JS with the Maptoolkit services already wired in: the API key is a constructor option rather than a query string you thread through every URL, and the style switcher, terrain toggle, weather layers and isochrone control are controls rather than code you write. The class names and the whole style spec are unchanged from Mapbox GL JS v1, so the diff is the script tag, the token line and the style URL:
- <script src="https://api.mapbox.com/mapbox-gl-js/v3.3.0/mapbox-gl.js"></script>
- <link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/v3.3.0/mapbox-gl.css" />
+ <script src="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.js"></script>
+ <link rel="stylesheet" href="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.css" />
- mapboxgl.accessToken = "YOUR_MAPBOX_TOKEN";
- const map = new mapboxgl.Map({
+ const map = new maptoolkit.Map({
container: "map",
+ apiKey: "YOUR_API_KEY",
- style: "mapbox://styles/mapbox/streets-v12",
+ style: "https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=YOUR_API_KEY",
center: [12.805988, 47.310897],
zoom: 11
});
Everything after those lines stays as it is. Map, Marker, Popup, LngLat,
LngLatBounds, the camera methods, the event names and the expression syntax are all the
same, and coordinates remain [longitude, latitude].
The migrated map, running, with the complete diff sits beside this guide: a Mapbox GL JS map with a marker, a popup, a GeoJSON line and a data-driven circle layer, ported over, with every changed line marked and the rest shown untouched.
Move to plain MapLibre GL JS. The community fork of Mapbox GL JS v1, BSD licensed, with
no token and no per-load billing. The same diff applies with maplibregl in place of
maptoolkit and no apiKey option, since the key then lives only in the style and tile
URLs. Choose this when you are already committed to a MapLibre wrapper of your own, or want
no Maptoolkit code in the bundle.
Keep Mapbox GL JS. Pointing the style URL at us is a quick way to prove the tiles work,
but two things make this a test rather than a migration. Mapbox GL JS v2 and later is licensed
by Mapbox and billed per map load, so you still need an access token and are still billed by
Mapbox. And our styles do not load in it unpatched: sprite is an array, the MapLibre
extension for several sprite sheets, and Mapbox GL JS rejects the style with
Error: sprite: string expected, array found. See
Mapbox GL JS for the workaround and what it costs.
What does not come across, whichever you pick:
- Anything using a
mapbox://URL. Styles, sprites, glyphs and tile sources all need real HTTPS URLs. - Mapbox GL JS v2 and v3 additions that MapLibre does not implement, most visibly the Standard style with its lighting model, and Mapbox’s 3D building and landmark layers.
- Custom layers written against the Mapbox v3 rendering internals.
Terrain, the one that silently renders noise
Mapbox encodes elevation as terrain-rgb. Maptoolkit uses Terrarium encoding. The source
config is otherwise identical, so a copied Mapbox terrain block will load tiles, decode them
with the wrong formula, and produce a landscape of noise rather than an error.
map.addSource("terrain", {
type: "raster-dem",
- url: "mapbox://mapbox.mapbox-terrain-dem-v1",
- encoding: "mapbox",
+ url: "https://tiles.maptoolkit.net/terrainrgb.json?api_key=YOUR_API_KEY",
+ encoding: "terrarium",
tileSize: 256
});
map.setTerrain({ source: "terrain", exaggeration: 1.5 });
See Terrain Tiles for the zoom range and the full source config.
Style and schema
Maptoolkit styles are plain MapLibre style JSON served over HTTPS, so
https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=YOUR_API_KEY goes
straight into the style option. Seven styles ship: Summer, Winter, Hiking, Cycling, Street,
Light and Dark.
If you wrote custom layers against Mapbox Streets, the source-layer names and the field names
are different, and every one of those layers needs remapping. The
Schema Reference lists every layer, field and allowed value.
Budget real time for this if your map is heavily customised. It is usually the largest single
item in a migration, and it is the one most often underestimated.
Vector tiles are 512px. Setting tileSize: 256 on the vector source produces rendering
artifacts.
The service APIs
Directions to Routing, Isochrone to Isochrone, Matrix to Matrix and Geocoding to Geocoding are one-to-one in purpose. Request parameters and response shapes differ in every case, so treat each as a small rewrite rather than a URL swap, and read the reference for the one you are moving:
Coordinate order is longitude,latitude, the same as Mapbox, so that class of bug does not
apply to this migration.
What bites on day one
- Errors are
text/plain. A missing key returns403 Access denied!, an unrecognised key returns403 Api-key not found!, and a key without access to that service returns403 Api-key not authorized!. Mapbox returns JSON error bodies, so code that assumes JSON will throw on the first failure rather than report it. - There are no rate-limit headers. No
RateLimit-*, noRetry-After. Quotas are monthly and tied to the plan rather than per second, so there is nothing to back off from at runtime. - Attribution is a license condition. Maptoolkit and OpenStreetMap stay visible. In
MapLibre,
AttributionControldefaults tocompact: true, which collapses the credit behind a button as soon as the map is dragged. Setcompact: falseto keep it readable. - Billing is per request, not per map load. A Mapbox bill is dominated by map loads; a Maptoolkit bill is tiles plus API calls, metered separately. A like-for-like estimate needs your tile volume, which a map-load count does not give you.
Doing it in stages
- Get an API key and load one Maptoolkit style into your existing Mapbox GL JS map. Nothing else changes. This proves the tiles and the key.
- Replace
mapbox-glwithmaplibre-gl. Fix whatever depends onmapbox://URLs and on v2 or v3 features. Drop the Mapbox token. - Remap custom layers against the Maptoolkit schema.
- Move terrain, and switch the encoding to
terrarium. - Move the service APIs one at a time, keeping both providers live behind a flag.
- Check attribution renders on every map, at every breakpoint, after a drag.
- Watch the request counts for a full billing period before cancelling anything.
Pricing
Self-service plans are billed through RapidAPI. See RapidAPI for how to subscribe and authenticate. Plan allowances and prices are on the Maptoolkit pricing page. Enterprise customers call the native hosts with a Maptoolkit API key.
Tile requests and API requests are metered separately and at different rates, so a map-heavy application and an API-heavy one are budgeted differently.