Migrating from Maps SDK for Web V6

TomTom deprecated Maps SDK for Web V6 on February 1, 2025, and withdrew its CDN endpoints on February 1, 2026. They answer 404 unless your contract runs past that date, and then only until it ends. V6 receives no further updates, security patches or bug fixes. The Maps SDK for JavaScript replaces it.

Migration carries no additional cost. Your API key, contract and per-call pricing stay the same (Pricing and commercial impact).


Why migrate

BenefitWhat it means for you
Map + services integrationA route, a place search or a traffic query renders on the map in one call, through a map module, with no addSource/addLayer boilerplate.
Open rendering engineBuilt on MapLibre GL JS, open source and BSD-licensed, with its plugin ecosystem.
Orbis MapsNative support for TomTom’s map data, which combines OpenStreetMap with TomTom’s own data (Future-proof with Orbis Maps).
Smaller bundlesES modules with tree-shaking, so you ship only what you import. V6 shipped monolithic UMD files.
First-class TypeScriptComplete type definitions ship with the package, so you don’t install @types.
Cross-platform servicesThe Services bundle runs in the browser and Node.js 22+ from one codebase.
Native GeoJSONPlaces, routes, reachable ranges, geometries and traffic come back as GeoJSON (the POI category and search-suggestion services return plain objects), ready for the map, deck.gl or your database.
Your brand on the mapRestyle the map at runtime with styling knobs for label sizes, road widths and colours, apply your brand colours in one call, and derive a theme from your site’s CSS or an image.
Built for AIA coding-agent skill for Claude Code, Cursor, Copilot and others, and the Agent Toolkit that lets your users talk to the map.

Feature comparison

Map display

CapabilityV6New SDKNotes
Vector map renderingYesYesMapLibre-based
Map styles (Light, Dark, Driving, Mono, Satellite)YesYesBuilt-in themes
Custom style files or URLsYes—Restyle a standard style at runtime with styling knobs and map colours
Style switching keeps your data—YesV6’s setStyle dropped added layers. SDK modules restore themselves
Map languageYesYesmap.setLanguage, or once for map and services in the global config
Geopolitical viewsMap tiles onlyYesOne setting covers the map and every service call
3D buildingsYesYesThe buildings3D layer group of the Base Map Module
Hillshade and 3D terrain—YesNew
Globe projection and sky—YesNew
Semantic styling (label sizes, road widths, traffic colours, presets)—YesNew: every setting is a knob with a stable id
Brand colours and the accent—YesNew: setMapColors, and exportStyle to save the result
Markers, popups, controlsYesYesMapLibre API
Search results as map pinsManualYesPlaces module: pins, clustering, entry points and connections
Built-in POI filtering and iconsShow/hide onlyYesPOIs module: by category, with your own icons
Route displayManualYesRouting module: alternatives, waypoints, sections, speed-limit signs
Reachable ranges on the mapManualYesReachable ranges module
GeoJSON layers / custom dataYesYesGeometries and the Custom GeoJSON module, which keeps your layer specs across style changes
Bring-your-own-data (heatmaps, etc.)ManualYesExample included
Click and hover on map featuresManualYesModule events with hover and click states
Orbis Maps support—YesNew map data
Layer group toggling—YesBase map module
Style part lazy loading—YesFaster initial load

Services

