Map modules
Map Modules are self-contained extensions that add specialized functionality to a TomTomMap instance.
Each module provides focused capabilities for different mapping needs — from displaying traffic information to handling user-generated content — while following a consistent pattern for initialization, configuration, and lifecycle management that makes them easy to integrate and use together.
Key features
- Composition: Modules can be combined to work together seamlessly. Whether a given module type can be instantiated more than once on the same map depends on who owns the layers it controls — see Types of modules below.
- Data management: Modules handle their own data sources and rendering
- Style integration: Modules automatically integrate with map styles and themes
- Statefulness: Modules maintain their own state and configuration independently. Modules restore their state when the map style changes.
- One configuration surface: every module takes its configuration at creation and through
applyConfig(config)(a whole configuration — see the module for whether it replaces or merges with the current one),updateConfig(partial)(changes the given properties and keeps the rest, the same on every module) andresetConfig();getConfig()reads it back andevents.on('config-change', …)reports every change. - Smart event handling: Modules provide their own event systems for user interactions with seamless mapping to the original typed data.
- Service integration: Seamless integration with TomTom services for added data such as places, routes and geometries
- Lazy loading: Modules are loaded only when needed for optimal performance
Types of modules
There are two types of modules in the TomTom Maps SDK, depending on who owns the sources and layers the module controls. Ownership decides both the factory you call and how many instances make sense on one map.
Style-owned modules — get(map, config?)
These modules do not display data of their own. They control sources and layers that the map style already provides — the base map, POI symbols, the traffic tile layers, the terrain elevation — under source and layer IDs that are fixed and global to the style.
A style-owned module is therefore a shared controller, not a piece of content. get() is a lookup, and quite literally so: the SDK keeps one instance per map, so calling it twice returns the same module. Two components can each ask for the terrain without coordinating, and neither has to hoist a shared reference.
Calling get(map) with no configuration is a plain accessor — it changes nothing. Calling it with a configuration applies that configuration to the instance that already exists.
To handle events for only part of what a style-owned module covers, scope the events rather than creating a second module — see Scoped events.
Data-owned modules — create(map, config?)
These modules bring their own data. They add the GeoJSON sources, layers and sprite images they need and own them for their whole lifetime, with every identifier suffixed per instance.
Instances are therefore fully independent: create() builds a new module every time, and stacking several of them on one map — one set of places per search, one route per plan — is a supported thing to do. Nothing is shared or reused between them.
Per-module reference
| Module | Kind | Factory | Instances per map | Why |
|---|---|---|---|---|
| BaseMapModule | Style-owned | get() |
One per map | One global vector-tile source. To act on part of the map, scope its events with events.where({ layerGroups }) rather than creating a second module. |
| POIsModule | Style-owned | get() |
One per map | Fixed POI source and layer IDs; visibility and category filters are global to the map. |
| TrafficFlowModule | Style-owned | get() |
One per map | Fixed traffic-flow source; visibility and filters are global to the map. |
| TrafficIncidentsModule | Style-owned | get() |
One per map | Fixed traffic-incident source; visibility and filters are global to the map. |
| TerrainModule | Style-owned | get() |
One per map | Fixed elevation source; hillshade visibility and the 3D surface are global to the map. |
| PlacesModule | Data-owned | create() |
Multiple | Owns its own place source, layers and pin images, suffixed per instance. |
| RoutingModule | Data-owned | create() |
Multiple | Owns its own route, waypoint and section sources and layers, suffixed per instance. |
| GeometriesModule | Data-owned | create() |
Multiple | Owns its own geometry and label sources, suffixed per instance. |
| CustomGeoJSONModule | Data-owned | create() |
Multiple | Owns the sources and layers declared in its own sources config, suffixed per instance. |
| TrafficIncidentOverlayModule | Data-owned | create() |
Multiple | Owns the GeoJSON source and layers for the incidents you fetched yourself. |
| TrafficAreaAnalyticsModule | Data-owned | create() |
Multiple | Owns the grid/heatmap source and layers it renders your analytics into. |
Who owns what
Everything visible on the map has exactly one owner, and the owner follows from who owns the layers:
| You want to change… | Owner | How |
|---|---|---|
| Whether something the loaded style draws is shown — a base-map layer group, the traffic tiles, a POI category, the hillshade, the 3D surface | The style-owned module for that part | setVisible, filter, filterCategories, setHillshadeVisible, setElevationEnabled |
| How the style draws it — label and icon sizes, road widths, the ten map colours, traffic colours, hillshade lighting, projection and sky | The Styling module | set(knob, value), applyPreset, setMapColors |
| Anything a data-owned module draws itself — routes, places, geometries, your GeoJSON, the incident overlay, area analytics | That module, through its own configuration | create(map, config), applyConfig / updateConfig, and its part-setters |
Two consequences:
- The rows do not cross. Styling knobs never touch a data-owned module's layers, and a data-owned module never restyles the base map under it: recolouring a route is
RoutingModuleconfiguration, recolouring the roads it runs on iscolors.roadMajor. - Where the first two rows meet, the later call wins. A
basemap.<group>toggle knob (buildings.footprintsandbuildings.3dfor the two building groups) andBaseMapModule.setVisibleset the same layer visibility;pois.zoomShiftrewrites the POI layer filters thatPOIsModule.filterCategoriesnarrows, and the two compose in either order.
Each module guide opens with a What this module owns line that applies this rule to that module.
List of modules
Base map module
A BaseMapModule provides visibility and events for layer groups of the base map.
import { BaseMapModule } from '@tomtom-org/maps-sdk/map';
const baseMapModule = await BaseMapModule.get(map);
// Toggle visibility, for the whole base map or for specific layer groups
baseMapModule.setVisible(true);
baseMapModule.setVisible(false, { layerGroups: { mode: 'include', names: ['borders', 'buildings2D'] } });
Learn more about Base Map Module →
Places module
A PlacesModule handles search results visualization and place information display.
import { PlacesModule } from '@tomtom-org/maps-sdk/map';
import { discoverPlaces } from '@tomtom-org/maps-sdk/services';
// Initialize places module
const placesModule = await PlacesModule.create(map);
// Search and display results
const results = await discoverPlaces({ query: 'restaurants near me' });
await placesModule.show(results);
// Handle place interactions — `events.places` is the pins alone, typed as Place
placesModule.events.places.on('click', (place) => {
console.log('Selected place:', place.properties.title);
});
Learn more about Places Module →
POIs module
A POIsModule controls the display and events for Points of Interest with category-based filtering and styling.
import { POIsModule } from '@tomtom-org/maps-sdk/map';
// Display specific POI categories
const poisModule = await POIsModule.get(map, {
filters: {
categories: { show: 'all-except', values: ['CHARGING_LOCATION'] },
},
});
Learn more about POIs Module →
Routing module
A RoutingModule controls the display of routes, waypoints, and navigation instructions, and user events on such parts.
import { RoutingModule } from '@tomtom-org/maps-sdk/map';
import { calculateRoute } from '@tomtom-org/maps-sdk/services';
// Initialize routing module
const routingModule = await RoutingModule.create(map);
// Calculate and display route
const route = await calculateRoute({
geoInputs,
});
await routingModule.showRoutes(route);
Learn more about Routing Module →
Traffic flow module
The TrafficFlowModule displays real-time traffic flow information with color-coded speed indicators.
import { TrafficFlowModule } from '@tomtom-org/maps-sdk/map';
// Add traffic flow visualization
const trafficFlowModule = await TrafficFlowModule.get(map);
// Control traffic display
trafficFlowModule.setVisible(true);
// Configure traffic styling
trafficFlowModule.filter({
any: [{ showRoadClosures: 'only' }],
});
Learn more about Traffic Flow Module →
Traffic incidents module
The TrafficIncidentsModule shows traffic incidents like accidents, road closures, and construction.
import { TrafficIncidentsModule } from '@tomtom-org/maps-sdk/map';
// Display traffic incidents
const trafficIncidentsModule = await TrafficIncidentsModule.get(map, {
icons: { visible: false },
filters: { any: [{ magnitudes: { show: 'all-except', values: ['minor'] } }] },
});
Learn more about Traffic Incidents Module →
Geometries module
The GeometriesModule displays custom geometric data like polygons, lines, and markers.
import { GeometriesModule } from '@tomtom-org/maps-sdk/map';
// Initialize geometries module
const geometryModule = await GeometriesModule.create(map);
const geometryToSearch = await geometryData({ geometries: location });
await geometryModule.show(geometryToSearch);
Learn more about Geometries Module →
Custom GeoJSON module
The CustomGeoJSONModule renders your own GeoJSON data with typed sources, clustering, custom images, and style-change restoration.
import { CustomGeoJSONModule } from '@tomtom-org/maps-sdk/map';
const customModule = await CustomGeoJSONModule.create(map, {
sources: {
heatmap: { layers: [{ type: 'heatmap' }] }
}
});
await customModule.show(heatmapData, 'heatmap');
Learn more about Custom GeoJSON Module →
Traffic incident overlay module
The TrafficIncidentOverlayModule renders a specific set of incidents you fetched yourself, rather than the live vector-tile layer.
import { TrafficIncidentOverlayModule } from '@tomtom-org/maps-sdk/map';
import { trafficIncidentDetails } from '@tomtom-org/maps-sdk/services';
const overlay = await TrafficIncidentOverlayModule.create(map);
const result = await trafficIncidentDetails({ bbox });
await overlay.show(result);
Learn more about Traffic Incident Overlay Module →
Traffic area analytics module
The TrafficAreaAnalyticsModule visualizes aggregated traffic statistics for an area as a hexgrid, square grid, or heatmap.
import { TrafficAreaAnalyticsModule } from '@tomtom-org/maps-sdk/map';
const analyticsModule = await TrafficAreaAnalyticsModule.create(map, {
displayMode: 'hexgrid-3d',
activeMetric: 'congestionLevel',
});
await analyticsModule.show(analyticsResult);
analyticsModule.setMetric('speed');
Learn more about Traffic Area Analytics Module →
Terrain module
The TerrainModule draws the relief of the elevation data: hillshade shading, and the map surface raised in 3D.
import { TerrainModule } from '@tomtom-org/maps-sdk/map';
const terrain = await TerrainModule.get(map, { hillshade: true });
// Raise the surface in 3D, for a pitched camera
terrain.setElevationEnabled(true);