Quickstart
This page takes you through the three shortest working integrations, in the order most teams need them:
- Chat on a map you already run. A chat panel that answers questions about places and puts the answers on your own map as pins, camera moves and routes.
- A published map. A map you designed in Kaleidr Studio, embedded on your page.
- A basemap. A Kaleidr-designed basemap as a ready-made map on your page.
Each path is one HTML file. All three run on the Free plan.
| Path | Product | Key it needs | Renders |
|---|---|---|---|
| Chat on your map | chat | Publishable key | In your page, on top of your map |
| A published map | viewer | None | In a Kaleidr iframe |
| A basemap | tile | Publishable key | In a Kaleidr iframe |
If you would rather understand the model first, read How Kaleidr works. If you are not sure which product you need, read Choose your path.
Before you start
-
A Kaleidr account. Sign up at kaleidr.com. The Free plan is enough for everything on this page.
-
A publishable key for the chat and basemap paths. Create one at kaleidr.com/api-keys; it starts with
kld_pk_live_. Get an API key walks through the form. The published-map path needs no key. -
A web server for the page. Serve the file over HTTP, even locally. From the folder that holds the file, either of these works:
python -m http.server 8000# ornpx serve -l 8000Then open
http://localhost:8000/your-file.html. Do not open the file from disk: afile://page has no origin you can put in a key's allowed origins. -
Your origin in the key's allowed origins, if the key has any. A key with no allowed origins works from every site. A key that lists origins works only from those, so add
http://localhost:8000while you test. -
A Content Security Policy that lets Kaleidr load, if your site sends one. A page with no
Content-Security-Policyheader needs nothing. Otherwise see Content Security Policy.
Every path starts with the same script tag. It is the only file you load yourself; it fetches the code for each product when you mount it.
<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>
Chat on your map
You will end with a MapLibre GL JS map and a chat panel docked inside it. Asking "Where can I get ramen near Bryant Park?" streams an answer into the panel, drops a pin for each place and moves the camera to show them.
This example uses MapLibre GL JS. Chat also attaches to Mapbox GL JS, the Google Maps JavaScript API and Leaflet; see Supported maps.
1. Create the page
Save this as chat.html and replace kld_pk_live_… with your publishable key.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Kaleidr Chat on MapLibre</title>
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@5.17.0/dist/maplibre-gl.css" />
<style>
body { margin: 0; }
/* The chat panel docks inside this box, so it must be positioned and sized. */
#stage { position: relative; height: 100vh; }
#map { position: absolute; inset: 0; }
</style>
</head>
<body>
<div id="stage">
<div id="map"></div>
</div>
<!-- 1. Your map library, loaded as a page global (window.maplibregl). -->
<script src="https://unpkg.com/maplibre-gl@5.17.0/dist/maplibre-gl.js"></script>
<!-- 2. The Kaleidr loader. -->
<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>
<script>
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json', // replace with your own style
center: [-73.9857, 40.7484], // [longitude, latitude]
zoom: 11,
});
const chat = Kaleidr.mount('#stage', {
product: 'chat',
publishableKey: 'kld_pk_live_…',
map, // the live map instance, not a selector
contained: true, // dock the panel inside #stage
});
// When you remove the map (for example on a route change in a single-page app):
// chat.destroy();
</script>
</body>
</html>
Three details in this file matter:
- The map library is a page global. The chat code finds MapLibre at
window.maplibregl. Loading MapLibre with a script tag sets that global. If you import it from npm instead, assign it yourself before you mount:window.maplibregl = maplibregl. mapis the map object. Pass the instance you created, not a CSS selector.contained: trueneeds a positioned box with a height. The panel renders inside the mount target. Withoutcontained, the panel is a fixed window at the top-left of the browser window instead.
The demo style is a low-detail world map. Pins land at the right coordinates on it, but use your own style to see streets.
2. Serve it and ask a question
Start a local server in the file's folder and open http://localhost:8000/chat.html.
What you should see:
- The map fills the window and a chat panel with a text input sits at the top-left of the map.
- In the browser's Network tab, one request to
https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessionsreturns200. That is the SDK exchanging your key for a short-lived session. - Type a question about places, such as
Where can I get ramen near Bryant Park?. The answer streams into the panel as text, a pin appears on your map for each place, and the camera moves to fit them. The Network tab shows a request to…/b2b/v1/chat/control/streamthat stays open while the answer streams. - The console stays free of lines that contain
[kaleidr.
3. If it does not work
| What you see | Cause | Fix |
|---|---|---|
No panel, and the console shows a CORS error for …/sdk/sessions followed by a [kaleidr:chat] error | The key is wrong, revoked, or your page's origin is not in the key's allowed origins. The API answers such a request without CORS headers, so the browser reports it as a CORS failure. | Check the key value. Add your exact origin, including the port, to the key at kaleidr.com/api-keys, or clear the list while testing. |
| The panel is at the top-left of the browser window, not inside the map | contained: true is missing, or the mount target is not positioned | Pass contained: true and give the target position: relative and a height. |
| The panel answers, but no pins appear | The map library is not a page global, so the chat cannot create its pins | Load the library with a script tag, or set window.maplibregl before Kaleidr.mount. |
Troubleshooting covers every symptom with its exact console text.
Next for this path: Attach Chat to MapLibre for the full guide, and Capabilities and limits for what the panel does and does not do.
A published map
You will end with a map you designed in Kaleidr Studio showing on your own page. This path needs no API key: the map's public id is all the embed takes.
1. Publish the map and copy its id
- Open your map in Kaleidr Studio and choose Publish.
- On the Publish & embed page, choose Go Live.
- Under Embed code, copy the snippet. The id is the last part of the address in it: in
https://map-embed.kaleidr.com/embed/abc123, the id isabc123.
What you should see: the project status reads live, and the live preview under the embed code shows the map as visitors will see it.
2. Create the page
Save this as map.html and replace YOUR_SHARE_ID with the id you copied.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>A published Kaleidr map</title>
</head>
<body>
<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>
<kaleidr-map
product="viewer"
share-id="YOUR_SHARE_ID"
style="display:block; height:480px"
></kaleidr-map>
</body>
</html>
The element needs a height; without one the map falls back to 500 pixels tall. A <kaleidr-map> element is display:block by default, so the height applies. The snippet writes display:block as well: it is harmless, and it covers Safari before 16.4, where the element stays inline and a height has no effect.
If you cannot add a script to the page (a site builder, a CMS field), use the plain iframe that Studio's iFrame tab gives you. It needs no loader:
<iframe
src="https://map-embed.kaleidr.com/embed/YOUR_SHARE_ID"
width="100%"
height="480"
style="border:0;"
loading="lazy"
referrerpolicy="no-referrer-when-downgrade"
allow="geolocation; microphone; fullscreen; clipboard-write"
title="Kaleidr map"
></iframe>
3. Serve it
Open http://localhost:8000/map.html.
What you should see:
- Your map, 480 pixels tall and as wide as the page, opening at the view you saved in Studio.
- Scrolling with the pointer over the map zooms it. With the pointer beside the map, scrolling moves the page.
- In the Elements panel, an
<iframe>inside the<kaleidr-map>element whose address starts withhttps://map-embed.kaleidr.com/embed/.
If the frame shows "This map isn't available — it may have been unpublished, paused, or the link is incorrect.", the id is wrong or the map is not live. If it shows "This map isn't allowed to render on this site. Please contact the map owner.", the map is restricted to other domains.
Next for this path: Embed a map covers restricting the domains a map may appear on, and Chat on a published map adds a chat panel that your visitors can use without any key.
A basemap
You will end with a Kaleidr-designed basemap on your page: a finished interactive map with no map library to install and no style to write.
1. Create the page
Save this as basemap.html and replace kld_pk_live_… with your publishable key.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>A Kaleidr basemap</title>
</head>
<body>
<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>
<kaleidr-map
product="tile"
publishable-key="kld_pk_live_…"
style-id="kaleidr-morning"
center="-73.9857,40.7484"
zoom="11"
style="display:block; height:480px"
></kaleidr-map>
</body>
</html>
style-idnames the basemap. Always set it.kaleidr-morningis one of the general-purpose styles; Tile lists the others.centerislongitude,latitude. Setcenterwhenever you setzoom: azoomgiven without acenteris ignored.
2. Serve it
Open http://localhost:8000/basemap.html.
What you should see:
- The basemap centered on Midtown Manhattan, 480 pixels tall.
- In the Network tab, a request to
https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessionsthat returns200, then an iframe that loads fromhttps://map-embed.kaleidr.com. - Scrolling with the pointer over the map zooms it.
If nothing renders and the console shows a CORS error for …/sdk/sessions, the key is wrong or your origin is not in its allowed origins, exactly as in the chat path.
Each tile session counts as one map load against your organization's monthly map-load allowance. See Quota and rate limits.
Next for this path: Use Tile covers switching styles at runtime and driving the camera.
What you loaded
All three paths used the same two pieces:
Kaleidr.mount(target, options)mounts a product from JavaScript and returns a handle straight away. The product's code loads in the background, and calls you make on the handle before the product is ready are kept and applied once it is.<kaleidr-map>does the same from HTML. Its attributes are the mount options written with hyphens (share-id,style-id,publishable-key), with two exceptions: theenabledoption is theflagattribute, and the chat'stitleoption is thechat-titleattribute.
Use Kaleidr.mount for chat on your own map, because it needs the live map object. Use either form for the others.
The handle has a destroy() method for every product. The other methods depend on the product; for example setCamera works on viewer, tile and editor but not on chat, where the assistant moves your map itself and you keep using your map library's own camera methods. The full matrix is in The <kaleidr-map> element.
Limits to know now
- Chat adds its own pins, routes and camera moves. It does not change your layers or markers and sends none of them to Kaleidr, and your page receives no events from the panel. See Capabilities and limits.
- Viewer and Tile run in an iframe. You cannot add your own layers or markers to them. If you need your own layers, keep your own map and attach Chat to it.
- A Kaleidr basemap is shown through Tile. Loading Kaleidr styles or tiles into your own map library is not supported.
- The SDK is for web pages. There is no npm package and no native mobile SDK. Backends call the server API.
- Keyed mounts spend your allowance. Chat answers spend your organization's AI credits, and each Tile session spends a map load. See How Kaleidr works.
Which path next
| You want to | Read |
|---|---|
| Attach Chat to Mapbox GL JS | Attach Chat to Mapbox |
| Attach Chat to MapLibre GL JS | Attach Chat to MapLibre |
| Attach Chat to Google Maps | Attach Chat to Google Maps |
| Attach Chat to Leaflet | Attach Chat to Leaflet |
| Place the panel and match your brand colors | Theming and layout |
| Let visitors chat on a published map | Chat on a published map |
| Embed a published map and lock it to your domains | Embed a map |
| Show a basemap and switch its style | Use Tile |
| Put a map editor in your page | Attach the editor |
| Use the SDK from React, Next.js or Vue | Frameworks |
| Call Kaleidr from your backend | Server quickstart |
| Have answers draw on your own business data | Your data |
| Ship to production | Production checklist |