CapabilityV6New SDKNotes
Calculate route (A→B, waypoints)YesYesGeoJSON response
Route alternativesYesYes
Route guidance (arrows)YesYesExample included
Route with live trafficManualYesBuilt-in module
Route reconstructionYesYesInteractive playground
Long Distance EV RoutingYesNoRoutes are planned without a vehicle consumption model
Reachable rangesYesYesSeveral origins and budgets in one call. It is in private preview, so your key needs access
EV Charging AvailabilityYesNoSearch returns EV stations with their connectors and charging points, without live status
Fuzzy, category and nearby searchYesYesOne discoverPlaces function; playground included
Geometry search / along-route searchYesYesSame discoverPlaces function
Search suggestionsAutocompleteYesPlaces, brands and categories ranked together
Geocoding / reverse geocodingYesYesWeb + Node.js
Place detailsYesYesOpening hours, entry points, related POIs
POI categoriesYesYesMatch categories by name in any supported language
Geometry data (place boundaries)YesYesV6’s additionalData
Traffic flow tilesYesYesConfig playground
Traffic incidentsYesYesTyped filters by magnitude, category and road
Traffic incident detailsYesYesDrawn on the map by the incident details module
Traffic area analytics—YesNew: historical speed and congestion over any area, drawn as a heatmap or 3D grid. Needs a MOVE Portal key, with a 30-day free trial
Server-side services (Node.js)Services onlyYesFull support

Developer experience

CapabilityV6New SDKNotes
TypeScript supportAnnotations onlyFull typesNo @types needed
Tree-shaking / ESMUMD bundlesESMSmaller bundles
Centralized config (singleton)—YesSet once, use everywhere
Framework examples (React, Vue)LimitedYesIn docs
CodeSandbox examples—Yes110+ runnable examples
API reference docsYesYesFull TypeDoc
Per-call API key overrideYesYesOverride the key per call or per map
Keeping the API key off the pageManualYesProxy mode: your server adds the key
52 languages supportedYesYesGlobal config
Settings as data—YesEvery module setting has an id: save, replay, or build a UI from the catalogue
AI coding-agent skill—Yesnpx skills add for Claude Code, Cursor, Copilot and others
Open-source rendering engineMapbox GL (proprietary)MapLibre (BSD)No license risk

Plugins

V6 plugin or capabilityNew SDK
SearchBoxNo drop-in plugin yet. Build on getSearchSuggestions()
Zoom and pan controlsMapLibre’s NavigationControl, through map.mapLibreMap
Minimap, DrawingToolsMapLibre community plugins
—Viewport places: search results that follow the visible map
—Map theme: the map’s colours from your brand colours, your site’s CSS, an image or a mood
—Map effects: bloom, depth of field, colour grade, tint, fog, vignette and your own GPU passes
—Fly-over: a camera that flies a route, framing the junctions ahead
—Route dragging: a route edited by dragging its stops and its line, re-planned as you drag
—Landmarks 3D: detailed 3D meshes of landmark buildings, in private preview
—Agent Toolkit: LLM tools that search, route and restyle the map from a conversation

Estimating migration effort

Use the table below to estimate the effort from the V6 features you use.

What you use todayEffortWhat to expect
Basic map display onlyLowReplace the map initialization (tt.map → TomTomMap). Update the CSS import. Typically under 1 day.
Map + markers + popupsLowMarkers use MapLibre’s API, with a nearly identical pattern. Popups work the same way. Expect a few hours of find-and-replace.
Map + routing displayLow–MediumRoute calculation returns GeoJSON natively, so you skip V6’s conversion step.
Map + traffic layersLow–MediumTraffic is integrated into the map module. Replace the stylesVisibility config with the new traffic module configuration.
Search / geocoding servicesLowImport from @tomtom-org/maps-sdk/services instead of tt.services. Fuzzy, category, nearby, geometry and along-route search become one discoverPlaces function. See the service mapping below. Responses are typed. Server-side Node.js code works with minimal changes.
EV routing / chargingHighLong-distance EV routing, vehicle consumption models and live charging availability have no equivalent. Search returns EV stations with their connectors and charging points.
Custom map styles (Map Styler)MediumThe map loads standard styles only. Start from the closest one and restyle it in code with styling knobs and setMapColors.
SearchBox pluginMediumNo drop-in SearchBox plugin yet. Build on getSearchSuggestions(), with the search playground as a starting point, or use a MapLibre geocoder plugin.
Minimap / DrawingTools pluginsMediumNo first-party equivalents yet. Use MapLibre community plugins.
Custom data visualizationLowYour layer specs carry over unchanged. Use MapLibre’s addSource/addLayer as before, or the Custom GeoJSON module, which keeps them across style switches and adds SDK events. GeoJSON heatmaps, clusters and choropleth maps work out of the box.
CDN-only deployment (no bundler)MediumThe new SDK requires npm and a bundler (Vite, Webpack). If your project has no build step, you need to add one. That’s a one-time setup cost.

