Yak Docs
Reference

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.

Try it yourself!
These buttons are using the same 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.

PropertyTypeDescription
open() => voidOpen the chat panel
close() => voidClose the chat panel
openWithPrompt(prompt: string) => voidOpen with a specific prompt
isOpenbooleanWhether 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 PropertyTypeDescription
namestringTool name called (e.g., "order.cancel")
argsunknownArguments passed to the tool
okbooleanWhether the call succeeded
resultunknownResult (if ok is true)
errorstringError 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).

On this page