Build a custom chat welcome screen with starter prompts using InstantSearch.js.
This widget is and is subject to change in minor versions.
When the chat widget has no messages yet, it shows a welcome screen. Use the empty template to replace it with your own greeting and a set of starter prompts. Each prompt sends a message to the agent when clicked, so users can start a conversation in one tap.If you only need prompt suggestions after the agent responds, use Agent Studio prompt suggestions instead.
The empty template receives a sendMessage function. Call it with { text } to submit a starter prompt as the first message:
JavaScript
import algoliasearch from "algoliasearch/lite";import instantsearch from "instantsearch.js";import { chat, chatTrigger } from "instantsearch.js/es/widgets";const search = instantsearch({ indexName: "instant_search", searchClient: algoliasearch("YourApplicationID", "YourSearchOnlyAPIKey"),});const starterPrompts = [ "What are your best-selling headphones?", "Help me find a gift under $50", "Compare espresso machines",];search.addWidgets([ chat({ container: "#chat", agentId: "YOUR_AGENT_ID", templates: { empty({ sendMessage }, { html }) { return html` <div class="ais-ChatGreeting"> <h2 class="ais-ChatGreeting-heading">How can I help you today?</h2> <p class="ais-ChatGreeting-subheading"> Ask me anything about our products, or start with a suggestion. </p> <div class="ais-ChatPromptSuggestions"> ${starterPrompts.map( (prompt) => html`<button type="button" class="ais-ChatPromptSuggestions-suggestion" onClick=${() => sendMessage({ text: prompt })} > ${prompt} </button>`, )} </div> </div> `; }, }, }), chatTrigger({ container: "#chat-trigger", }),]);search.start();
The chat widget renders the panel but doesn’t open it on its own. Add an entry point on the same InstantSearch instance: the chatTrigger widget, AI mode on a searchBox, or an inline layout.
The empty template reuses the built-in classes (ais-ChatGreeting and ais-ChatPromptSuggestions) so it inherits the default styling. Replace them with your own classes to fully restyle the welcome screen.
Instead of writing the greeting markup yourself, render the built-in greeting with the exported chatGreeting template helper, then add your starter prompts below it. The helper renders the default heading and subheading, and accepts a banner image, translations, and classNames:
JavaScript
import { chatGreeting } from "instantsearch.js/es/templates";const greeting = chatGreeting({ banner: "https://example.com/welcome-banner.png", translations: { heading: "Welcome to our store", subheading: "Ask me anything, or pick a suggestion to get started.", },});// In the chat widget:templates: { empty(props, { html }) { return html` <div> ${greeting(props)} <div class="ais-ChatPromptSuggestions"> ${starterPrompts.map( (prompt) => html`<button type="button" class="ais-ChatPromptSuggestions-suggestion" onClick=${() => props.sendMessage({ text: prompt })} > ${prompt} </button>`, )} </div> </div> `; },},
The prompts don’t have to be static. Fetch them once (for example, from a dedicated Agent Studio agent that returns starter prompts), store them, and render them from the empty template:
JavaScript
const appID = "YourApplicationID";const apiKey = "YourSearchOnlyAPIKey";const promptsAgentId = "YOUR_STARTER_PROMPTS_AGENT_ID";async function getStarterPrompts() { const response = await fetch( `https://${appID}.algolia.net/agent-studio/1/agents/${promptsAgentId}/completions?stream=false&cache=true&compatibilityMode=ai-sdk-5`, { method: "POST", headers: { "Content-Type": "application/json", "X-Algolia-Application-Id": appID, "X-Algolia-API-Key": apiKey, }, body: JSON.stringify({ messages: [ { role: "user", parts: [{ text: "Return starter prompts for the welcome screen." }], }, ], }), } ); const data = await response.json(); const text = data.parts?.find((part) => part.type === "text")?.text ?? ""; return text .split("\n") .map((line) => line.trim()) .filter(Boolean);}let starterPrompts = [];getStarterPrompts() .then((prompts) => { starterPrompts = prompts; // Re-render the chat so the empty template picks up the prompts. search.refresh(); }) .catch(() => { starterPrompts = []; });
Reference starterPrompts from the empty template, exactly as in the static example above.
The empty template only replaces the initial empty state. To customize the surrounding chat layout (header, message list, prompt input), use the layout template instead. See instantsearch.templates.chatInlineLayout() for an inline (non-overlay) layout.