@kelu/react gives you <KeluChat />, a finished chat panel, and useKeluChat, a hook for building your own. It needs react and react-dom 18 or later, depends on @kelu/sdk, and re-exports its types and KeluError.
@kelu/react is not on npm yet, so npm install @kelu/react fails today. Until it is published, embed the website widget or call the REST API directly.
Example
"use client";
import { KeluChat } from "@kelu/react";
export default function HelpPage() {
return (
<KeluChat
knowledgeBaseId="YOUR_KNOWLEDGE_BASE_ID"
clientKey="kl_pk_..."
welcomeMessage="Hi! Ask me anything about our documentation."
theme={{ primaryColor: "#5b21b6" }}
/>
);
}
Both exports use React hooks. In the Next.js App Router, use them from a file that starts with "use client".
KeluChat props
| Prop | Type | Default | Description |
|---|
knowledgeBaseId | string | required | The knowledge base to answer from |
clientKey | string | required | Public client key (kl_pk_…) |
baseUrl | string | https://app.kelu.dev | API base URL |
placeholder | string | "Ask a question…" | Input placeholder |
welcomeMessage | string | none | Shown while the chat is empty |
theme | { primaryColor?, borderRadius? } | #343CED, 12px | Accent colour (buttons, links, citation numbers) and corner radius |
className | string | none | Class name on the outer wrapper |
groupIds | string[] | none | Answer and search only from these source groups |
searchEnabled | boolean | false | Show an Ask AI / Search toggle. Search lists matching pages without an answer |
defaultMode | "ask" | "search" | "ask" | Which mode opens first when searchEnabled is on |
searchPlaceholder | string | "Search sources…" | Placeholder in search mode |
searchLimit | number | 8 | Search results to show |
labels | Partial<ChatLabels> | English | Replace any of the search-mode strings, for example { modeAsk: "Ask", searchEmpty: "Nothing found." } |
getCaptchaToken | () => Promise<string> | none | Returns a reCAPTCHA v3 token when the deployment requires one |
In search mode, the search runs when the reader presses Enter or the search button, with at least 2 characters typed.
ChatLabels keys: modeAsk, modeSearch, searchHint, searchEmpty, searchFailed, searching, fromTheDocs, askAiRow ({query} is replaced with the text typed) and askAiRowSub.
The header reads AI Assistant and the footer shows Powered by Kelu. Neither can be changed. For your own markup, use the hook.
useKeluChat(options)
import { useKeluChat } from "@kelu/react";
const { messages, ask, isStreaming, error, threadId, reset, sendFeedback, clearFeedback } =
useKeluChat({ knowledgeBaseId: "YOUR_KNOWLEDGE_BASE_ID", clientKey: "kl_pk_..." });
Options
| Option | Type | Default | Description |
|---|
knowledgeBaseId | string | required | The knowledge base to answer from |
clientKey | string | required | Public client key (kl_pk_…) |
baseUrl | string | https://app.kelu.dev | API base URL |
groupIds | string[] | none | Answer only from these source groups |
getCaptchaToken | () => Promise<string> | none | Returns a reCAPTCHA v3 token, sent with every ask() |
Return value
| Property | Type | Description |
|---|
messages | ChatMessage[] | User and assistant messages in order. The assistant message fills in as the answer streams |
ask | (query: string) => Promise<void> | Send a question on the current thread. Ignored while an answer is streaming or when the query is blank |
isStreaming | boolean | true while an answer is streaming |
error | KeluError | null | The last failed answer or rating. Cleared by the next ask() |
threadId | string | undefined | The conversation that later questions continue |
reset | () => void | Stop any answer and start a new conversation |
sendFeedback | (messageId, rating: "up" | "down", comment?) => Promise<void> | Rate an answer. A second rating replaces the first |
clearFeedback | (messageId) => Promise<void> | Remove the rating |
If a rating fails, sendFeedback and clearFeedback reject and set error to “Your rating could not be saved.”, so you can undo the button. Unmounting stops any answer in progress.
ChatMessage
| Field | Type | Description |
|---|
id | string | Local id, for React keys |
role | "user" | "assistant" | Who wrote it |
content | string | Message text |
citations | Citation[]? | On assistant messages: the sources the answer cited. Label each with its index, not its position |
messageId | string? | Set on assistant messages once the answer is complete. Pass it to sendFeedback. Absent when the workspace keeps no chat data |
Citation and the error codes on KeluError are in the @kelu/sdk reference.