About MapLibre
The TomTom Maps SDK for JavaScript renders through MapLibre GL JS, the open-source map renderer, and exposes it as is.
MapLibre underneath, fully exposed
MapLibre is a peer dependency, so you install it next to the SDK. TomTomMap doesn't hide it. map.mapLibreMap is the MapLibre Map itself, and the mapLibre constructor option takes MapLibre's map options unchanged, except the few the SDK sets itself:
- MapLibre controls, markers, popups, community plugins and examples work on a TomTom map as they are, and so does code written for MapLibre.
- Whatever the SDK doesn't offer, MapLibre's full API still can, so you never hit a dead end.
import { TomTomConfig } from '@tomtom-org/maps-sdk/core';
import { TomTomMap } from '@tomtom-org/maps-sdk/map';
import { NavigationControl } from 'maplibre-gl';
TomTomConfig.instance.put({ apiKey: 'YOUR_API_KEY' });
const map = new TomTomMap({ mapLibre: { container: 'map', pitch: 45 /* any MapLibre option */ } });
map.mapLibreMap.addControl(new NavigationControl(), 'top-right');
map.mapLibreMap.on('moveend', () => console.log('Viewport:', map.mapLibreMap.getBounds()));
What the SDK adds over raw MapLibre
The SDK's own features draw anything MapLibre can, with less code and fewer ways to break:
- They survive style switches. Module data, configuration, layer placement and styling knobs are re-applied after every
setStyle. MapLibre drops the sources, layers and images you added yourself. - They survive style upgrades. Knobs and module settings are semantic, such as
labels.sizeFactoror a route'scolor, and the SDK re-verifies them against every TomTom style release. Raw layer ids and paint expressions belong to one style version and aren't a contract. - Their user events are smarter. One pipeline serves every module. The top-most feature receives the event instead of every overlapping layer, and the cursor has one state. Hover and long-hover have timing built in, clicks have tolerance, and handlers receive your original typed data.
- They follow the map's theme. Routes, places, geometries and reachable ranges take the map's accent colour, so one
setMapColorscall restyles them along with the base map. - Their settings are data. Every module lists its settings in a knob catalogue, validates what you give it, and saves and replays its configuration as JSON.
When to use TomTom SDK vs direct MapLibre
Use the SDK feature wherever one covers what you need:
| To… | Use |
|---|---|
| Switch or load a style | setStyle |
| Restyle the TomTom map: sizes, colours, features | StylingFoundationsModule knobs and setMapColors; styling.layers for a style layer no knob reaches |
| Show or hide base map, POI, traffic and terrain parts | BaseMapModule, POIsModule, TrafficFlowModule, TrafficIncidentsModule, TerrainModule |
| Draw a POI category with an icon of your own | POIsModule's icon.categoryIcons, the same list a PlacesModule takes |
| Show places, routes, geometries and reachable ranges | PlacesModule, RoutingModule, GeometriesModule, ReachableRangesModule, each styled through its own config. Use its layers entries for any MapLibre property the rest doesn't cover (which modules take one) |
| Draw your own GeoJSON data, styled any way | CustomGeoJSONModule |
| React to clicks and hovers, including on the empty map | Module events, and BaseMapModule for the rest of the map |
Your own data belongs in CustomGeoJSONModule too, even a single layer. It takes the same layer specs as MapLibre's addLayer, so you keep MapLibre's full styling and gain the restoration and events above.
Use map.mapLibreMap for anything these don't cover:
- Controls, markers and popups.
- Camera moves (
flyTo,fitBounds) and map lifecycle events (load,moveend,zoom). - Tile overlays: vector, raster and other non-GeoJSON sources.
- Third-party MapLibre plugins.
If you add sources, layers or images through map.mapLibreMap, you restore them after setStyle yourself. They also sit outside the SDK's event coordination.
Combining both
SDK modules and the MapLibre API share one map:
import { TomTomConfig } from '@tomtom-org/maps-sdk/core';
import { PlacesModule, TomTomMap } from '@tomtom-org/maps-sdk/map';
import { discoverPlaces } from '@tomtom-org/maps-sdk/services';
import { Marker, Popup } from 'maplibre-gl';
TomTomConfig.instance.put({ apiKey: 'YOUR_API_KEY' });
const map = new TomTomMap({ mapLibre: { container: 'map' } });
// SDK: places that survive style switches, with coordinated events
const restaurants = await discoverPlaces({ query: 'restaurants' });
const placesModule = await PlacesModule.create(map);
await placesModule.show(restaurants);
placesModule.events.on('click', (feature) => console.log('Place clicked:', feature.properties.title));
// MapLibre: a marker with a popup
new Marker({ color: '#ff0000' })
.setLngLat([4.9, 52.3])
.setPopup(new Popup().setText('Custom Location'))
.addTo(map.mapLibreMap);
MapLibre CSS
The SDK applies the MapLibre CSS itself unless your page already has it, so you don't need to import anything. The stylesheet ships with the SDK:
- It is served from wherever your app serves the SDK, never from a third party.
- A strict Content Security Policy (
style-src 'self') doesn't block it. - It sits in a cascade layer, so your own CSS overrides it whatever order the two load in.
The bundled copy matches the MapLibre version the SDK was built with. To use the CSS of the MapLibre version you installed instead, import it in your JavaScript/TypeScript files:
import 'maplibre-gl/dist/maplibre-gl.css';
Use this import, which your bundler serves alongside your app, instead of a <link> to a public CDN such as unpkg.com. A CDN link sends every end user's IP address to that third party.