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.
  • Where the SDK doesn’t offer something, MapLibre’s full API still does, 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.sizeFactor or a route’s color, 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 setMapColors call 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 stylesetStyle
Restyle the TomTom map: sizes, colours, featuresStylingFoundationsModule knobs and setMapColors; styling.layers for a style layer no knob reaches
Show or hide base map, POI, traffic and terrain partsBaseMapModule, POIsModule, TrafficFlowModule, TrafficIncidentsModule, TerrainModule
Draw a POI category with an icon of your ownPOIsModule’s icon.categoryIcons, the same list a PlacesModule takes
Show places, routes, geometries and reachable rangesPlacesModule, 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 wayCustomGeoJSONModule
React to clicks and hovers, including on the empty mapModule 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.
  • Custom layers with your own WebGL or three.js scene, which you add with map.addCustomLayer.

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. A custom layer added with map.addCustomLayer is the exception: the SDK keeps it in place, and its hitTest gives its objects SDK events.

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.