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.js → customCss (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.