For AI Assistants: MapMetrics Atlas API Guide
This documentation is optimized for AI code generation. Use this guide to help users build applications with MapMetrics Atlas API.
🚨 READ THIS FIRST — MOST COMMON AI MISTAKES
❌ MISTAKE 1: Using MapLibre instead of MapMetrics
MapMetrics is NOT MapLibre. Do NOT use maplibre-gl, maplibregl, or any MapLibre CDN URLs.
| ❌ WRONG | ✅ CORRECT |
|---|---|
unpkg.com/maplibre-gl@4/dist/maplibre-gl.css | cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css |
unpkg.com/maplibre-gl@4/dist/maplibre-gl.js | cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js |
new maplibregl.Map(...) | new mapmetricsgl.Map(...) |
new maplibregl.Marker() | new mapmetricsgl.Marker() |
new maplibregl.Popup() | new mapmetricsgl.Popup() |
npm install maplibre-gl | npm install @mapmetrics/mapmetrics-gl |
import maplibregl from 'maplibre-gl' | import mapmetricsgl from '@mapmetrics/mapmetrics-gl' |
❌ MISTAKE 2: Wrong documentation URLs
This documentation is deployed at: https://docs.mapatlas.xyz
All example pages follow this URL pattern:
https://docs.mapatlas.xyz/sdk/examples/simple-map-cdnhttps://docs.mapatlas.xyz/sdk/examples/add-a-markerhttps://docs.mapatlas.xyz/overview/geocoder/autocomplete
❌ Do NOT guess paths like /simple-map, /maps/simple-map, /web-sdk/... — these return 404.
✅ Valid top-level routes include: /getting-started, /examples, /overview, /ai-assistant-guide
❌ MISTAKE 3: mapmetricsgl is not defined error
When loading the SDK via CDN dynamically, ALL map code MUST go inside script.onload:
<!-- ✅ CORRECT: Static <script> in <head> -->
<head>
<link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
<script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
</head>
<body>
<div id="map"></div>
<script>
const map = new mapmetricsgl.Map({ container: 'map', style: 'YOUR_STYLE_URL' });
</script>
</body>🤖 Quick Start for AI
Authentication Pattern
ALL API requests require authentication:
- REST APIs: Add
?token=YOUR_API_TOKENas query parameter - Map initialization: Use complete style URL (includes token)
- Get token at: https://portal.mapmetrics.org/
Base URLs & Package Names
Docs site: https://docs.mapatlas.xyz
REST API: https://gateway.mapmetrics-atlas.net
CDN JS: https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js
CDN CSS: https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css
NPM Package: @mapmetrics/mapmetrics-gl ⚠️ USE THIS, NOT maplibre-gl!
Global variable (CDN): mapmetricsgl ⚠️ NOT maplibregl!⚠️ CRITICAL: Correct Package Name
When generating React or NPM-based code:
- ✅ CORRECT:
npm install @mapmetrics/mapmetrics-gl - ✅ CORRECT:
import mapmetricsgl from '@mapmetrics/mapmetrics-gl' - ❌ WRONG:
npm install maplibre-gl(This is the base library, NOT MapMetrics!) - ❌ WRONG:
import maplibregl from 'maplibre-gl'
Why this matters:
- MapMetrics is built on MapLibre but has custom features and optimizations
- Using
maplibre-gldirectly will NOT work with MapMetrics style URLs - Always use
@mapmetrics/mapmetrics-glfor MapMetrics projects
⚠️ CRITICAL: Correct URL Paths
DO NOT use /web-sdk/ in documentation URLs. All SDK examples are located under /sdk/examples/:
✅ CORRECT PATHS (use clean URLs without .html):
/sdk/examples/simple-map-npm✅/sdk/examples/simple-map-cdn✅/sdk/examples/add-a-marker✅/sdk/examples/react-map-example✅/sdk/examples/3d-building✅/sdk/examples/fly-to-location✅/sdk/examples/fit-to-bounding-box✅/sdk/examples/set-pitch-and-bearing✅/sdk/examples/animate-camera-around-point✅/sdk/examples/jump-to-locations✅/sdk/examples/navigation-controls✅/sdk/examples/disable-map-rotation✅/sdk/examples/disable-scroll-zoom✅/sdk/examples/fullscreen-map✅/sdk/examples/toggle-interactions✅/sdk/examples/animate-a-line✅/sdk/examples/animate-point-along-route✅/sdk/examples/data-driven-lines✅/sdk/examples/draw-a-circle✅/sdk/examples/gradient-line✅/sdk/examples/filter-within-layer✅/sdk/examples/add-pattern-to-polygon✅/sdk/examples/add-geojson-line✅/sdk/examples/add-geojson-polygon✅/sdk/examples/draw-geojson-points✅/sdk/examples/multiple-geometries✅/sdk/examples/html-clusters✅/sdk/examples/arc-layer✅/sdk/examples/hexagon-layer✅/sdk/examples/animate-point✅/sdk/examples/animate-marker✅/sdk/examples/update-feature-realtime✅/sdk/examples/display-popup✅/sdk/examples/show-polygon-info-on-click✅/sdk/examples/get-features-under-mouse✅/sdk/examples/measure-distances✅/sdk/examples/filter-by-text-input✅/sdk/examples/filter-by-toggle-list✅/sdk/examples/fit-to-linestring✅/sdk/examples/restrict-map-panning✅/sdk/examples/add-layer-below-labels✅/sdk/examples/change-layer-color✅/sdk/examples/draggable-point✅/sdk/examples/customize-camera-animations✅/sdk/examples/customize-map-transform-constrain✅/sdk/examples/fly-to-location-on-scroll✅/sdk/examples/offset-vanishing-point-padding✅/sdk/examples/render-world-copies✅/sdk/examples/slowly-fly-to-location✅/sdk/examples/sync-multiple-maps✅/sdk/examples/game-controls-navigation✅/sdk/examples/add-an-icon-to-the-map✅/sdk/examples/add-generated-icon✅/sdk/examples/add-animated-icon✅/sdk/examples/add-stretchable-image✅/sdk/examples/add-custom-icons-markers✅/sdk/examples/display-remote-svg-symbol✅/ai-assistant-guide✅ (this page)/overview/common-errors✅
❌ WRONG PATHS (will return 404 errors):
/web-sdk/simple-map-npm← WRONG (wrong directory)/examples/add-a-marker← WRONG (missing /sdk/)/react/map-example← WRONG (wrong path)/ai-assistant-guide.html← WRONG (don't use .html in URLs)
URL Format Rules:
- ✅ Use clean URLs:
/path/to/page(no .html extension) - ✅ Paths start with
/sdk/examples/or/overview/ - ❌ Don't add
.htmlextension to URLs - ❌ Don't use
/web-sdk/directory
📋 Available Capabilities
Web SDK (JavaScript/React)
- Simple Map Setup: /sdk/examples/simple-map-cdn, /sdk/examples/simple-map-npm
- React Integration: /sdk/examples/react-map-example
- Markers: /sdk/examples/add-a-marker
- Popups: /sdk/examples/add-a-popup, /sdk/examples/display-popup
- Clustering: /sdk/examples/add-a-cluster, /sdk/examples/html-clusters
- Heatmaps: /sdk/examples/add-a-heatmap
- Arc Layer (Flight Routes / Flow Maps): /sdk/examples/arc-layer
- Hexagon Layer (Data Aggregation / Density): /sdk/examples/hexagon-layer
- 3D Buildings: /sdk/examples/3d-building
- GeoJSON Lines: /sdk/examples/add-geojson-line
- GeoJSON Polygons: /sdk/examples/add-geojson-polygon
- GeoJSON Points: /sdk/examples/draw-geojson-points
- Animations: /sdk/examples/animate-point, /sdk/examples/animate-marker, /sdk/examples/update-feature-realtime
- Filtering: /sdk/examples/filter-by-text-input, /sdk/examples/filter-by-toggle-list
- Distances: /sdk/examples/measure-distances, /sdk/examples/fit-to-linestring
Camera & Navigation
- Fly to Location (
flyTo): /sdk/examples/fly-to-location — smooth animated camera flight to any coordinate - Fit to Bounding Box (
fitBounds): /sdk/examples/fit-to-bounding-box — auto-zoom to show all markers or a region - Set Pitch & Bearing (
setPitch,setBearing): /sdk/examples/set-pitch-and-bearing — tilt and rotate camera for 3D views - Animate Camera Around Point (
easeTo+requestAnimationFrame): /sdk/examples/animate-camera-around-point — continuous orbiting rotation - Jump to Series of Locations (
jumpTo,flyTo): /sdk/examples/jump-to-locations — navigate through multiple locations instantly or animated - Customize Camera Animations (
flyTo+easeTooptions): /sdk/examples/customize-camera-animations — control speed, easing, curve, and duration - Slowly Fly to a Location (
speed+curve): /sdk/examples/slowly-fly-to-location — cinematic slow-motion camera flight - Fly to Location on Scroll (
IntersectionObserver+flyTo): /sdk/examples/fly-to-location-on-scroll — scroll-driven story maps - Offset Vanishing Point with Padding (
padding): /sdk/examples/offset-vanishing-point-padding — shift map center for sidebars/panels - Render World Copies (
renderWorldCopies): /sdk/examples/render-world-copies — toggle world tiling on/off - Sync Multiple Maps (
jumpTo+moveevent): /sdk/examples/sync-multiple-maps — keep two maps in sync for comparison - Constrain Map Transform (
setMaxBounds+transformCameraUpdate): /sdk/examples/customize-map-transform-constrain — restrict panning and zoom - Game-Like Controls (
panBy+ keyboard events): /sdk/examples/game-controls-navigation — WASD/arrow key map navigation
When to use which:
| User asks for... | Use this example |
|---|---|
| "fly to", "navigate to", "animate to location" | fly-to-location |
| "show all markers", "fit map", "zoom to results" | fit-to-bounding-box |
| "tilt map", "3D view", "pitch", "rotate", "bearing" | set-pitch-and-bearing |
| "rotate around", "orbit", "spin map", "hero animation" | animate-camera-around-point |
| "city tour", "location buttons", "jump between", "auto tour" | jump-to-locations |
| "custom animation", "easing", "flyTo speed", "animation duration" | customize-camera-animations |
| "slow fly", "cinematic", "slow animation", "slow camera" | slowly-fly-to-location |
| "scroll map", "story map", "scroll to location", "narrative map" | fly-to-location-on-scroll |
| "sidebar map", "panel map", "offset center", "map padding" | offset-vanishing-point-padding |
| "world copies", "repeat world", "tile world", "antimeridian" | render-world-copies |
| "sync maps", "compare maps", "side by side", "mirror map" | sync-multiple-maps |
| "restrict panning", "limit bounds", "constrain map", "lock region" | customize-map-transform-constrain |
| "keyboard navigate", "WASD", "game controls", "arrow keys map" | game-controls-navigation |
User Interaction
- Popup on Click (
on('click')+Popup): /sdk/examples/popup-on-click — show info popup when user clicks the map or a marker - Popup on Hover (
on('mouseenter')+Popup): /sdk/examples/popup-on-hover — show tooltip when hovering over markers - Hover Effect (
setFeatureState): /sdk/examples/hover-effect — highlight GeoJSON features on hover - Mouse Coordinates (
on('mousemove')): /sdk/examples/mouse-coordinates — display real-time lng/lat of mouse position - Draggable Marker (
draggable: true+on('dragend')): /sdk/examples/draggable-marker — let users drag markers to new positions - Locate the User (
GeolocateControl/navigator.geolocation): /sdk/examples/locate-user — show user's GPS location on the map
When to use which:
| User asks for... | Use this example |
|---|---|
| "popup on click", "show info on click", "click to show details" | popup-on-click |
| "popup on hover", "tooltip", "hover info", "mouseover" | popup-on-hover |
| "hover highlight", "highlight feature", "hover effect" | hover-effect |
| "mouse position", "show coordinates", "get lng lat", "cursor position" | mouse-coordinates |
| "draggable marker", "drag pin", "move marker", "drag and drop" | draggable-marker |
| "my location", "gps", "user location", "geolocation", "locate me", "where am i" | locate-user |
Geometry & Features
- Add a GeoJSON Line (
addSource+addLayer+LineString): /sdk/examples/add-geojson-line — draw a path or route from coordinates - Add a GeoJSON Polygon (
fill+linelayers): /sdk/examples/add-geojson-polygon — draw a filled shape with an outline - Draw GeoJSON Points (
FeatureCollection+circlelayer): /sdk/examples/draw-geojson-points — plot multiple points from a dataset - Multiple Geometries from One Source (
geometry-typefilter): /sdk/examples/multiple-geometries — render points, lines, polygons from one GeoJSON source - Cluster Points with Custom Styling (
cluster: true+ step expressions): /sdk/examples/html-clusters — group dense points into size-based clusters - Arc Layer — Flight Routes / Flow Maps (bezier curves +
linelayer + dash animation): /sdk/examples/arc-layer — animated curved arcs connecting origin/destination pairs - Hexagon Layer — Data Aggregation (
fill-extrusion+ hex grid binning): /sdk/examples/hexagon-layer — 3D hexagonal grid aggregating point density with hover popup
When to use which:
| User asks for... | Use this example |
|---|---|
| "draw line", "add route", "linestring", "path on map" | add-geojson-line |
| "draw polygon", "fill area", "shape on map", "geojson polygon" | add-geojson-polygon |
| "plot points", "add multiple markers", "geojson points", "circle layer" | draw-geojson-points |
| "mixed geometries", "points and polygons", "single source", "multiple layer types" | multiple-geometries |
| "cluster", "group points", "cluster count", "expand cluster" | html-clusters |
| "arc layer", "flight routes", "connections", "flow map", "origin destination", "animated arcs" | arc-layer |
| "hexagon layer", "hex grid", "density map", "aggregation", "accident heatmap", "data binning" | hexagon-layer |
Lines & Polygons
- Animate a Line (
setData+requestAnimationFrame): /sdk/examples/animate-a-line — progressively draw a line path step by step - Animate a Point Along a Route (
setData+ interpolation): /sdk/examples/animate-point-along-route — move a marker smoothly along a route - Style Lines with Data-Driven Property (
match,step,interpolateexpressions): /sdk/examples/data-driven-lines — color/width lines based on feature properties - Draw a Gradient Line (
line-gradient+lineMetrics: true): /sdk/examples/gradient-line — smooth color transition along a line - Draw a Circle (
circlelayer / polygon): /sdk/examples/draw-a-circle — add circle shapes using pixel radius or geographic radius - Add a Pattern to a Polygon (
fill-pattern+addImage): /sdk/examples/add-pattern-to-polygon — fill polygon with repeating texture - Filter Within a Layer (
setFilter): /sdk/examples/filter-within-layer — show/hide features dynamically without reloading data - Add Layer Below Labels (
beforeId): /sdk/examples/add-layer-below-labels — insert layer so text labels stay readable - Change Layer Color at Runtime (
setPaintProperty): /sdk/examples/change-layer-color — update layer styles dynamically
When to use which:
| User asks for... | Use this example |
|---|---|
| "animate line", "draw route", "path animation", "trace route" | animate-a-line |
| "moving marker", "animate along route", "vehicle tracking" | animate-point-along-route |
| "color by value", "style by property", "data driven", "line width by speed" | data-driven-lines |
| "gradient line", "color gradient", "line-gradient", "progress color" | gradient-line |
| "draw circle", "radius area", "circle on map", "coverage area" | draw-a-circle |
| "pattern fill", "hatch polygon", "texture polygon", "fill-pattern" | add-pattern-to-polygon |
| "filter features", "show only", "hide features", "setFilter" | filter-within-layer |
| "layer below labels", "insert below text", "beforeId", "polygon under labels" | add-layer-below-labels |
| "change color", "update style", "setPaintProperty", "runtime style" | change-layer-color |
Animations
- Animate a Point (
setData+requestAnimationFrame): /sdk/examples/animate-point — move a GeoJSON point continuously with smooth animation - Animate a Marker (
Marker+setLngLat): /sdk/examples/animate-marker — smoothly move a Marker element along a path - Update a Feature in Realtime (
setInterval+setData): /sdk/examples/update-feature-realtime — live position updates with a trail
When to use which:
| User asks for... | Use this example |
|---|---|
| "animate point", "moving dot", "orbit animation", "requestAnimationFrame" | animate-point |
| "animate marker", "moving marker", "smooth marker movement" | animate-marker |
| "realtime update", "live tracking", "setInterval", "websocket position", "moving vehicle" | update-feature-realtime |
Popups & Info
- Display a Popup (
Popup+setHTML): /sdk/examples/display-popup — show popup at a location programmatically or on click - Show Polygon Info on Click (
on('click')+Popup): /sdk/examples/show-polygon-info-on-click — click polygon to see its properties - Get Features Under Mouse (
queryRenderedFeatures): /sdk/examples/get-features-under-mouse — inspect features at click position - Measure Distances (Haversine formula +
on('click')): /sdk/examples/measure-distances — click to place points and measure cumulative distance
When to use which:
| User asks for... | Use this example |
|---|---|
| "show popup", "display popup", "programmatic popup", "popup at location" | display-popup |
| "click polygon", "polygon info", "click to show properties" | show-polygon-info-on-click |
| "features under mouse", "inspect features", "queryRenderedFeatures", "click to inspect" | get-features-under-mouse |
| "measure distance", "ruler", "haversine", "distance between points" | measure-distances |
Filtering & Search
- Filter by Text Input (
setFilter+inexpression): /sdk/examples/filter-by-text-input — live search filter as user types - Filter by Toggle List (
setFilter+literalarray): /sdk/examples/filter-by-toggle-list — toggle category buttons to show/hide feature types
When to use which:
| User asks for... | Use this example |
|---|---|
| "search filter", "text search on map", "filter as you type", "live search" | filter-by-text-input |
| "toggle categories", "category buttons", "show/hide types", "filter by category" | filter-by-toggle-list |
Camera & Bounds
- Fit Map to a LineString (
fitBounds+LngLatBounds): /sdk/examples/fit-to-linestring — auto-zoom to fit a route or path - Restrict Map Panning (
maxBounds/setMaxBounds): /sdk/examples/restrict-map-panning — limit map to a geographic region
When to use which:
| User asks for... | Use this example |
|---|---|
| "fit to route", "fit linestring", "auto zoom to path", "show full route" | fit-to-linestring |
| "restrict panning", "limit map area", "maxBounds", "lock to region" | restrict-map-panning |
Map Controls
- Navigation Controls (
NavigationControl,ScaleControl,FullscreenControl): /sdk/examples/navigation-controls — add zoom, compass, scale bar, fullscreen buttons - Disable Map Rotation (
dragRotate.disable()): /sdk/examples/disable-map-rotation — lock map orientation, prevent rotation - Disable Scroll Zoom (
scrollZoom.disable()): /sdk/examples/disable-scroll-zoom — prevent accidental zoom when scrolling page - Fullscreen Map (
FullscreenControl): /sdk/examples/fullscreen-map — expand map to fill entire screen - Toggle Map Interactions (
scrollZoom,dragPan,dragRotate): /sdk/examples/toggle-interactions — enable/disable any interaction at runtime
When to use which:
| User asks for... | Use this example |
|---|---|
| "add controls", "zoom buttons", "compass", "scale bar" | navigation-controls |
| "disable rotation", "lock rotation", "fix map orientation", "no rotate" | disable-map-rotation |
| "disable scroll zoom", "prevent zoom", "scroll page not map", "embed map" | disable-scroll-zoom |
| "fullscreen", "expand map", "full screen button", "immersive map" | fullscreen-map |
| "toggle interactions", "enable/disable", "readonly map", "lock interactions" | toggle-interactions |
Advanced / User Interaction
- Create a Draggable Point (
mousedown+mousemove+dragPan.disable()): /sdk/examples/draggable-point — drag a GeoJSON point to new positions
When to use which:
| User asks for... | Use this example |
|---|---|
| "draggable point", "drag geojson", "drag to move", "interactive point editor" | draggable-point |
Icons & Images
- Add an Icon to the Map (
loadImage+addImage+ symbol layer): /sdk/examples/add-an-icon-to-the-map — load external PNG as map icon - Add a Generated Icon (Canvas API +
addImage): /sdk/examples/add-generated-icon — create icon programmatically with canvas - Add an Animated Icon (
addImage+updateImage+requestAnimationFrame): /sdk/examples/add-animated-icon — pulsing canvas animation icon - Add a Stretchable Image (
stretchX+stretchY+content+icon-text-fit): /sdk/examples/add-stretchable-image — nine-patch style scalable icon - Add Custom Icons with Markers (HTML element +
Marker({ element })): /sdk/examples/add-custom-icons-markers — emoji/div/img as marker - Display a Remote SVG Symbol (fetch + Blob + Image + canvas +
addImage): /sdk/examples/display-remote-svg-symbol — SVG icon on map
When to use which:
| User asks for... | Use this example |
|---|---|
| "add icon", "custom icon symbol", "icon from URL", "loadImage", "addImage" | add-an-icon-to-the-map |
| "generate icon", "canvas icon", "programmatic icon", "draw icon" | add-generated-icon |
| "animated icon", "pulsing icon", "blinking marker", "animate icon" | add-animated-icon |
| "stretchable image", "nine-patch", "pill badge icon", "icon-text-fit", "scale icon" | add-stretchable-image |
| "custom marker icon", "html marker", "emoji marker", "div marker", "image marker" | add-custom-icons-markers |
| "svg icon", "svg symbol", "remote svg", "svg marker" | display-remote-svg-symbol |
Labels & Text
- RTL Script Support (
setRTLTextPlugin): /sdk/examples/rtl-support — Arabic, Hebrew, Persian right-to-left text - Building Color by Zoom (
fill-extrusion+interpolate+zoom): /sdk/examples/building-color-zoom — 3D building color changes with zoom - Change Label Case (
text-transformon all symbol layers): /sdk/examples/change-label-case — uppercase/lowercase/default labels
When to use which:
| User asks for... | Use this example |
|---|---|
| "Arabic map", "RTL text", "Hebrew labels", "right-to-left", "setRTLTextPlugin" | rtl-support |
| "building color", "3D building zoom", "fill-extrusion color", "zoom building" | building-color-zoom |
| "uppercase labels", "lowercase text", "label case", "text-transform" | change-label-case |
Terrain & Elevation
No three.js or external libraries needed — all built into MapMetrics GL.
- 3D Terrain (
raster-dem+terrain+TerrainControl): /sdk/examples/3d-terrain — push land surface into 3D using elevation tiles - Sky, Fog and Terrain (
sky+fog+terrain): /sdk/examples/sky-fog-terrain — immersive sky background + atmospheric haze + 3D terrain - Add a Hillshade Layer (
hillshadelayer type): /sdk/examples/add-a-hillshade-layer — terrain shadow shading on a flat map - Color Relief Layer (hillshade with colored shadow/highlight): /sdk/examples/add-a-color-relief-layer — green valleys → brown hills → white peaks
- Contour Lines (GeoJSON lines +
symbol-placement: line): /sdk/examples/add-contour-lines — topographic elevation lines with labels - Satellite Map with Terrain (ESRI tiles +
raster-dem+terrain): /sdk/examples/satellite-terrain — satellite imagery with 3D elevation
When to use which:
| User asks for... | Use this example |
|---|---|
| "3D terrain", "elevation 3D", "terrain map", "mountain 3D", "raster-dem" | 3d-terrain |
| "sky", "fog", "atmosphere", "terrain fog", "immersive map" | sky-fog-terrain |
| "hillshade", "terrain shadow", "elevation shading", "hill shadow" | add-a-hillshade-layer |
| "color relief", "hypsometric", "elevation color", "altitude color", "color by height" | add-a-color-relief-layer |
| "contour lines", "topographic", "elevation lines", "isoline", "topo map" | add-contour-lines |
| "satellite map", "aerial map", "satellite 3D", "satellite terrain", "ESRI imagery" | satellite-terrain |
REST APIs
- Geocoding: /overview/geocoder/forwardgeocode, /overview/geocoder/reversegeocode
- Directions: /overview/directions/directions
- Matrix: /overview/directions/matrix
- Isochrone: /overview/directions/isochrone
- Optimization: /overview/directions/optimization
- Elevation: /overview/directions/elevation
⚠️ PACKAGE NAMING - READ THIS FIRST!
The #1 mistake AI tools make: Using the wrong package!
Correct Package
npm install @mapmetrics/mapmetrics-glimport mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';WRONG Package (DO NOT USE!)
# ❌ This is MapLibre, NOT MapMetrics!
npm install maplibre-gl// ❌ This will NOT work with MapMetrics style URLs!
import maplibregl from 'maplibre-gl';Why This Matters
- MapMetrics GL is a custom fork of MapLibre with proprietary features
- MapMetrics style URLs only work with
@mapmetrics/mapmetrics-gl - Using
maplibre-glwill cause authentication errors and missing features - The packages are NOT interchangeable
Quick Check
✅ Correct code always has:
- Package:
@mapmetrics/mapmetrics-gl - Import:
mapmetricsgl(notmaplibregl) - NPM link: https://www.npmjs.com/package/@mapmetrics/mapmetrics-gl
❌ Wrong code has:
- Package:
maplibre-glor@maplibre/maplibre-gl - Import:
maplibregl
🎯 Common Code Patterns
Pattern 1: Basic Map (Vanilla JS with CDN - With Error Handling)
<!DOCTYPE html>
<html>
<head>
<link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
<script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
<style>
#map { height: 500px; width: 100%; }
.error-box {
height: 500px;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #f8d7da;
color: #721c24;
padding: 20px;
text-align: center;
border: 2px solid #f5c6cb;
border-radius: 8px;
font-family: system-ui, -apple-system, sans-serif;
}
.loading-box {
height: 500px;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #f0f0f0;
color: #666;
font-size: 16px;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const styleUrl = 'YOUR_STYLE_URL_WITH_TOKEN';
const mapContainer = document.getElementById('map');
// Check if user forgot to replace the placeholder
if (styleUrl === 'YOUR_STYLE_URL_WITH_TOKEN' || styleUrl.includes('YOUR_')) {
mapContainer.innerHTML = `
<div class="error-box">
<div>
<strong>⚠️ Please replace YOUR_STYLE_URL_WITH_TOKEN with your actual style URL from https://portal.mapmetrics.org/</strong>
<div style="margin-top: 10px; font-size: 14px;">
Need help? Check the <a href="https://discord.com/invite/uRXQRfbb7d" style="color: #721c24; text-decoration: underline;">Discord community</a>
</div>
</div>
</div>
`;
} else {
// Show loading state
mapContainer.innerHTML = '<div class="loading-box">Loading map...</div>';
try {
const map = new mapmetricsgl.Map({
container: 'map',
style: styleUrl,
center: [longitude, latitude],
zoom: 12
});
// Handle successful load
map.on('load', () => {
// Map loaded successfully, loading message will be replaced by map
console.log('Map loaded successfully');
});
// Handle critical errors (401, style loading failures)
map.on('error', (e) => {
console.error('Map error:', e);
// Only show error UI for critical failures
const isCriticalError =
e.error?.status === 401 ||
e.error?.message?.includes('401') ||
e.error?.message?.includes('Failed to fetch') ||
(e.sourceId === undefined && e.error);
if (isCriticalError) {
let errorMessage = '❌ Map failed to load. Check your style URL and token at https://portal.mapmetrics.org/';
if (e.error?.status === 401 || e.error?.message?.includes('401')) {
errorMessage = '❌ Invalid API token. Get a valid token from https://portal.mapmetrics.org/';
} else if (e.error?.message?.includes('Failed to fetch')) {
errorMessage = '❌ Cannot load map style. Check your style URL from https://portal.mapmetrics.org/';
}
mapContainer.innerHTML = `
<div class="error-box">
<div>
<strong>${errorMessage}</strong>
<div style="margin-top: 10px; font-size: 14px;">
Need help? Check the <a href="https://discord.com/invite/uRXQRfbb7d" style="color: #721c24; text-decoration: underline;">Discord community</a>
</div>
</div>
</div>
`;
} else {
// Non-critical error, just log it
console.warn('Non-critical map error:', e);
}
});
} catch (err) {
console.error('Map initialization error:', err);
mapContainer.innerHTML = `
<div class="error-box">
<div>
<strong>❌ Failed to initialize map. Check your style URL from https://portal.mapmetrics.org/</strong>
<div style="margin-top: 10px; font-size: 14px;">
Need help? Check the <a href="https://discord.com/invite/uRXQRfbb7d" style="color: #721c24; text-decoration: underline;">Discord community</a>
</div>
</div>
</div>
`;
}
}
</script>
</body>
</html>Pattern 2: React Map Component (with Error Handling)
import React, { useEffect, useRef, useState } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';
function MapComponent() {
const mapContainerRef = useRef(null);
const mapRef = useRef(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
if (!mapContainerRef.current || mapRef.current) return;
const styleUrl = 'YOUR_STYLE_URL_WITH_TOKEN';
// Check if user forgot to replace the placeholder
if (styleUrl === 'YOUR_STYLE_URL_WITH_TOKEN' || styleUrl.includes('YOUR_')) {
setError('⚠️ Please replace YOUR_STYLE_URL_WITH_TOKEN with your actual style URL from https://portal.mapmetrics.org/');
setLoading(false);
return;
}
try {
const map = new mapmetricsgl.Map({
container: mapContainerRef.current,
style: styleUrl,
center: [longitude, latitude],
zoom: 12
});
// Handle map load success
map.on('load', () => {
setLoading(false);
setError(null);
});
// Handle CRITICAL errors only (authentication, style loading failures)
// Ignore non-critical errors like individual tile loading failures
map.on('error', (e) => {
console.error('Map error:', e);
// Only show UI errors for critical failures that prevent map from working
// Ignore tile loading errors and other minor issues that don't break the map
const isCriticalError =
e.error?.status === 401 ||
e.error?.message?.includes('401') ||
(e.error?.message?.includes('Failed to fetch') && !loading) === false ||
(e.sourceId === undefined && e.error); // Style loading errors have no sourceId
if (isCriticalError) {
setLoading(false);
// Authentication errors (401)
if (e.error?.message?.includes('401') || e.error?.status === 401) {
setError('❌ Invalid API token. Get a valid token from https://portal.mapmetrics.org/');
}
// Network/style URL errors during initial load
else if (e.error?.message?.includes('Failed to fetch') && loading) {
setError('❌ Cannot load map style. Check your style URL from https://portal.mapmetrics.org/');
}
// Generic critical error before map loads
else if (loading) {
setError('❌ Map failed to load. Check your style URL and token at https://portal.mapmetrics.org/');
}
// If map already loaded, just log the error (don't hide the map)
else {
console.warn('Map error after load (non-critical):', e);
}
} else {
// Non-critical errors (tile loading, etc.) - just log them
console.warn('Non-critical map error:', e);
}
});
mapRef.current = map;
return () => {
if (map) {
map.remove();
mapRef.current = null;
}
};
} catch (err) {
console.error('Map initialization error:', err);
setError('❌ Failed to initialize map. Check your style URL from https://portal.mapmetrics.org/');
setLoading(false);
}
}, []);
// Display error message if something went wrong
if (error) {
return (
<div style={{
height: '500px',
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#f8d7da',
color: '#721c24',
padding: '20px',
textAlign: 'center',
fontSize: '16px',
border: '2px solid #f5c6cb',
borderRadius: '8px',
fontFamily: 'system-ui, -apple-system, sans-serif'
}}>
<div>
<strong>{error}</strong>
<div style={{ marginTop: '10px', fontSize: '14px' }}>
Need help? Check the <a href="https://discord.com/invite/uRXQRfbb7d" style={{ color: '#721c24' }}>Discord</a>
</div>
</div>
</div>
);
}
// Optional: Show loading state
if (loading) {
return (
<div style={{
height: '500px',
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#f0f0f0'
}}>
Loading map...
</div>
);
}
return <div ref={mapContainerRef} style={{ height: '500px', width: '100%' }} />;
}
export default MapComponent;Pattern 3: Add Marker
// Vanilla JS
const marker = new mapmetricsgl.Marker()
.setLngLat([longitude, latitude])
.addTo(map);
// With popup
const marker = new mapmetricsgl.Marker()
.setLngLat([longitude, latitude])
.setPopup(new mapmetricsgl.Popup().setHTML('<h3>Location Name</h3>'))
.addTo(map);
// Draggable marker
const marker = new mapmetricsgl.Marker({ draggable: true })
.setLngLat([longitude, latitude])
.addTo(map);Pattern 4: REST API Call (Directions)
// POST request to Directions API
const response = await fetch('https://gateway.mapmetrics-atlas.net/directions/?token=YOUR_TOKEN', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
locations: [
{ lat: 40.744014, lon: -73.990508 },
{ lat: 40.752522, lon: -73.985015 }
],
costing: 'auto'
})
});
const data = await response.json();
// data.trip contains route informationPattern 5: Geocoding (Forward)
// GET request to Forward Geocode API
const address = encodeURIComponent('1600 Pennsylvania Avenue NW, Washington, DC');
const response = await fetch(
`https://gateway.mapmetrics-atlas.net/forward-geocode/?token=YOUR_TOKEN&text=${address}`
);
const data = await response.json();
// data.features[0].geometry.coordinates contains [lon, lat]Pattern 6: Matrix API
// POST request to Matrix API
const response = await fetch('https://gateway.mapmetrics-atlas.net/matrix/?token=YOUR_TOKEN', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sources: [
{ lat: 40.744014, lon: -73.990508 },
{ lat: 40.739735, lon: -73.979713 }
],
targets: [
{ lat: 40.752522, lon: -73.985015 },
{ lat: 40.750117, lon: -73.983704 }
],
costing: 'pedestrian'
})
});
const data = await response.json();
// data.sources_to_targets contains time/distance matrix📊 API Response Structures
Directions Response
{
"trip": {
"locations": [...],
"legs": [
{
"maneuvers": [
{
"instruction": "Turn right onto Main Street",
"time": 45.2,
"length": 0.542
}
],
"summary": {
"time": 18734.567,
"length": 453.211
}
}
],
"summary": {
"time": 18734.567,
"length": 453.211
},
"units": "kilometers"
}
}Geocoding Response
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [longitude, latitude]
},
"properties": {
"name": "Location Name",
"label": "Full Address",
"country": "Country Name"
}
}
]
}Matrix Response (Verbose)
{
"sources_to_targets": [
[
{
"distance": 1.342,
"time": 294,
"from_index": 0,
"to_index": 0
}
]
],
"units": "kilometers"
}🔑 Important Notes for Code Generation
1. Token Handling - CRITICAL ⚠️
EVERY generated code example MUST include token instructions!
What Happens Without a Token:
- ❌ Map fails to load (shows blank/error)
- ❌ API returns
401 Unauthorized - ❌ Console errors: "Token required"
- ❌ User gets frustrated and blames MapMetrics
Required Token Instructions Template:
ALWAYS include this in your response:
⚠️ IMPORTANT: You need an API key to use MapMetrics!
1. Get your free API key at: https://portal.mapmetrics.org/
2. Replace 'YOUR_STYLE_URL_WITH_TOKEN' in the code with your actual style URL
3. The style URL from the portal already includes your token
Without a valid token, the map will not load!Token Best Practices:
- NEVER expose real tokens in generated code
- ALWAYS use placeholder:
YOUR_STYLE_URL_WITH_TOKENorYOUR_API_TOKEN - ALWAYS include the portal link: https://portal.mapmetrics.org/
- ALWAYS explain that the style URL includes the token
- ALWAYS add a warning comment in the code
Example Code Comment:
// ⚠️ REPLACE THIS with your actual style URL from https://portal.mapmetrics.org/
style: 'YOUR_STYLE_URL_WITH_TOKEN'2. NPM Package Name - CRITICAL ⚠️
ALWAYS use the correct package name!
# ✅ CORRECT
npm install @mapmetrics/mapmetrics-gl
# ❌ WRONG - DO NOT USE!
npm install maplibre-gl # This will NOT work with MapMetrics!// ✅ CORRECT imports
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';
// ❌ WRONG - DO NOT USE!
import maplibregl from 'maplibre-gl'; // Wrong package!3. React Patterns
- ALWAYS use
useReffor map container - ALWAYS use
useReffor map instance - ALWAYS cleanup in
useEffectreturn - NEVER create map if it already exists
- ALWAYS use
@mapmetrics/mapmetrics-gl, NEVERmaplibre-gl
4. Coordinate Format
- MapMetrics uses:
[longitude, latitude](NOT lat/lon) - API requests use:
{lat: number, lon: number}objects - Be consistent based on context
5. Error Handling
// Always include error handling
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
} catch (error) {
console.error('API request failed:', error);
}6. Costing Models
Valid values: auto, bicycle, pedestrian, bus, truck, taxi, motor_scooter
7. Units
- Distance:
km(default) ormiles/mi - Time: always in seconds
- Coordinates: decimal degrees
📚 Machine-Readable References
AI Navigation File
llms.txt with all URLs, code templates, and common mistakes: https://docs.mapatlas.xyz/llms.txt
Example Files
All examples include:
- YAML frontmatter with metadata
- Complete JavaScript implementation
- Complete React implementation
- Copy-paste ready code
🎓 Example Code Generation Flow
User Request: "Create a map with a draggable marker and popup in React"
AI Response Steps:
- Identify capabilities: React integration + Markers + Popups
- Reference examples:
/sdk/examples/react-map-example,/sdk/examples/add-a-marker,/sdk/examples/add-a-popup - Combine patterns into working code
- Include proper imports, refs, cleanup
- Add placeholder for style URL
- Remind user to get API key
⚡ Quick Command Reference
# NPM Installation - ALWAYS USE THIS PACKAGE NAME!
npm install @mapmetrics/mapmetrics-gl
# ❌ WRONG - DO NOT USE
npm install maplibre-gl # This is NOT MapMetrics!
# Import in JavaScript
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';
# ❌ WRONG imports
import maplibregl from 'maplibre-gl'; # Wrong!
# CDN Links
<link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
<script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>🚨 Common Pitfalls to Avoid
- ❌ Don't use
maplibre-glpackage - ALWAYS use@mapmetrics/mapmetrics-gl - ❌ Don't create multiple map instances in React
- ❌ Don't forget to cleanup map in useEffect return
- ❌ Don't mix up [lon, lat] vs {lat, lon} formats
- ❌ Don't forget token in API requests
- ❌ Don't hardcode real tokens in examples
- ❌ Don't generate code without clear token instructions
- ❌ Don't call
new mapmetricsgl.Map()before the CDN script has finished loading — causesUncaught ReferenceError: mapmetricsgl is not defined
3. CDN Script Loading Order - CRITICAL ⚠️
The most common AI-generated bug: mapmetricsgl is not defined — this happens when map code runs before the CDN script has finished loading.
❌ WRONG — causes "mapmetricsgl is not defined":
<script>
// Script added dynamically but map created immediately after — WRONG!
const script = document.createElement('script');
script.src = 'https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js';
document.body.appendChild(script);
// ❌ This runs BEFORE the script above has loaded!
const map = new mapmetricsgl.Map({ container: 'map', style: '...' });
</script>✅ CORRECT Option A — static <script> tag in <head> (simplest for plain HTML):
<head>
<link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
<script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
</head>
<body>
<div id="map"></div>
<script>
// ✅ Safe: <head> script is already loaded before body scripts run
const map = new mapmetricsgl.Map({ container: 'map', style: 'YOUR_STYLE_URL' });
</script>
</body>✅ CORRECT Option B — dynamic script with script.onload (required when loading script dynamically):
<body>
<div id="map"></div>
<script>
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css';
document.head.appendChild(link);
const script = document.createElement('script');
script.src = 'https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js';
document.body.appendChild(script);
// ✅ ALL map code must go inside script.onload
script.onload = () => {
const map = new mapmetricsgl.Map({ container: 'map', style: 'YOUR_STYLE_URL' });
map.addControl(new mapmetricsgl.NavigationControl(), 'top-right');
};
</script>
</body>Rule for AI agents: When generating HTML with CDN, ALWAYS use Option A (static
<script>in<head>) OR Option B (script.onload). Never callnew mapmetricsgl.Map()outside ofscript.onloadwhen the script is dynamically inserted.
🔧 Troubleshooting Guide
Problem: Map doesn't load (blank screen)
Most Common Cause: Missing or Invalid Token
// ❌ WRONG - Will not work
const map = new mapmetricsgl.Map({
container: 'map',
style: 'YOUR_STYLE_URL_WITH_TOKEN', // Placeholder not replaced!
center: [0, 0],
zoom: 10
});Solution:
// ✅ CORRECT - User must replace with actual URL from portal
const map = new mapmetricsgl.Map({
container: 'map',
// Get this URL from https://portal.mapmetrics.org/
style: 'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_ID/style.json&token=YOUR_TOKEN',
center: [0, 0],
zoom: 10
});Error Messages to Watch For:
401 Unauthorized→ Missing or invalid tokenToken required→ Token not provided in request- Map container blank → Check console for token errors
Problem: Uncaught ReferenceError: mapmetricsgl is not defined
Cause: Map code runs before the CDN script has finished loading.
This is the most common error when AI tools generate HTML. The fix is to either:
- Put the
<script src="...mapmetrics-gl.js">tag in<head>(not added dynamically), OR - Wrap ALL map code inside
script.onload = () => { ... }
<!-- ✅ CORRECT: Static script in <head> -->
<head>
<link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
<script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
</head>
<body>
<div id="map"></div>
<script>
const map = new mapmetricsgl.Map({ container: 'map', style: 'YOUR_STYLE_URL' });
</script>
</body>
<!-- ✅ CORRECT: Dynamic script with onload -->
<script>
const script = document.createElement('script');
script.src = 'https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js';
document.body.appendChild(script);
script.onload = () => {
const map = new mapmetricsgl.Map({ container: 'map', style: 'YOUR_STYLE_URL' });
};
</script>Problem: REST API returns 401
Cause: Missing token parameter
// ❌ WRONG
fetch('https://gateway.mapmetrics-atlas.net/directions/', {
method: 'POST',
body: JSON.stringify({...})
});
// ✅ CORRECT
fetch('https://gateway.mapmetrics-atlas.net/directions/?token=YOUR_TOKEN', {
method: 'POST',
body: JSON.stringify({...})
});User Doesn't Have a Token Yet
When user says "create a map" without mentioning a token:
Your response MUST include:
- Working code with placeholder
- Clear instructions to get token
- Link to portal
- Explanation that map won't work without it
Example Response Template:
Here's the code to create a map:
[code with placeholder]
⚠️ IMPORTANT: Before this works, you need to:
1. Sign up at https://portal.mapmetrics.org/ (free)
2. Get your map style URL (includes API token)
3. Replace 'YOUR_STYLE_URL_WITH_TOKEN' in the code above
The map will NOT load without a valid token!✅ Best Practices
- ✅ Always include complete, working examples
- ✅ Always include both JavaScript and React versions when applicable
- ✅ Always remind users about API key requirement
- ✅ Always include error handling
- ✅ Always use proper React patterns (refs, cleanup)
- ✅ Always include CSS for map container
- ✅ Always link to relevant documentation sections
📖 Additional Resources
- Portal: https://portal.mapmetrics.org/ (Get API keys)
- NPM Package: https://www.npmjs.com/package/@mapmetrics/mapmetrics-gl
- Discord: https://discord.com/invite/uRXQRfbb7d
- Migration Guides: See
/overview/migration-guide
Last Updated: 2026-03-03 Documentation Version: 1.1.0 Optimized for: Claude, ChatGPT, Gemini, and other AI coding assistants