For most integrations using map display, routing and traffic, expect 2–4 developer-days of migration work, with the 110+ runnable examples to check each feature against.


V6 API to new SDK

Find each V6 call you use and its replacement. Services come from @tomtom-org/maps-sdk/services and map classes from @tomtom-org/maps-sdk/map. None of them takes a key, because the global configuration holds it.

Map

V6New SDK
tt.map({ key, container, center, zoom })new TomTomMap({ mapLibre: { container, center, zoom } }) (TomTom map)
map.setStyle(style)await map.setStyle('streetDark'). Modules keep their data and settings (Map styles)
stylesVisibility, showTrafficFlow(), hideTrafficFlow()(await TrafficFlowModule.get(map)).setVisible(true) (Traffic flow)
showTrafficIncidents(), hideTrafficIncidents()(await TrafficIncidentsModule.get(map)).setVisible(true) (Traffic incidents)
showPOI(), hidePOI()(await POIsModule.get(map)).setVisible(false) (POIs)
map.setLanguage(language)map.setLanguage(language), or language in the global configuration for the map and services
map.setGeopoliticalView(view), tiles onlymap.setGeopoliticalView(view), or geopoliticalView in the global configuration for the map and services (Geopolitical views)
tt.Marker, tt.PopupMarker, Popup from maplibre-gl, or the Places module for many pins
map.addLayer(…) with a route’s toGeoJson()await (await RoutingModule.create(map)).showRoutes(routes) (Routes)
map.addLayer(…) with your own GeoJSONthe Geometries or Custom GeoJSON module, or map.mapLibreMap.addLayer(…)

Services

V6 tt.services.…New SDK
fuzzySearch, poiSearch, categorySearch, nearbySearchdiscoverPlaces, or discoverOnePlace for the best match
geometrySearchdiscoverPlaces({ geometries }) (Geometry search)
alongRouteSearchdiscoverPlaces({ route, maxDetourTimeSeconds }) (Along-route search)
autocompletegetSearchSuggestions
geocodegeocode, or geocodeOne for the best match
reverseGeocodereverseGeocode
placeByIdgetPlaceDetails
poiCategoriesgetPOICategories
additionalDatageometryData
calculateRoutecalculateRoute
calculateReachableRangecalculateReachableRange, or calculateReachableRanges for several
incidentDetails, incidentDetailsV5trafficIncidentDetails
matrixRouting, structuredGeocode, crossStreetLookup, staticImage, trafficFlowSegmentData, incidentViewport, longDistanceEVRouting, evChargingStationsAvailabilityNo equivalent yet. See What’s not yet available below

Responses come back as GeoJSON, so there is no toGeoJson(). Positions are [longitude, latitude] arrays throughout.


Step-by-step migration

Migrate incrementally, following only the sections your integration needs. The SDK works at two levels, which you can mix:

  • At the high level, map modules draw what services return, with no layer management of your own.
  • At the low level, map.mapLibreMap is the full MapLibre API. It is the most direct path for V6 code that called the map’s low-level methods (Using TomTom map with MapLibre directly). As you go, move each feature up to a module to get what the SDK adds.

Install the new SDK

Remove the legacy packages and CDN references, then install the new SDK:

# Remove legacy packages
npm uninstall @tomtom-international/web-sdk-maps @tomtom-international/web-sdk-services
# Install new SDK (peer dependencies installed automatically)
npm install @tomtom-org/maps-sdk

Also remove any V6 CDN <script> and <link> tags from your HTML. Your existing API key works with the new SDK.

Set up centralized configuration

