Skip to main content
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.

Render starter prompts with the empty template

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.

Reuse the default greeting

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>
    `;
  },
},

Fetch starter prompts dynamically

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.

Customize more than the empty state

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.
Last modified on June 18, 2026