Skip to main content

Customising the chatbot UI

This template displays an Algolia InstantSearch Chat widget on every page. Most useful changes are about conversation flow: how sources appear, how links open, and how each assistant turn is ordered.

PieceFile
Mount on every pagesrc/theme/Root.js
Chat widget, tools, sources UIsrc/components/AlgoliaChat/index.js
Layout and brand tokens for chatsrc/components/AlgoliaChat/styles.module.css
InstantSearch chat stylesheetdocusaurus.config.jscustomCss (instantsearch.css/.../chat.css)

Credentials and agentId also live at the top of AlgoliaChat/index.js. Keep Search-Only keys in the client; never put the Admin API Key here.

How a turn is built

Each assistant reply can include:

  1. Markdown answer text
  2. Tool output (search hits from the agent)
  3. Follow-up prompt suggestions

Upstream InstantSearch often shows tool hits as a carousel of tiles. This template replaces that with a single Sources pill and popover, and CSS reorders the bubble so readers see answer → sources → follow-ups.

Changing how sources appear

Search and recommend tool results use a custom layout in sourceTools:

src/components/AlgoliaChat/index.js
const sourceTools = {
[SearchIndexToolType]: {layoutComponent: SourcesLayout},
[RecommendToolType]: {layoutComponent: SourcesLayout},
};

<Chat agentId={AGENT_ID} tools={sourceTools} ... />

SourcesLayout is the component that:

  • Collects hits from tool parts on the parent message
  • Deduplicates by objectID / url / path
  • Renders one pill (1 Source / N Sources) and a popover list of links
  • Returns null for later tool parts so you do not get a pill per tool call

Change the pill label

Edit the countLabel logic in SourcesLayout:

const countLabel =
items.length === 1 ? '1 Source' : `${items.length} Sources`;

For example use References or Docs used instead of Sources.

sourceLabel prefers the crawler heading (page H1), then title, then URL. It also strips a | Site title suffix from Docusaurus document titles:

const SITE_TITLE = '3di Docusaurus Template';

Update SITE_TITLE to match title in docusaurus.config.js when you rebrand. Adjust sourceLabel if you want URL paths or section titles instead.

Change the open behaviour

Links in the popover currently open in a new tab and fire a click insight event. To open in the same tab, remove target / rel from the <a> in SourcesLayout. To drop analytics, remove the sendEvent call.

Restore the default InstantSearch tool UI

Remove or empty tools={sourceTools} on <Chat /> if you want the stock search-index carousel and tiles again. You can also delete SourcesLayout and the related CSS under .sources* in styles.module.css.

Assistant text is not the InstantSearch default renderer. It uses AssistantText, which compiles markdown and routes anchors through ChatMarkdownLink:

messagesProps={{
assistantMessageProps: {
textComponent: AssistantText,
},
}}

ChatMarkdownLink adds an external-link icon for http(s) URLs and opens them in a new tab. Same-origin or relative links stay in the current tab.

To change that flow:

  1. Open src/components/AlgoliaChat/index.js.
  2. Edit ChatMarkdownLink (icons, target, classes).
  3. Or point textComponent at your own component with a different markdown pipeline.

Changing message order in the bubble

Tool DOM nodes often arrive before the answer text. This template uses flex order so the written answer stays first:

src/components/AlgoliaChat/styles.module.css
.root :global(.ais-ChatMessage--left .ais-ChatMessage-tool) {
order: 2;
/* ... */
}

Follow-up suggestions keep a separator under the answer and sources via .ais-ChatPromptSuggestions. Edit those rules if you want sources above the answer, or no rules between blocks.

Hiding InstantSearch chrome you do not use

This site has no dedicated InstantSearch results page, so the tool carousel “View all” control is hidden:

.root :global(.ais-ChatToolSearchIndexCarouselHeaderViewAll) {
display: none;
}

Remove that rule only if you add a full results route and want the control back.

Brand colour (optional)

Primary InstantSearch chrome (trigger accent, selection) follows CSS variables on .root:

--ais-primary-color-rgb: 79, 38, 131;

Dark theme overrides the same variables under html[data-theme='dark']. Prefer conversation-flow changes above for product behaviour; use these tokens when you only need the widget to match --ifm-color-primary.