The new SDK uses a singleton configuration pattern. Set your API key once at startup, and it applies to all maps and service calls.

Before (V6):

// API key passed to every call individually
var map = tt.map({ key: 'YOUR_API_KEY', container: 'map' });
tt.services.fuzzySearch({ key: 'YOUR_API_KEY', query: 'pizza' });

After:

import { TomTomConfig } from '@tomtom-org/maps-sdk/core';
// Set once at app startup — used by all maps and service calls
TomTomConfig.instance.put({
apiKey: 'YOUR_API_KEY',
language: 'en-GB',
});

You can still override the key per call or per map.

Migrate map initialization

Before (V6):

var map = tt.map({
key: 'YOUR_API_KEY',
container: 'map',
center: [4.8156, 52.4414],
zoom: 8,
});

After:

import { TomTomMap } from '@tomtom-org/maps-sdk/map';
const map = new TomTomMap({
mapLibre: {
container: 'map',
center: [4.8156, 52.4414],
zoom: 8,
},
});

Map options (center, zoom, bearing, pitch and all other MapLibre options) pass through unchanged under the mapLibre key.

Available styles:

V6 style nameNew SDK style ID
basic_main / basic_night, 2/basic_street-light / 2/basic_street-darkstreetLight / streetDark
driving_main / driving_nightstreetLightDriving / streetDarkDriving
hybrid_main, or labels_main over your own imagerystreetSatellite, which carries imagery, roads and labels in one style
—monoLight / monoDark, muted backdrops for your own data

V6’s separate trafficFlow, trafficIncidents and poi styles have no names of their own. You load the traffic parts with include (see Migrate traffic layers), and show, hide and filter the style’s own POIs with the POIs module.

const map = new TomTomMap({
style: 'streetDark',
mapLibre: { container: 'map' },
});

To switch style at runtime, call await map.setStyle('streetLight'). In V6, setStyle dropped every layer you had added. The SDK’s modules keep their data and settings and redraw on the new style (Map styles).

Migrate routing

Before (V6):

tt.services.calculateRoute({
key: 'YOUR_API_KEY',
locations: '4.89,52.37:4.88,52.36',
}).then(function(routeData) {
var geojson = routeData.toGeoJson();
map.addLayer({ /* ... */ });
});

After:

import { calculateRoute } from '@tomtom-org/maps-sdk/services';
import { RoutingModule } from '@tomtom-org/maps-sdk/map';
const routes = await calculateRoute({
locations: [
[4.89, 52.37], // [longitude, latitude]
[4.88, 52.36],
],
travelMode: 'car',
});
// Pass directly to RoutingModule — no .toGeoJson() or manual layer setup needed
const routingModule = await RoutingModule.create(map);
await routingModule.showRoutes(routes);

The response is standard GeoJSON, with no .toGeoJson() conversion step. RoutingModule handles the layers, default styling, waypoint icons and traffic-section colouring, so the route renders with a single call and looks production-ready by default. To change the colour scheme, the line widths or the waypoint markers, configure the module.

To manage the map layers yourself, closer to how V6 worked, pass the GeoJSON response directly to map.mapLibreMap.addSource / addLayer:

// Low-level approach — use the MapLibre instance directly
map.mapLibreMap.addSource('route', { type: 'geojson', data: routes });
map.mapLibreMap.addLayer({ id: 'route-line', type: 'line', source: 'route', paint: { 'line-color': '#0080ff', 'line-width': 4 } });

setStyle drops layers added this way, and they get no SDK events. The Custom GeoJSON module takes the same layer specs and gives you both.

Migrate search and geocoding

Search and geocoding responses are standard GeoJSON, so you can pass them directly to the map. PlacesModule renders search results on the map as styled, interactive markers with minimal setup. For a data-only integration, the GeoJSON features work equally well with any MapLibre data source.

Before (V6):

tt.services.fuzzySearch({
key: 'YOUR_API_KEY',
query: 'restaurant',
center: { lat: 52.37, lng: 4.89 },
}).then(function(results) { /* ... */ });

