Programmatic API
Control the chat widget programmatically from anywhere in your application using the useYak hook.
Live Demo
Try the programmatic API right here:
Interactive Demo
Click any button below to see the programmatic API in action. Each button demonstrates a different way to control the chat widget.
useYak hook that you'll use in your application. The chat widget on this page is a live instance running with the Yak API.Basic Usage
import { useYak } from "@yak-io/nextjs/client";
// or: import { useYak } from "@yak-io/react";
function MyComponent() {
const { open, close, openWithPrompt, isOpen } = useYak();
return (
<div>
<button onClick={() => open()}>Open Chat</button>
<button onClick={() => openWithPrompt("Help me!")}>Get Help</button>
{isOpen && <button onClick={() => close()}>Close</button>}
</div>
);
}API Reference
useYak()
Returns an object with widget control methods.
| Property | Type | Description |
|---|---|---|
open | () => void | Open the chat panel |
close | () => void | Close the chat panel |
openWithPrompt | (prompt: string) => void | Open with a specific prompt |
isOpen | boolean | Whether the chat is open |
Prompts sent via openWithPrompt are automatically queued if called before the iframe is ready.
useYakToolEvent()
Subscribe to tool call completion events. Useful for cache invalidation when the chatbot modifies data.
import { useYakToolEvent } from "@yak-io/nextjs/client";
// or: import { useYakToolEvent } from "@yak-io/react";
function OrderPage({ orderId }: { orderId: string }) {
const utils = trpc.useUtils();
useYakToolEvent((event) => {
if (event.ok && event.name.startsWith("order.")) {
utils.order.get.invalidate({ id: orderId });
}
});
return <OrderDetails orderId={orderId} />;
}| Event Property | Type | Description |
|---|---|---|
name | string | Tool name called (e.g., "order.cancel") |
args | unknown | Arguments passed to the tool |
ok | boolean | Whether the call succeeded |
result | unknown | Result (if ok is true) |
error | string | Error message (if ok is false) |
Common Patterns
Context-Sensitive Help
Open with context-specific prompts based on the page:
"use client";
import { useYak } from "@yak-io/nextjs/client";
import { usePathname } from "next/navigation";
export function ContextualHelpButton() {
const { openWithPrompt } = useYak();
const pathname = usePathname();
const getHelpPrompt = () => {
if (pathname.includes("/billing")) return "Help me with billing";
if (pathname.includes("/settings")) return "Guide me through settings";
return "Help me with this page";
};
return (
<button onClick={() => openWithPrompt(getHelpPrompt())}>
Get Help
</button>
);
}Feature Onboarding
Guide users through features:
function FeatureCard({ title, description }: Props) {
const { openWithPrompt } = useYak();
return (
<div className="feature-card">
<h3>{title}</h3>
<p>{description}</p>
<button onClick={() => openWithPrompt(`Show me how to use ${title}`)}>
Learn More
</button>
</div>
);
}Error Assistance
Offer help when errors occur:
function ErrorFallback({ error }: { error: Error }) {
const { openWithPrompt } = useYak();
return (
<div>
<h2>Something went wrong</h2>
<p>{error.message}</p>
<button
onClick={() => openWithPrompt(`Help me fix: ${error.message}`)}
>
Get AI Assistance
</button>
</div>
);
}Cache Invalidation
Keep your UI in sync when chatbot tool calls modify data:
import { useYakToolEvent } from "@yak-io/react";
import { trpc } from "@/utils/trpc";
function PlanPage({ planId }: { planId: string }) {
const utils = trpc.useUtils();
// Subscribe to tool completion events
useYakToolEvent((event) => {
// Only invalidate on successful mutations that affect this page
if (event.ok) {
if (event.name.startsWith("plan.")) {
utils.plan.get.invalidate({ id: planId });
}
if (event.name.startsWith("planItem.")) {
utils.planItem.list.invalidate({ planId });
}
}
});
// The page automatically refreshes when the chatbot modifies plans
return <PlanDetails planId={planId} />;
}The hook unsubscribes automatically when the component unmounts, so each page only handles invalidation for its own data.
Keyboard Shortcuts
Toggle the chat with a keyboard shortcut:
import { useEffect } from "react";
import { useYak } from "@yak-io/react";
function useYakShortcut() {
const { open, close, isOpen } = useYak();
useEffect(() => {
function handleKeyDown(e: KeyboardEvent) {
// Cmd/Ctrl + K to toggle
if ((e.metaKey || e.ctrlKey) && e.key === "k") {
e.preventDefault();
isOpen ? close() : open();
}
// Escape to close
if (e.key === "Escape" && isOpen) {
close();
}
}
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [openWidget, closeWidget, isWidgetOpen]);
}Smart Help Menu
Create a help menu with predefined prompts:
const helpTopics = [
{ label: "Getting Started", prompt: "Show me how to get started" },
{ label: "Account Settings", prompt: "Help me configure my account" },
{ label: "Billing Questions", prompt: "I have questions about billing" },
];
function HelpMenu() {
const { openWithPrompt } = useYak();
return (
<div className="help-menu">
<h3>How can we help?</h3>
<ul>
{helpTopics.map((topic) => (
<li key={topic.label}>
<button onClick={() => openWithPrompt(topic.prompt)}>
{topic.label}
</button>
</li>
))}
</ul>
</div>
);
}Best Practices
Clear Prompts
Use specific, contextual prompts:
// ✓ Good - specific
openWithPrompt("How do I export my project data to CSV?");
// ✗ Less ideal - too vague
openWithPrompt("Help");Avoid Auto-Opening
Don't auto-open without user action:
// ✓ Good - user-initiated
<button onClick={() => open()}>Need Help?</button>
// ⚠️ Use sparingly
useEffect(() => {
if (isCriticalError) {
openWithPrompt("Help me resolve this error");
}
}, [isCriticalError]);Check State
Avoid opening multiple times:
const { isOpen, openWithPrompt } = useYak();
const handleHelp = () => {
if (!isOpen) {
openWithPrompt("How do I use this feature?");
}
};Don't include sensitive data in prompts (passwords, tokens, personal information).