Yak Docs
SDKs

React SDK

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 App Router integration.

Installation

npm install @yak-io/react @yak-io/javascript
pnpm add @yak-io/react @yak-io/javascript
yarn add @yak-io/react @yak-io/javascript
bun add @yak-io/react @yak-io/javascript

Quick 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 on your backend. See the JavaScript SDK for runtime-specific examples (Express, Hono, Cloudflare Workers, etc.).

// 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

Wraps your application and manages widget state and communication.

PropTypeRequiredDescription
appIdstringYesYour Yak application ID
mode"chat" | "voice" | "both"NoWhich surfaces the trigger exposes. Defaults to "chat". See Voice Mode.
getConfig() => Promise<ChatConfig>NoConfig provider for routes and tools (used by chat and voice)
onToolCall(name, args) => Promise<unknown>NoHandler for tool execution (used by chat and voice)
themeThemeNoWidget styling options
onRedirect(path: string) => voidNoCustom navigation handler
disableRestartButtonbooleanNoHide the restart button in the header
user{ id, hash }NoSigned end-user identity. Enables server-side conversation persistence and the history pane.

YakWidget

Renders the trigger pill — logo plus one or two icon buttons depending on mode.

PropTypeDefaultDescription
mode"chat" | "voice" | "both"inherited from providerOverride the provider mode for this trigger
positionWidgetPosition"bottom-left"One of nine positions (e.g. "bottom-right", "top-center")
colorMode"light" | "dark" | "system"Force a color mode for the pill
lightButton{ background?, color?, border? }Custom pill colors in light mode
darkButton{ background?, color?, border? }Custom pill colors in dark mode

Hooks

useYak

Access widget controls from any component inside YakProvider:

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>
  );
}
PropertyTypeDescription
mode"chat" | "voice" | "both"The current mode the provider was configured with
open() => voidOpen the chat panel
close() => voidClose the chat panel
openWithPrompt(prompt: string) => voidOpen and send a specific prompt
isOpenbooleanWhether the chat panel is currently open
isReadybooleanWhether the chat iframe has loaded and can receive messages
chatLoadingbooleanisOpen && !isReady — the panel is opening but not yet interactive
voiceStateVoiceState"idle" | "connecting" | "listening" | "thinking" | "speaking" | "error"
voiceIsActivebooleantrue while a voice session is live
voiceLoadingbooleantrue while the voice session is connecting
voiceStart()() => Promise<void>Start a voice session (call from a user gesture)
voiceStop()() => Promise<void>Stop the current voice session
voiceToggle()() => Promise<void>Start if idle/error, stop if active

See Voice Mode for the full voice API and behavior.

useYakToolEvent

Subscribe to tool call completion events — useful for keeping your UI in sync with agent actions:

import { useYakToolEvent } from "@yak-io/react";

function OrderPage({ orderId }: { orderId: string }) {
  const queryClient = useQueryClient();

  useYakToolEvent((event) => {
    if (event.ok && event.name.startsWith("order.")) {
      queryClient.invalidateQueries({ queryKey: ["order", orderId] });
    }
  });

  return <OrderDetails orderId={orderId} />;
}

See UI Synchronization for more details.

Router Integration

Pass your framework's navigation function to onRedirect for client-side navigation:

// 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 })} />

Next Steps

On this page