The BeforeQuery widget is a single script tag that adds instant search and streaming RAG chat with source citations to any page. Styles are isolated in a Shadow DOM — zero CSS leakage. Installing on a docs platform or CMS? See the per-platform guides: Mintlify, Docusaurus, GitBook, ReadMe, VitePress, MkDocs, Sphinx, Next.js, WordPress, Webflow, Shopify, plain HTML.

Quick start

Configuration

Every option can be set as a data-* attribute on the script tag, or as the equivalent camelCase key passed to init(). These are the ones most sites set:

Full configuration reference

All 160-odd options — launcher, modal chrome, open triggers, consent, hand-off, surveys, analytics identity, theme tokens, and the kapa.ai attribute spellings the widget also answers to.
Booleans are true unless the value is exactly "false" or "0", and an absent attribute leaves the default rather than meaning false — which matters for the options that default to on, like data-instant-search and data-exit-feedback-enabled.

View modes

A centered overlay triggered by the floating launcher. Closes on backdrop click or Esc.

Making the panel bigger

The panel header has a button, so a reader with a long answer in front of them can give it more room. puts it back. Their choice is saved in the browser, per knowledge base: expand it on one page and it is already expanded on the next. On phones there is no button, because the panel already fills the screen. Two attributes change it, both optional. data-modal-expanded-size sets how big “expanded” is, and data-modal-expand-button-hidden removes the button:
The arrangement most docs sites want: an Ask AI button in the header, next to the search box, where a reader who has just failed to find something is looking. There are two ways round it, and which one you need depends on one thing — can you edit your header’s markup? No (a hosted docs theme — Mintlify, GitBook, ReadMe). Name an element that is already there, and the widget puts its own button beside it:
The button becomes a labelled toolbar control — 36px, no drop shadow, no animations — and keeps its own shadow root, so your header’s CSS cannot restyle it by accident. Anchors are re-checked for the life of the page, so a header your framework re-renders on every navigation gets its button back. Finding the selector: right-click your search box → Inspect → read the id="…" off the highlighted tag (#that-id), or one of its classes (.that-class). Check it in the console with document.querySelectorAll("…") before you ship it.

Your own “Ask AI” button

Yes, you can edit the header. Then keep the button in your own markup and point the widget at it — it inherits your styling and sits exactly where your layout puts it.
Triggers are bound by delegation on document, so a button your framework re-renders on every route change keeps working without re-initialising the widget. data-open-query-from is what stops the reader typing the question twice: they typed it into the search box, then pressed the button next to it. Without it the panel opens with an empty composer. The same thing from code, if you would rather wire the click yourself:

Programmatic API

For SPAs, initialize and control the widget from code. Everything hangs off window.BeforeQueryWidget:

Methods

Events

Every widget interaction is reported to a callback, which is how a docs team gets “how many opened it, what did they ask, did the answer land” into the analytics tool they already use:
Handlers run inside a try/catch. A broken analytics snippet logs and is stepped over; it cannot take the chat down with it. Subscriptions outlive any one instance, so unmount() then render() keeps reporting, and registering before the bundle has finished loading is safe.
Migrating from another widget — there is a callable form of the same bus:
The event names and payload shapes match kapa.ai’s, so an existing analytics wiring can be pointed here without being rewritten. The same goes for the embed itself: where an attribute has two spellings, the second is the one a kapa script tag already carries.

Keyboard shortcut & dark mode

  • Cmd+K (Mac) / Ctrl+K (Windows/Linux) opens the widget by default. Change with data-hotkey="/" or disable with data-hotkey="none". Esc always closes.
  • The widget renders light unless told otherwise. Set data-color-scheme="auto" to follow the visitor’s OS preference, or "dark" to force it. Better still on a site with its own theme switch: point data-color-scheme-selector at the class that switch toggles (html.dark), which wins over both and is re-checked as the page changes, so the widget follows the toggle mid-session.

Features at a glance

  • Instant search results as you type (debounced 250 ms)
  • Optional Search tab — matching pages, no answer generated
  • Streaming RAG chat with numbered source citations
  • Follow-up questions continue the same thread
  • Thumbs up / down feedback, plus optional satisfaction and exit prompts
  • 11 UI languages
  • Full theming with separate light and dark palettes, and a selector that follows your site’s own toggle
  • Consent screen and footer privacy links for GDPR-style flows
  • “Talk to a human” escalation on configurable triggers
  • “Connect to AI tools” menu offering the MCP server
  • reCAPTCHA v3 support (configured server-side via the widget-config API)
  • Mobile full-screen sheet layout
  • White-label branding: custom name, logo, accent color, and hideable footer (enterprise)

Local testing