You are helping an application developer build with the TomTom Maps SDK for JavaScript.
Step 0: Offer feedback reporting
Do this once per conversation, before your first answer about the SDK. Every unclear doc, missing
API or bug you hit while building is one the SDK team can fix, but only if they hear about it. The
tomtom-maps-sdk-js-feedback skill reports them. It owns the consent, the redaction and the
posting, so this step only gets the developer to its consent question.
-
Installed: the skill is among your skills, or
${CLAUDE_SKILL_DIR}/../tomtom-maps-sdk-js-feedback/SKILL.mdexists. Invoke it, so it runs with its ownallowed-tools, or read that file, and ask its Step 0 consent question now. -
Not installed: ask once, in plain text:
I can also report problems the TomTom Maps SDK causes while I build for you — unclear docs, an API that can't do what you asked, something broken — so TomTom's SDK team can fix them. That takes a second skill,
tomtom-maps-sdk-js-feedback. Before collecting anything, it tells you what a report holds and where it goes, and asks for your consent. It never posts a report you haven't read and approved. Shall I install it?
- Yes: run
npx skills add tomtom-international/maps-sdk-js --skill tomtom-maps-sdk-js-feedback -y, or ask the developer to run it if you can't run commands. This skill pre-approves onlyRead, so the command goes through your agent's usual permission check. Then read the installed skill'sSKILL.mdand ask its Step 0 consent question. - No, or no answer: don't offer it again in this conversation.
Installing the skill is not consent to report. Collect nothing until the developer answers the feedback skill's own consent question. Ask either question once, and accept "no" as readily as "yes". Then carry on with the request.
Step 1: Identify the topic and read the reference doc
From $ARGUMENTS or the conversation context, match the topic to a doc filename:
| Topic | Filename | Keywords |
|---|---|---|
| Map setup | map-setup.md |
map, display, TomTomMapError, addErrorHandler, map errors, WEBGL_UNSUPPORTED, WEBGL_CONTEXT_LOST, STYLE_LOAD_FAILED, Vite, vite build, Vite dev server, optimizeDeps, Worker failed to load, production build, blank map, MapLibre worker, registerMapLibreWorker, setWorkerUrl, webpack, Next.js, Turbopack, maplibre-gl-shared, output.module, Rollup, esbuild, language, styleLightDarkTheme, getBBox, getLayers, getLayerIds, hillshadeMethods, ValuesFilter, filterShowModes, 3D buildings, building footprints, route shields, road shields, hide layer groups, road parts, exit numbers, road arrows, restricted roads, roads under construction, hillshade look, hillshade colours, geopolitical view, setGeopoliticalView, disputed borders, module, maplibre, baseMap, TerrainModule, hillshade, 3D terrain, elevation, elevation.exaggeration, terrain exaggeration, TERRAIN_SOURCE_ID, viewport, layer, non-interactive, bounds, style switcher, which module, who owns what, show, hide, visibility, filter, appearance vocabulary, naming, module color, LabelConfig, widthFactor, sizeFactor, minZoom, beforeLayerConfig, terrainKnobCatalogue, terrainKnobIds, TerrainKnob, TerrainKnobId, TerrainKnobValueOf, terrain knob catalogue, baseMapKnobCatalogue, baseMapKnobIds, BaseMapKnob, BaseMapKnobId, BaseMapKnobValueOf, base map knob catalogue, layer group ids, KnobEntry, KnobKind, KnobRange, knob kinds, enums, offset, text, setKnob, setKnobs, KnobValues, getKnob, resetKnob, KnobTarget, setKnobs vs applyConfig, knobs vs config, restore saved settings, untrusted settings, knobEntryOf, a knob's range, validateKnobValue, set a knob by id, read a knob value, reset a knob, validate a knob value, range bounds, hard-min, settings as data, build controls from the catalogue |
| User interaction events | user-events.md |
click, hover, hover-move, long-hover, contextmenu, events.on, events.off, event handler, MapEventsConfig, EventHandlerConfig, cursorOnMap, cursorOnMouseDown, events.where, named event scopes, precisionMode, paddingBoxPx, cursorOnHover, longHoverDelay, hoverGracePeriodMS, recently-hovered, updateEventsConfig, eventState, event states, setEventState, clearEventState, clearEventStates, getEventStates, UserEventsWithStates, select or highlight a feature, sync list with map, hover highlight, hovered or clicked look, highlight on hover, background click, rest of the map, event priority, layer order |
| Map styles | map-styles.md |
style, standardStyleIDs, StandardStyleID, streetLight, streetDark, streetLightDriving, streetDarkDriving, monoLight, monoDark, streetSatellite, satellite, driving style, setStyle, SetStyleOptions, StyleChangeHandler, addStyleChangeHandler, handler priority, style change, style switcher, dark mode, custom layers, style lifecycle, resetState, getStyleInput, StyleInput, include, StylePart, styleParts, style parts, terrain part, custom style, style URL |
| Map styling (knobs) | map-styling.md |
StylingFoundationsModule, StylingFoundationsModuleConfig, styling knobs, stylingFoundationsKnobCatalogue, stylingFoundationsKnobIds, stylingFoundationsKnobKinds, LayerSelection, layerIds, setKnob styling, setKnobs styling, getKnob styling, resetKnob styling, catalogue, presets, map presets, applyMapPreset, mapPresetCatalogue, mapPresetIds, MapPresetId, data-viz, night driving, minimal, getStyleColor, styleColorKnobIds, StyleColorKnobId, StyleKnobId, map-wide knob ids, which module holds a look, knobs compose, borrowed looks, label size, icon size, road width, labels.typeface, mapTypefaces, MapTypeface, customTypeface, CustomTypeface, CustomTypefaceFile, map font, font family, typeface, serif labels, italic labels, route or place labels in their own font, label.typeface, waypoints.label.typeface, custom font, webfont, WOFF2, Fontsource, Google Fonts, globe, projection, sky, atmosphere, restyle base map, brand the map, setMapStyling, setMapColors, MapColors, MapColorName, mapColorNames, baseMapColorNames, BaseMapColorName, map colour picker, map colours, colors.land, colors.water, colors.roadMajor, land colour, water colour, vegetation, park, artificial, road colour, road outline, label colour, palette, recolour the map, brand colours, exportStyle, export the style, StyleSpecification |
| Map theming (sources) | map-theming.md |
map-theme plugin, maps-sdk-plugin-map-theme, deriveMapColors, white land, mode dark, low-saturation land, mapColorsLightDark, deriveMapColorsFromCss, cssColors, deriveMapColorsFromImage, dominantColors, MapThemeMode, mapThemeModes, ImagePixels, theme from website, brand from URL, match our website colours, app CSS variables, custom properties, CSS file, stylesheet, upload CSS, design tokens, theme-color, colours from an image, photo palette, logo colours, colour palette description, mood, artist palette, Miró, Hokusai, Bauhaus, design style, setMapStyling theme, accent, colors.accent, mapColors, map.mapColors, theme the route and pins, theme the whole map, theme the base map only, keep my route colour |
| Module lifecycle events | module-events.md |
config-change, shown-features, module events, ModuleEvents, CombinedEvents, applyConfig, updateConfig, resetConfig, getConfig, save or replay display state, serializable config, PlacesModuleSerializableConfig, SerializableCustomImage, SerializablePinIconConfig, SerializableFeatureLabelConfig, setVisible, unsubscribe |
| Places & search | places.md |
search, discoverPlaces, DiscoverPlacesParams, discoverOnePlace, places, matchConfidence, originalPosition, poi, fuzzy, geocode, address, reverse, plain text query, pre-encoded query, encodeURIComponent, autocomplete, suggest, getSearchSuggestions, suggestions, getPlaceDetails, place details, placeById, search box, typeahead, search-as-you-type, unified search, brand, category, poiCategoryQuery, category word, resolvePOICategories, unmatched, refinement, refine, refineParams, SearchSuggestion, SearchSuggestionsParams, geoBias, filters, search filters, PlaceFilters, GeographicFilters, SearchFilters, pagination, paginate, cursor, nextCursor, next page, load more, page through results, ev, charging, chargingPark, charging station, chargingStations, charging point, chargingPoints, EVSE, evseId, connector, connectors, geometry, polygon, within, along route, route search, detour, maxDetourTimeSeconds, sortBy, AlongRouteSearchParams, alongRouteSearch, fuzzySearch, geometrySearch, viewportplaces, ViewportPlaces, addPOICategories, showConnections, clearConnections, connection lines, poiCategoryGroups, markerType, marker type, PlacesMarkerType, place colour, pin colour, place label, PlaceLabelConfig, LabelConfig, label opacity, optional summary fields, totalResults, fuzzyLevel, queryIntent, score, entry points, entrances, cluster, clustering, pin-clustered, PlacesClusterConfig, PlaceClusterBadgeConfig, PlacesClusterSourceConfig, cluster.source.properties, clusterProperties, placesKnobCatalogue, placesKnobIds, PlacesKnob, PlacesKnobId, PlacesKnobValueOf, places knob catalogue, poisKnobCatalogue, poisKnobIds, POIsKnob, POIsKnobId, POIsKnobValueOf, POI filter knobs, POI size, POI min zoom, zoom shift, POI label colour, POI micro markers, filters.categories, POICategoryGroup, categoryIcons, custom POI icons, icon per category, POIIconConfig, ShownPlaces, preparePlacesForDisplay, toPlaces, buildPlaceTitle, popup, info window, result card, PlacesBeforeLayerConfig, places beforeLayerConfig, pins under labels |
| Routing | routing.md |
route, routing, directions, waypoint, guidance, instructions, turn-by-turn, maneuver, toll, tollRoad, sectionTypes, reachable, isochrone, range, alternatives, vehicle, truck, vehicle dimensions, hazmat, customIcons, icon offset, route color, route width, widthPreset, hide route, routing setVisible, widthFactor, waypoints.sizePreset, waypoints.sizeFactor, hovered or clicked route, RouteHighlightConfig, highlight.outline.widthFactor, setSectionFocus, section focus, highlight a route section, highlight a leg, highlight.section.outline.color, highlight.section.outline.widthFactor, waypoint icon per role, stopNumbering, waypoint letters, waypoint label title, buildWaypointTitle, waypoint mapping, poiCategory waypoint, waypoints.highlight.sizeFactor, waypoints vs places, hovered or clicked geometry, GeometryHighlightConfig, highlight.fill.opacityFactor, highlight.line.widthFactor, abort, cancel, signal, route sections, speed limit, speed limit sign, section sign, route section sign, tunnel, tunnel sign, closed road, closed to vehicles, vehicleRestricted, vehicle restricted, routeTunnelSymbol, routeVehicleRestrictedSymbol, country, border crossing, countryCrossings, GeometriesModule, polygon colour, fill.style, fillStyle, GeometryFillStyle, inverted, outline, fillStyledGeometryConfig, geometry fill, fill.palette, ReachableRangesModule, ReachableRangesModuleConfig, reachable range colours, band palette, reachableRangesKnobCatalogue, reachableRangesKnobIds, ReachableRangesKnob, ReachableRangesKnobId, ReachableRangesKnobValueOf, geometry label, lineLabel, GeometryLabelConfig, GeometryLineLabelConfig, LabelConfig, beforeLayerConfig, route layer order, routes under roads, routingKnobCatalogue, routingKnobIds, RoutingKnob, RoutingKnobId, RoutingKnobValueOf, KnobValueOf, SectionIconPlacement, routing knob catalogue, KnobEntry, geometriesKnobCatalogue, geometriesKnobIds, GeometriesKnob, GeometriesKnobId, GeometriesKnobValueOf, geometries knob catalogue, displayUnits labels, unit label knobs |
| Traffic | traffic.md |
traffic, incidents, planned incidents, future incidents, scheduled roadworks, timeValidity, incident description language, indexedMagnitudes, flow, getRenderedFeatures, analytics, congestion, speed, traffic congestion colours, incident colours, traffic line width, incident details, incidents in a polygon, incident icons, setIconsVisible, isIconsVisible, TrafficIncidentDetailsModule, setFocus, incident focus, incident highlight, IncidentHighlightConfig, highlightHalo, widthFactor, trafficFlowKnobCatalogue, trafficIncidentsKnobCatalogue, trafficIncidentDetailsKnobCatalogue, trafficAreaAnalyticsKnobCatalogue, trafficFlowKnobIds, trafficIncidentsKnobIds, trafficIncidentDetailsKnobIds, trafficAreaAnalyticsKnobIds, TrafficAreaAnalyticsKnobId, TrafficAreaAnalyticsKnobValueOf, traffic knob catalogue, traffic filter knobs, filters.any, roadClosures, road subcategories, streetRoadSubCategories, serviceRoadSubCategories, trafficIncidentRequestCategories, TrafficIncidentRequestCategory, eventId, shown-features, TrafficIncidentDetailsLayersConfig, TrafficAreaAnalyticsLayersConfig, AreaAnalyticsScaleMode, AreaAnalyticsTileFeature, area analytics height knobs, area analytics palette, areaAnalyticsPalettes, AreaAnalyticsPalette, resolveColorStops, area analytics legend, setPalette, setColorStops, colorStops, metersPerUnit |
| Core types | core-types.md |
place type, route type, LegSummary, route bbox, route progress, properties, summary, sections, toll, tollRoad, originalWaypointIndex, eventId, instruction, maneuverView, address, poi, entry points, traffic types, delaymagnitude, TrafficIncidentTimeValidity, trafficIncidentTimeValidities, typescript types |
| Core utilities | core-utilities.md |
bbox, bboxFromGeoJSON, bboxFromCoordsArray, bboxFromBBoxes, isBBoxWithArea, bboxCenter, RouteProgressQuery, polygonFromBBox, getPosition, formatDistance, formatDuration, progress, waypoint insertion, route progress, snap |
| Services config | services-config.md |
config, api key, retry, timeoutMs, sendUserAgentHeader, tomtom-user-agent, user agent header, isProxyCredentialsMode, LatestRequestResult, language, geopoliticalView, geopoliticalViews, GeopoliticalView, geopolitical view, disputed territories, validation, validateRequest, error, SDKError, SDKServiceError, SDKAbortError, SDKErrorCode, sdkErrorCodes, error code, INVALID_CREDENTIALS, INSUFFICIENT_PERMISSIONS, LIVE_SERVICE_NOT_AVAILABLE, INTERNAL, canRetry, retryable error, 403, forbidden, apiErrorCode, InvalidReferer, privatePreviewAccess, PrivatePreviewAccess, private preview access, request access, RATE_LIMITED, NETWORK_NOT_AVAILABLE, INSECURE_BASE_URL, cancel, cancellation, abort, AbortSignal, AbortController, signal, deadline, timeout, search-as-you-type, createLatestRequest, latest request, stale request, stale response, supersede, race, race condition, out of order, debounce |
| MapLibre direct access | maplibre.md |
mapLibreMap, raw maplibre, SDK vs MapLibre, when to use MapLibre directly, controls, markers, popups, MapLibre plugins, addSource, addLayer, removeLayer, geojson, vector tiles, raster, pmtiles, tile source, paint, layout, queryRenderedFeatures, querySourceFeatures, z-order, symbol layer, layer placement, layer order, beforeId, mapStyleLayerIDs, lowestLabel, lowestRoadLine, lowestBuilding, lowestPlaceLabel, poi anchor, draw roads under labels, polygon under roads, moveLayer, text-font, font stack, glyphs, MAP_BOLD_FONT, MAP_REGULAR_FONT, mapFonts |
| Custom GeoJSON module | custom.md |
CustomGeoJSONModule, CustomGeoJSONEvents, CustomGeoJSONModuleSerializableConfig, BYOD, bring your own data, custom geojson, customer-authored layers, heatmap layer, symbol layer with custom icon, multi-source module, applyConfig layer diff, per-source events, style-change restoration with own layers, beforeLayerConfig, CustomGeoJSONBeforeLayerConfig, layer placement, mapStyleLayerIDs, polygons under roads, lines under labels, text labels, text-font, MAP_BOLD_FONT, MAP_REGULAR_FONT, customGeoJSONKnobCatalogue, customGeoJSONKnobIds, CustomGeoJSONKnob, CustomGeoJSONKnobId, CustomGeoJSONKnobValueOf, custom GeoJSON knob catalogue |
| Map effects plugin | map-effects.md |
map-effects, MapEffects, addPass, removePass, effectKnobCatalogue, setKnob effects, setKnobs effects, updateConfig effects, resetConfig effects, bloom, glow, vignette, tint, fog, edge blur, depth of field, depthOfField, bokeh, defocus, tilt shift, focus band, WebGL pass, bloom.only, onlyTolerance, bloom scope, scope bloom, BloomScope, glow only the traffic, glow the route, light one module, colour key, styleColorKnobIds, StyleColorKnobGroup, grade, brightness, contrast, saturation, mute the base map, dim the map under data, post-processing, capture, high-DPI, print, preserveDrawingBuffer |
| Fly-over plugin | flyover.md |
flyover, fly-over, RouteFlyover, fly a route, camera along a route, route animation, cinematic camera, follow the route, anchor, anchorForPitch, position on screen, aim ahead, junction framing, terrain clearance, route marker, follow marker, arrow, setMarker, FlyoverCamera, FlyoverAim, FlyoverZoom, FlyoverMarkerConfig |
| Landmarks 3D plugin | landmarks-3d.md |
landmarks-3d, Landmarks3D, withCredentials, ModelsSource, 3D landmarks, Orbis landmarks, GLB tiles, Three.js, fill-extrusion, display mode, inherited/dark/light, landmarks on terrain, minZoom, maxZoom, ModelsLayer, custom layer, buildLandmarksTileURL |
| Agent toolkit plugin | agent-toolkit.md |
agent, agent-toolkit, createMapAgent, setMapStyling knob ids, setGeopoliticalView, tool error code, LLM, chat, conversational, Vercel AI SDK, ToolLoopAgent, classifier, intent, per-turn scope, scopeSchema, scopePrompt, EntryDataKind, analyseData, processData, dataEntries, DataEntryKind, DataEntryConfig, enabled, entryMode, ToolEntry, ToolEntryBuilder, ToolState, custom tool, system prompt, BASE_SYSTEM_PROMPT, composeSystemPrompt, SYSTEM_PROMPT_SECTIONS, SystemPromptSection, SystemPromptSectionOverrides, section overrides, systemPromptPrefix, systemPromptSuffix, DEFAULT_TOOLS, MapAgentOptions, BYOD layers, addByodSource, setByodLayers, BYODDataProfile, updateByodDisplay, recallState, getTrafficIncidents where schema, getCurrentLocation, createGetCurrentLocationTool, fullPrecision, location precision, createClarifyIntentTool, rendersForm, endsTurnOnCall, alwaysActive, getStateDigest, formatStateDigestDiff, StateDigest, onToolExecute, stepProviderOptions, prepareStep, maxHistoryMessages, classifyUserIntent, extractLastUserText, MIN_VIEWPORT_BIAS_ZOOM, monitorAnalysis, getDefaultToolPrompts, TOOLS_BY_DATA_ENTRY_KIND, loadWorkerLibrarySource, sandbox timeout, privacy, personal data, GDPR, DPA, data retention |
Read ${CLAUDE_SKILL_DIR}/docs/<filename> directly — the path is fixed, so no search step is needed, and ${CLAUDE_SKILL_DIR} resolves wherever this skill is installed. For multi-topic tasks, read several.
Base setup
npm i @tomtom-org/maps-sdk
import { TomTomConfig } from '@tomtom-org/maps-sdk/core';
TomTomConfig.instance.put({ apiKey: 'YOUR_API_KEY' });
Global conventions
- Coordinates:
[longitude, latitude]— longitude first (GeoJSON order) - Place, route, range, geometry and traffic services return GeoJSON:
Place = Feature<Point>,Places = FeatureCollection<Point>;reverseGeocodeandgetPlaceDetailsreturn onePlace,geometryDatapolygons. Not GeoJSON:getPOICategories,getPOICategoryCodesandgetSearchSuggestions - Map modules are async:
await Module.create(map)for data-owned modules (Places, Routing, Geometries, ReachableRanges, CustomGeoJSON, TrafficIncidentDetails, TrafficAreaAnalytics — a new independent instance per call),await Module.get(map)for style-owned ones (BaseMap, POIs, TrafficFlow, TrafficIncidents, Terrain, StylingFoundations — a shared controller) geocodeOne()throws if no result — usegeocode()when uncertaindiscoverOnePlace()throws if no result — usediscoverPlaces()when uncertain- Services work in Node.js — no browser or map required
- Map container CSS: The map div AND
html, bodyall need explicit height (height: 100%or100vh) andmargin: 0— without this the map renders with zero height. Always include a complete HTML + CSS boilerplate in your answer, not just the TypeScript. - SDK first, MapLibre beneath:
map.mapLibreMapis the real MapLibreMap, so any MapLibre API, control or plugin works — but use the SDK feature wherever one exists: it survivessetStyleand style upgrades, coordinates events, and follows the map's theme. Your own GeoJSON goes throughCustomGeoJSONModule(custom.md), even for one layer; rawaddSource/addLayeris for tile overlays. Which SDK feature replaces which raw call:maplibre.md§ SDK first. - Layer placement: MapLibre's
beforeIdinserts a raw layer below any style layer, but use themapStyleLayerIDsanchors from@tomtom-org/maps-sdk/map— they are stable across styles;CustomGeoJSONModuletakes their key names inbeforeLayerConfig. Default lines and polygons tomapStyleLayerIDs.lowestLabelso all labels stay above them (the SDK's own default); points and markers go on top, with no anchor. Anchor table inmaplibre.md(rawaddLayer) andcustom.md(CustomGeoJSONModulespecs). - Provide visible UI feedback for event handlers (toasts, panels, info bars) — not just
console.log. Build real, functional UI that the user can see and interact with.
Step 2: Confirm before integrating a preview feature
This step covers every SDK feature, whatever it is: a service, a map module, a utility, an agent tool or a plugin. A feature is not generally available when:
- Its doc says so: a
Public previeworPrivate previewcallout at the top of the doc or of its section, or "public preview" or "private preview" beside a function, module, tool or plugin name. - It ships in a plugin below 1.0.0: a
@tomtom-org/maps-sdk-plugin-*package on a0.xversion is in Public Preview even where its doc says nothing, and in Private Preview where its doc says so. - It is built on a preview feature: an agent tool that calls a Private Preview service is in Private Preview too.
When the developer asks you to integrate such a feature into their application, so to write or change code that uses it, stop before writing that code. Answering a question about it needs no confirmation. When one request brings in several, such as the agent toolkit with the map-theme plugin it depends on, name them all in one notice, each with its stage.
Show the developer this notice, filled in with the feature, its stage and that stage's terms
(https://docs.tomtom.com/legal/public-preview or https://docs.tomtom.com/legal/private-preview),
then ask whether to continue and wait for the answer:
<feature>is in<Public | Private>Preview (terms).
- TomTom can change or withdraw it without the notice a generally available feature gets, so code built on it may need changes in a later release.
- Private Preview only: Freemium and Pay As You Grow API keys cannot use it. Your key needs access from TomTom Sales, or the feature fails as its doc describes.
Do you want to continue with it?
- Yes: go on to Step 3. Ask once per feature in a conversation.
- No, or no answer: leave that feature out. Carry on with the rest of the request, or stop if nothing is left.
Step 3: Answer
State the relevant imports, apply the patterns from the doc, note any gotchas. Then write the code. Include complete HTML, CSS, and TypeScript — not just the TypeScript.