The chat widget
The launcher
Section titled “The launcher”A round bubble in the bottom-right corner of the page, in your brand color. Clicking it opens and closes the chat panel.
The launcher can be moved: press and hold it for about half a second without moving, then drag it anywhere on the page. A drag that completes doesn’t open the panel, so moving the bubble never accidentally starts a chat. Its position is clamped to stay on screen, and it’s remembered for that site in the browser’s localStorage. When the panel is docked, it re-anchors itself just above wherever the launcher now sits.
The panel
Section titled “The panel”The header shows your header title (Settings → header title; it falls back to your workspace name) and two controls: a ⋯ window menu and a × close button. Your own admins additionally get a 💡 feedback menu.
The ⋯ menu has three items:
- Detach window / Dock to corner — detached, the panel floats free and you drag it by its header; docked, it’s anchored to the bottom-right corner above the launcher.
- Reset size & position — clears the remembered size, panel position, detached/docked mode, and launcher position all at once.
- New conversation — starts a fresh conversation.
Resizing: drag the small grip in the panel’s top-left corner. Because the panel is anchored bottom-right, dragging up and to the left grows it. The panel won’t go below 320 × 400 pixels, and won’t exceed 90% of the window in either direction.
Mode, size, panel position, and launcher position are each remembered per site in localStorage, and everything is clamped on restore — a window that shrinks or a phone that rotates can’t strand the panel off screen.
Careful with the ×: if the visitor has sent at least one message, × ends the conversation (and offers the rating prompt). On an empty or already-ended conversation it just collapses the panel. Clicking the launcher always just collapses.
Sending messages
Section titled “Sending messages”Type in the composer and press Enter to send; Shift+Enter inserts a newline. A message can be up to 4,000 characters.
If a reply takes unusually long the composer unlocks itself after 45 seconds with a note that the answer will appear when it’s ready — the visitor is never stuck.
Attachments
Section titled “Attachments”Three ways to attach a file:
- Click the 📎 button and pick one (this is the only way to attach a document — you can paste a screenshot, but not a PDF).
- Paste from the clipboard into the composer.
- Drag and drop onto the chat panel; the panel outlines itself when a droppable file is over it.
What’s accepted:
| Kind | Types | Size cap |
|---|---|---|
| Images | PNG, JPEG, WebP, GIF | 15 MB |
| Documents | PDF, TXT, CSV, Markdown, RTF, DOC/DOCX, XLS/XLSX, PPT/PPTX | 25 MB |
Two things worth knowing. First, the widget’s own pre-check only rejects files over 25 MB, so an image between 15 MB and 25 MB is accepted by the browser and then refused by the server — the visitor sees “Couldn’t upload <filename>”. Second, browsers report file types unreliably for anything but images, so when the type is missing or generic the file extension decides. An extension that isn’t on the list above is never accepted, whatever the file claims to be.
Uploads start the moment the file is attached, not when Send is pressed, and each one shows a progress bar. If the composer is empty when an upload finishes, the message posts itself — drop a screenshot and it just appears. If the visitor is mid-sentence, the file waits for Send so the caption and the file stay together. Sending waits for any upload still in flight and drops the ones that failed, so the text still goes through.
Images render as thumbnails in the transcript; documents render as a download chip with the extension and file size. Operators can attach files to their replies too, and they show the same way.
Formatting in bot replies
Section titled “Formatting in bot replies”The widget renders a deliberately small markdown subset in assistant messages: headings, bullet and numbered lists, inline code, fenced code blocks, **bold**, *italic*, [links](https://example.com), and bare URLs turned into links. Underscores are not treated as emphasis on purpose — snake_case identifiers in a support answer would otherwise turn into italics. Links open in a new tab.
Slash commands
Section titled “Slash commands”Type /help in the composer to list them.
/help— list the available commands./new— start a new conversation (/clearand/resetdo the same)./end— end this conversation.
Slash commands work even when the widget is waiting on a reply or the conversation has already ended, so they’re always an escape hatch.
Starting a new conversation
Section titled “Starting a new conversation”⋯ → New conversation, /new, or the “Start a new chat” button on an ended conversation. This does not delete the previous conversation — it stays in your workspace with its transcript intact. The widget simply forgets which conversation it was on, and the next message starts a fresh one.
Idle conversations
Section titled “Idle conversations”After three minutes with no typing or activity, the widget shows a “Still there? Ending in 60s” banner with Keep chatting and End now. If the countdown runs out the conversation ends by itself. This is separate from the workspace-level auto-close described in How a conversation is handled.
Ratings
Section titled “Ratings”When a conversation ends and the visitor sent at least one message, they’re offered Was this helpful? — a 0 to 5 star scale plus an optional comment, or Skip. Ratings and comments show up on your Chats page.
Screenshots
Section titled “Screenshots”An operator can ask to see the visitor’s screen from the workspace. The visitor gets a prompt in the transcript — “…asks to see a screenshot of this page. Nothing is shared until you agree.” — with Share screenshot and Not now. Nothing is captured unless the visitor explicitly agrees, and the captured image arrives as a normal attachment.
Continuity and isolation
Section titled “Continuity and isolation”- Shadow DOM. All the widget’s markup and CSS live inside a shadow root, so your site’s styles and the widget’s can’t affect each other.
- No third-party cookies. Identity is a 32-character visitor token in
localStorage, sent as a request header. The widget works in browsers that block third-party cookies. - Resume. Conversations survive page reloads and revisits in the same browser. If
localStorageis blocked or full (private-browsing modes), the widget falls back to an in-memory token: chat works for that page load but doesn’t survive a reload. - Live updates. Replies stream in over a WebSocket. If that connection is refused or blocked, the widget falls back to refreshing every 10 seconds so replies still arrive.