React
The @yak-io/react package provides React components and hooks for integrating Yak into any React application.
For Next.js applications, use @yak-io/nextjs instead for automatic route scanning and better integration.
Installation
npm install @yak-io/react @yak-io/javascriptpnpm add @yak-io/react @yak-io/javascriptyarn add @yak-io/react @yak-io/javascriptbun add @yak-io/react @yak-io/javascriptQuick Start
Add the Provider and Widget
// App.tsx
import { YakProvider, YakWidget } from "@yak-io/react";
export default function App() {
return (
<YakProvider
appId="your-app-id"
getConfig={async () => {
const res = await fetch("/api/yak");
return res.json();
}}
onToolCall={async (name, args) => {
const res = await fetch("/api/yak", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, args }),
});
const data = await res.json();
if (!data.ok) throw new Error(data.error);
return data.result;
}}
>
{/* Your app content */}
<YakWidget />
</YakProvider>
);
}Set up server handlers
Use @yak-io/javascript to create the API endpoints. See Server Handlers for runtime-specific examples.
// api/yak.ts
import { createYakHandler } from "@yak-io/javascript/server";
export const { GET, POST } = createYakHandler({
routes: [
{ path: "/", title: "Home" },
{ path: "/products", title: "Products" },
],
});Components
YakProvider
The context provider managing widget state and iframe communication.
<YakProvider
appId="your-app-id"
getConfig={async () => fetch("/api/yak").then(r => r.json())}
onToolCall={async (name, args) => {
const res = await fetch("/api/yak", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, args }),
});
return res.json();
}}
theme={{ position: "right" }}
onRedirect={(path) => navigate(path)}
>
{children}
</YakProvider>Props
| Prop | Type | Required | Description |
|---|---|---|---|
appId | string | ✓ | Your Yak application ID |
getConfig | () => Promise<ChatConfig> | Provider for routes/tools config | |
onToolCall | (name, args) => Promise<unknown> | Handler for tool execution | |
theme | Theme | Widget theming options | |
onRedirect | (path: string) => void | Custom navigation handler | |
disableRestartButton | boolean | Hide the restart session button in the header |
YakWidget
Renders the floating chat button and iframe panel.
<YakWidget
iframeClassName="custom-iframe-class"
triggerLabel="Ask AI"
/>Hooks
useYak
Access the widget API from any component:
import { useYak } from "@yak-io/react";
export function ChatButton() {
const { open, close, openWithPrompt, isOpen } = useYak();
return (
<div>
<button onClick={() => open()}>Open Chat</button>
<button onClick={() => openWithPrompt("Help me with this page")}>
Get Help
</button>
{isOpen && (
<button onClick={() => close()}>Close</button>
)}
</div>
);
}Return Value
| Property | Type | Description |
|---|---|---|
open | () => void | Open the chat panel |
close | () => void | Close the chat panel |
openWithPrompt | (prompt: string) => void | Open with a pre-filled prompt |
isOpen | boolean | Current open/closed state |
useYakToolEvent
Subscribe to tool call completion events for page-level cache invalidation. This is useful when the chatbot modifies data via tool calls and you need to refresh specific UI components.
import { useYakToolEvent } from "@yak-io/react";
function OrderPage({ orderId }: { orderId: string }) {
const queryClient = useQueryClient();
useYakToolEvent((event) => {
// Invalidate cache when order-related tools are called
if (event.ok && event.name.startsWith("order.")) {
queryClient.invalidateQueries({ queryKey: ["order", orderId] });
}
});
return <OrderDetails orderId={orderId} />;
}Event Object
| Property | Type | Description |
|---|---|---|
name | string | The tool name that was called (e.g., "order.cancel") |
args | unknown | The arguments passed to the tool |
ok | boolean | Whether the call succeeded |
result | unknown | The result (if ok is true) |
error | string | The error message (if ok is false) |
The hook automatically unsubscribes when the component unmounts, making it safe for page-specific invalidation.
Navigation Integration
The onRedirect prop integrates with your router:
// React Router
import { useNavigate } from "react-router-dom";
function App() {
const navigate = useNavigate();
return (
<YakProvider onRedirect={(path) => navigate(path)} {...props}>
{children}
</YakProvider>
);
}
// TanStack Router
<YakProvider onRedirect={(path) => router.navigate({ to: path })} />
// Full reload (default)
<YakProvider onRedirect={(path) => window.location.href = path} />Styling
Customize the widget position, color mode, and display mode:
<YakProvider
theme={{
position: "right", // or "left"
colorMode: "system", // "light", "dark", or "system"
displayMode: "chatbox", // "chatbox" (floating panel) or "drawer" (side panel)
}}
{...props}
>
<YakWidget triggerLabel="Chat with AI" />
</YakProvider>For drawer mode, the position controls which side the drawer appears on ("right" → right side, "left" → left side).
See Styling for display modes and CSS variable customization.
TypeScript
The package is fully typed:
import { useYak } from "@yak-io/react";
import type { YakConfig, YakMessage } from "@yak-io/react";
function MyComponent() {
const {
openWidget,
closeWidget,
openWithPrompt,
isWidgetOpen,
config, // YakConfig | null
sendMessage, // (message: YakMessage) => void
} = useYak();
}