Skip to content
Pilotoo
v0.1

Embedding the web chat

mountChat puts the whole chat in an element of a page you already have, with no React in your app. It is the quickest way to add the assistant to a site, a dashboard or a CMS page. It is built from the demo web app and is not published as a kit package, so you build the bundle yourself.

If your app is React and you want to compose the pieces, use ChatProvider and ChatPanel from Chat UI instead.

Terminal window
pnpm --filter @pilotoo/web build:embed

The build writes two files to apps/web/dist-embed/: pilotoo-chat.js, an ES module with React and the kit inside, and pilotoo-chat.css. Serve both from your site.

<link rel="stylesheet" href="/pilotoo-chat.css" />
<div id="chat" style="height: 640px"></div>
<script type="module">
import { mountChat } from '/pilotoo-chat.js';
const chat = mountChat(document.getElementById('chat'), {
apiUrl: 'https://gateway.example.com',
credentials: () => session.token,
onConversationChange: (id) => console.log('now reading', id),
});
// later: chat.unmount();
</script>

mountChat returns { unmount() }. Call it when the host page removes the element.

Restoring a conversation and storing state

Section titled “Restoring a conversation and storing state”

By default the embed keeps drafts, the theme choice and the last conversation in memory. Pass a storage to keep them, and a conversationId to open on a specific conversation.

mountChat(element, {
apiUrl,
credentials: () => session.token,
conversationId: savedId,
storage: {
getItem: async (key) => localStorage.getItem(key),
setItem: async (key, value) => localStorage.setItem(key, value),
removeItem: async (key) => localStorage.removeItem(key),
},
theme: 'dark',
onConversationChange: (id) => save(id),
});
Option Meaning
apiUrl The gateway. Required.
credentials () => token | undefined, read before every request and socket connection.
conversationId The conversation to open on; the new-conversation screen otherwise.
storage A KeyValueStorage for drafts, the theme choice and the last conversation. Memory when omitted.
onConversationChange Called with the conversation id, or undefined for the new-conversation screen.
theme 'light' | 'dark' | 'system'; overrides a stored choice.
  • It never writes your localStorage unless you hand it a storage.
  • Routing is in memory. It never reads or writes location.hash.
  • While mounted, your element gets the class pilotoo-chat and a data-theme attribute.
  • Every rule in pilotoo-chat.css matches only .pilotoo-chat or its descendants, and is one class more specific than Tailwind’s, so a host rule such as input { padding: 8px } does not reach into the chat.
  • The embed ships without voice.