After:

import { discoverPlaces } from '@tomtom-org/maps-sdk/services';
const results = await discoverPlaces({
query: 'restaurant',
geoBias: { position: [4.89, 52.37] }, // [longitude, latitude]
});
// results is a typed GeoJSON FeatureCollection — access via results.features

For reverse geocoding:

Before (V6):

tt.services.reverseGeocode({
key: 'YOUR_API_KEY',
position: { lat: 52.37, lng: 4.89 },
}).then(response => { /* ... */ });

After:

import { reverseGeocode } from '@tomtom-org/maps-sdk/services';
const place = await reverseGeocode({ position: [4.89, 52.37] });
if (place.properties) {
const address = place.properties.address;
}

Migrate traffic layers

TrafficFlowModule and TrafficIncidentsModule connect live TomTom traffic data to the map with pre-styled, interactive layers. Incident markers are styled and clickable out of the box. You can filter them by magnitude, category or road type without writing any rendering logic, and customise the modules for a different look.

Before (V6):

var map = tt.map({
key: 'YOUR_API_KEY',
container: 'map',
stylesVisibility: { trafficFlow: true, trafficIncidents: true },
});
// Toggle later:
map.showTrafficFlow();
map.hideTrafficFlow();

After:

import { TomTomMap, TrafficFlowModule, TrafficIncidentsModule } from '@tomtom-org/maps-sdk/map';
// Include traffic layers when initializing the map style
const map = new TomTomMap({
style: { type: 'standard', id: 'streetLight', include: ['trafficFlow', 'trafficIncidents'] },
mapLibre: { container: 'map' },
});
const trafficFlow = await TrafficFlowModule.get(map, { visible: true });
const trafficIncidents = await TrafficIncidentsModule.get(map, { visible: true });
// Toggle visibility
trafficFlow.setVisible(false);
trafficIncidents.setVisible(true);
// Typed filtering — show only major and moderate incidents
trafficIncidents.updateConfig({
filters: { magnitudes: { show: 'only', values: ['major', 'moderate'] } },
});

Migrate custom styling

In V6, you restyled the map by editing a style in Map Styler and loading its JSON. The new SDK loads standard styles only. Instead, the Styling Foundations module changes a style at runtime, and the change survives style switches.

import { setKnob, StylingFoundationsModule, stylingFoundationsKnobCatalogue } from '@tomtom-org/maps-sdk/map';
const styling = await StylingFoundationsModule.get(map);
setKnob(styling, stylingFoundationsKnobCatalogue, 'labels.sizeFactor', 1.2); // every base-map label 20% bigger
setKnob(styling, stylingFoundationsKnobCatalogue, 'roads.widthFactor', 0.8); // thinner roads, hierarchy kept
styling.setMapColors({ land: '#f3f5f7', water: '#accbe2', roadMajor: '#a1b8ce' });

The map theme plugin derives those colours for you from your brand colours, your site’s CSS or an image. exportStyle saves the result as a style file.

Update CSS

Before (V6):

<link rel='stylesheet' href='https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/.../maps.css'>

After:

The SDK applies the MapLibre CSS itself, from its own bundle. You only need this import to use the CSS of the MapLibre version you installed.

// In your JS/TS entry point
import 'maplibre-gl/dist/maplibre-gl.css';

Performance improvements

Bundle size

With modular ESM and tree-shaking enabled, you ship only the code you use.

ComponentV6 (min + gzip)New SDK
Maps library~720 KB monolithic~220 KB MapLibre + SDK modules (tree-shaken)
Services library~175 KB monolithicImport only what you use (significantly smaller)
Total (maps + routing)~895 KBSubstantially reduced

Rendering engine

  • MapLibre GL JS is actively maintained with performance improvements in every release
  • Vector tile rendering runs on WebGL 2, which the map requires. In a browser without it, new TomTomMap throws a TomTomMapError with the code WEBGL_UNSUPPORTED
  • Style part lazy loading loads layers on demand, so the map displays sooner
  • Layer group visibility animation gives you smooth transitions

