How Kaleidr works
This page explains the parts of Kaleidr that every integration touches and how they fit together. Read it once and the product pages, the key settings and the error messages will make sense.
In short:
- You load one script, the loader. It gives you four products: Chat, Viewer, Tile and Editor.
- Two products render in your page and two render in a Kaleidr iframe. That one fact decides what your Content Security Policy and your layout have to do.
- A publishable key in your page is exchanged for a short-lived session, and the session makes the calls. A server key calls the API directly from your backend.
- Keys belong to an organization. The organization's plan decides what its keys may do, and its usage is counted in two pools: AI credits and map loads.
The picture
YOUR PAGE (https://www.example.com)
+--------------------------------------------------------------------+
| <script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"> |
| the loader: window.Kaleidr and the <kaleidr-map> element |
| |
| RENDERS IN YOUR PAGE RENDERS IN A KALEIDR IFRAME |
| +------------------------------+ +---------------------------+ |
| | Chat panel on your map | | Viewer a published map | |
| | Editor map editor | | Tile a basemap | |
| +---------------+--------------+ +-------------+-------------+ |
+------------------|---------------------------------|---------------+
| |
session token | | iframe document
v v
api.kaleidr.com map-embed.kaleidr.com
sessions, answers, the map itself, running
places, routes under Kaleidr's own policy
^
| server key (kld_sk_live_...)
|
YOUR BACKEND
The loader
Everything in the browser starts with one script:
<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>
The loader is small (about 17 KB before compression) and contains no map library and no product code. Loading it does two things:
- It defines
window.Kaleidr, withmount(target, options)to mount a product from JavaScript, andenable(on)to hold or release the mounts made after the call. It cannot hold back<kaleidr-map>elements that are already in the HTML, because they mount as the loader runs; to hold those, set the page flagwindow.__KALEIDR_EMBED_ENABLED__ = falsebefore the loader script. See the enable gate. - It registers the
<kaleidr-map>element, which mounts a product from HTML.
When you mount a product, the loader fetches that product's code from https://cdn.kaleidr.com/embed/v1/ and runs it. A page that mounts only Viewer never downloads Chat.
Kaleidr.mount returns a handle immediately, before the product has loaded. Calls you make on the handle in the meantime are kept and applied, in order, once the product is ready; for Viewer and Tile that is when the map inside the frame reports ready. A failed mount does not throw: if something fails, the loader logs one console error that contains [kaleidr:<product>] and the handle does nothing. The one call that throws is Kaleidr.mount with no options object, which raises a TypeError. There is no promise to await and no event that says a mount succeeded; Troubleshooting lists what to look for instead.
Reference: kaleidr.js and the <kaleidr-map> element.
The four products
| Product | What it is | Renders | Key | Scope it needs |
|---|---|---|---|---|
| Chat | A chat panel that answers questions about places and shows the answers on a map: pins, camera moves, routes | In your page | Publishable key, or none on a published map | ai |
| Viewer | A map published from Kaleidr Studio | In a Kaleidr iframe | None | None |
| Tile | A Kaleidr-designed basemap as a ready-made interactive map | In a Kaleidr iframe | Publishable key | maps |
| Editor | A map editor: text, images, markers, drawing | In your page | Publishable key | design |
Chat is the product that attaches to something you already have. It works with a map you run yourself (Mapbox GL JS, MapLibre GL JS, the Google Maps JavaScript API or Leaflet), with a Viewer or Tile element on the same page, or with no map at all as a chat-only panel.
All four products run on every plan, Free included.
Two ways a product renders
Where a product's code runs is the most useful thing to know about it.
In your page: Chat and Editor
Chat and Editor run as scripts in your own document. Their elements are part of your DOM and their network requests come from your page.
What follows from that:
- Your Content Security Policy applies to them. If your site sends a policy, it must allow scripts from
https://cdn.kaleidr.com, connections tohttps://api.kaleidr.com, and inline styles, because both products add their styles to your page. Editor also loads its basemap fromhttps://tile.kaleidr.com. - Their styles share your page. Chat adds one
<style>tag to your document head and sets its theme values as CSS variables on the root element. Those are page-wide and remain after the panel is destroyed. - Layout is yours to provide. By default the chat panel is a fixed window at the top-left of the browser window. To dock it inside your map, mount it with
contained: trueinto an element that is positioned and has a height. See Theming and layout. - Chat can use your map object. Because it runs in your page, Chat calls your map library directly to add its own markers, move the camera and draw routes. It does not change your layers, sources or markers, and it sends none of them to Kaleidr.
In a Kaleidr iframe: Viewer and Tile
Viewer and Tile put an <iframe> inside the element you mount them on. The map runs inside that frame, in a document served from https://map-embed.kaleidr.com.
What follows from that:
- Your policy needs very little. Allow the loader script from
https://cdn.kaleidr.comand a frame fromhttps://map-embed.kaleidr.com. Tile also callshttps://api.kaleidr.comfrom your page to exchange the key. Nothing the map loads inside the frame is subject to your policy. - Nothing leaks into your page. The frame's styles and scripts cannot affect your document, and yours cannot affect the map.
- You size the box; the frame fills it. Give the element a height. A
<kaleidr-map>element isdisplay:blockby default, so the height applies. The snippets writestyle="display:block; height:480px", which also covers Safari before 16.4, where the element stays inline. An element with no height gets a frame 500 pixels tall. - You cannot reach the map object. There is no map instance to call. You control the map through the handle (
setCameraon both,setStyleon Tile) and learn that it loaded or failed from two messages the frame posts to your window. See Viewer embed.
| In your page (Chat, Editor) | In a Kaleidr iframe (Viewer, Tile) | |
|---|---|---|
| Your Content Security Policy must allow | Kaleidr scripts, API connections, inline styles | The loader script and one frame host |
| Styles | Share your page | Isolated in the frame |
| Layout | You position the panel or the editor | You size the element; the frame fills it |
| Access to a map object | Chat drives the map you pass it | None; use the handle |
| Needs a map library on your page | Chat uses yours; Editor brings its own | No |
The complete policy for each product is in Content Security Policy.
Keys
A key identifies your organization. There are two types, and they are used in different ways.