Supported maps
Kaleidr Chat attaches to a map your page already created. It ships no map library of its own: it uses the one on your page, through that library's public API. This page lists the libraries the chat bundle recognizes, what each one needs, and what the assistant can do on it.
Libraries
| Library | Status | Guide |
|---|---|---|
| Mapbox GL JS | Supported | Attach Kaleidr Chat to Mapbox |
| MapLibre GL JS | Supported | Attach Kaleidr Chat to MapLibre |
| Google Maps JavaScript API | Supported | Attach Kaleidr Chat to Google Maps |
| Leaflet | Supported | Attach Kaleidr Chat to Leaflet |
| Apple MapKit JS | Recognized, no guide | None |
| Naver Maps | Recognized, no guide | None |
| A Kaleidr viewer or tile element on the same page | Supported through map-target | Chat on a published map |
| Anything else | Not recognized: the panel runs chat-only | None |
Capabilities by library
| Mapbox GL JS | MapLibre GL JS | Google Maps | Leaflet | Apple MapKit JS | Naver Maps | |
|---|---|---|---|---|---|---|
| Pins | Yes | Yes | Yes | Yes | Yes | Yes |
| Click a pin to open its place card | Yes | Yes | Yes | Yes | Yes | Yes |
| Move to one place | Animated fly | Animated fly | Pan, then a zoom change | Animated fly | Animated region change | Recenter, then a zoom change |
| Fit several places | Yes, with per-side padding that keeps results clear of the panel | Yes, with per-side padding that keeps results clear of the panel | Yes, with a fixed 56 px margin | Yes, with a fixed 56 px margin | Yes, with a margin of about a fifth of the framed area | Yes, with no margin |
| Route line | Yes, as layers in your style | Yes, as layers in your style | Yes, as two polylines | Yes, as two polylines | Yes, as two polyline overlays | Yes, as two polylines |
| Reads the zoom level | Yes | Yes | Yes | Yes | Estimated from the visible span | Yes |
Where a fit uses a fixed margin or none, a result can land underneath the chat panel. The visitor can pan the map; the panel can also be minimized.
The assistant moves the center and the zoom. Leaflet, Google Maps, MapKit JS and Naver Maps are treated as flat, north-up maps.
How the bundle recognizes your map
You do not tell Kaleidr which library you use. The chat bundle looks at the object you pass as map and decides
from the methods it exposes. It checks in this order and stops at the first match:
| Order | Library | The object is recognized when it has |
|---|---|---|
| 1 | Mapbox GL JS or MapLibre GL JS | getCanvas, addControl and getStyle |
| 2 | Google Maps | It is an instance of google.maps.Map; or it has getDiv, setZoom and overlayMapTypes, and no getCanvas |
| 3 | Apple MapKit JS | convertCoordinateToPointOnPage and setRegionAnimated |
| 4 | Leaflet | addLayer and latLngToContainerPoint, and no getCanvas |
| 5 | Naver Maps | getProjection, panTo and setCenter, and no getCanvas |
Mapbox GL JS and MapLibre GL JS expose the same methods, so the bundle tells them apart by the class names on the
map's container element (mapboxgl-… or maplibregl-…), and if that is inconclusive, by which of
window.mapboxgl and window.maplibregl exists.
Pass the library's own map object. A React ref, a wrapper component, a DOM element, a promise or a map that has not been constructed yet is not a map object and is not recognized.
What happens with an object that is not recognized
The panel mounts chat-only, and says nothing. Questions are answered and result cards and place cards work, but there are no pins, no camera moves and no route line. No warning is logged, because a chat-only panel is also a valid configuration.
If the panel answers but your map never changes, this is the first thing to check. In the console, test the object you passed:
// A Mapbox GL JS or MapLibre GL JS map answers true:
typeof map.getCanvas === 'function' && typeof map.getStyle === 'function';
// A Leaflet map answers true:
typeof map.latLngToContainerPoint === 'function';
The page global each library needs
The chat bundle creates its pins and bounds with the library's own classes, and it finds those classes on a page
global. The global must exist before the first Kaleidr.mount call for chat on the page. The bundle reads it
once, when it loads.
| Library | Global the bundle reads | Loaded by |
|---|---|---|
| Mapbox GL JS | window.mapboxgl | The Mapbox GL JS script tag |
| MapLibre GL JS | window.maplibregl | The MapLibre GL JS script tag |
| Leaflet | window.L | The Leaflet script tag |
| Google Maps | google.maps | The Google Maps JavaScript API, however you load it |
| Apple MapKit JS | mapkit, loaded and initialized | The MapKit JS script and your mapkit.init call |
| Naver Maps | naver.maps | The Naver Maps script tag |
A script tag for the library defines the global for you. That is why every guide loads the map library with a
script tag, before kaleidr.js.
If the global is missing
A Mapbox, MapLibre or Leaflet map created from a bundled import is still recognized, because the map object has the right methods. But the bundle cannot find the library's classes, so no pins appear, the view is not fitted to several places, to an area or to a route, and nothing is logged. On Leaflet the route line is not drawn either. The camera still flies to a single place, which makes this easy to misread as a partial failure.
For MapKit JS and Naver Maps, a missing global fails the mount with a [kaleidr:chat] console error instead.
Making an npm-imported library a page global
If your app imports the map library from npm, assign it to window yourself before you mount:
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
window.maplibregl = maplibregl; // must run before Kaleidr.mount
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [-0.12, 51.5],
zoom: 11,
});
Kaleidr.mount('#chat', {
product: 'chat',
publishableKey: 'kld_pk_live_…',
map,
contained: true,
});
The same one-line assignment works for the other two:
import mapboxgl from 'mapbox-gl';
window.mapboxgl = mapboxgl;
import L from 'leaflet';
window.L = L;
The Google Maps JavaScript API always defines google.maps, whichever loader you use, so it needs no
assignment.
kaleidr.js itself has no npm package. Load it with a script tag, or inject the tag from your app; see
Frameworks for React, Next.js and Vue.
Notes per library
Mapbox GL JS and MapLibre GL JS
- Pins are the library's
Markerobjects with an HTML element. - A route is drawn with sources and layers the panel adds to your style and removes when the route is cleared or the conversation is closed. Your own layers are not reordered or changed.
- Fits are padded on each side to keep results clear of the panel, measured against the map's own rectangle, so this works whether the map fills the window or sits in a column.
Google Maps JavaScript API
google.mapsmust be loaded and thegoogle.maps.Mapconstructed before you mount. With the asynchronous loader, mount inside the callback. The Google Maps guide shows the script order.- Pins are HTML elements. If your page loaded the
markerlibrary, the bundle uses advanced markers, which Google requires a Map ID for. If it did not, the bundle draws the pins through a custom overlay, which needs no Map ID. The guide uses the second form. - Moving to a place is a
panTofollowed bysetZoom, not a single animated flight. - A route is two
Polylineobjects: a white casing and a colored line. - Your Google Maps key stays between your page and Google; Kaleidr does not receive it. Google bills your map usage as before, and Kaleidr bills the questions.
Leaflet
- Leaflet is a 2-D map: there is no bearing or pitch, and no 3-D content.
- Pins are Leaflet markers with an HTML icon. They live in Leaflet's marker pane with your own markers.
- A route is two polylines in Leaflet's overlay pane.
- Leaflet gives its panes and controls large
z-indexvalues. Give the map element its own stacking context so the panel can sit above it; the Leaflet guide shows how.
Apple MapKit JS and Naver Maps
Both are recognized and get pins, camera moves, fits and a route line, as the table above shows. There is no
guide for either. The mount pattern is the same as the other libraries: create the map, then pass it as map.
- MapKit JS frames by region rather than zoom level, so zoom values are converted approximately in both
directions.
mapkitmust be loaded and initialized before you mount. - Naver Maps fits without a margin.
A Kaleidr viewer or tile element
A chat mount can drive a <kaleidr-map product="viewer"> or <kaleidr-map product="tile"> element on the same
page instead of a map library. Point map-target (or the mapTarget option) at the element with a CSS
selector:
<kaleidr-map product="chat" publishable-key="kld_pk_live_…" contained
map-target="#store-map"
style="display:block; position:absolute; inset:0; z-index:1; pointer-events:none"></kaleidr-map>
The selector is resolved each time the panel needs the map, so the order in which the two elements mount does not
matter. If the selector matches nothing, the panel runs chat-only. If you pass both map and mapTarget, map
wins. Chat on a published map has the complete layout.
No map at all
Omit map and mapTarget for a chat-only panel. Answers, result cards and place cards work. There are no pins,
no camera moves and no route line.