API response handling

  • Native GeoJSON responses eliminate the serialisation/deserialisation overhead of V6’s .toGeoJson() conversion
  • Typed responses are checked at compile time, so fewer errors reach runtime

Future-proof with Orbis Maps

The new SDK is the first to support TomTom Orbis Maps natively. Orbis Maps is TomTom’s map data platform, and it combines open data (OpenStreetMap) with TomTom’s proprietary data.

What Orbis Maps deliversDetails
Fresher dataCommunity-contributed open data combined with TomTom’s own map-making operations for faster update cycles
Richer detailMore granular POI data, improved address precision and better coverage in emerging markets
Same APIs, better dataOrbis Maps work with the same Routing, Search and Traffic APIs you already use. The data quality improves, and your code stays the same
Forward investmentTomTom’s roadmap is centred on Orbis. New features, coverage improvements and data quality investments will land on Orbis first

After migrating, your application gets every Orbis Maps improvement automatically.


Pricing and commercial impact

  • Your API key stays the same. You don’t need a new key.
  • Per-call pricing stays the same. Both SDKs call the same backend APIs, billed at the same rate whichever SDK made the call.
  • Contract terms stay the same. Your existing agreement covers the new SDK, with no amendment.
  • The free evaluation plan’s daily requests cover prototyping and testing the migration.
  • Tailored enterprise plans, QPS limits and support levels carry over.

Using TomTom map with MapLibre directly

TomTomMap exposes the underlying MapLibre GL JS instance as map.mapLibreMap. Through it, the full MapLibre API (addSource, addLayer, on, queryRenderedFeatures and everything else) works exactly as in a standalone MapLibre project.

This is the most direct migration path for V6 code that calls TomTom’s tt.map methods directly. Replace tt.map(...) with new TomTomMap(...), swap the CSS import and then migrate the rest of the codebase incrementally. Each time a feature is ready for a high-level module, replace its manual layer code. Everything else keeps working unchanged through map.mapLibreMap.

import { TomTomMap } from '@tomtom-org/maps-sdk/map';
const map = new TomTomMap({ mapLibre: { container: 'map' } });
map.mapLibreMap.on('load', () => {
// Standard MapLibre API
map.mapLibreMap.addSource('my-data', { type: 'geojson', data: myGeojson });
map.mapLibreMap.addLayer({ id: 'my-layer', type: 'fill', source: 'my-data' });
});

Custom data visualisation, such as heatmaps, clustering, choropleth maps and deck.gl layers, works through map.mapLibreMap without any SDK-specific code. You can use the high-level modules and the raw MapLibre API on the same map instance at once. For GeoJSON layers, the Custom GeoJSON module takes the same layer specs and restores them after every style switch.


What’s not yet available

The new SDK is in Public Preview (0.x versions). Until 1.0, a minor release can carry a breaking change, and Upgrading to 1.0 lists each one. Some V6 capabilities are not yet available as first-party SDK features:

  • SearchBox plugin - No drop-in replacement yet. Build on getSearchSuggestions(), starting from the search playground.
  • Minimap / DrawingTools plugins - Use MapLibre community plugins, listed in awesome-maplibre.
  • Turn-by-turn navigation UI - In-car navigation UI components are not yet available.
  • Long-distance EV routing, vehicle consumption models and live EV charging availability - Not offered. Search returns EV stations with their static connectors and charging points.
  • Matrix routing, structured geocoding, cross-street lookup, static map images, traffic flow segment data and incident viewport - No SDK function yet, so call those TomTom APIs over HTTP. For structured geocoding, pass the full address to geocode.
  • CDN-only deployment - The new SDK requires a bundler (Vite, Webpack, etc.).

For GeoJSON data that no first-party module covers, use the Custom GeoJSON module. For anything else, map.mapLibreMap is the full MapLibre GL JS API.


Further reading