React & Next.js Integration
Chatty provides two simple, zero-bundle-bloat ways to integrate into React and Next.js applications:
- The Official npm Package (
@personaliai/react-widget): A lightweight (< 2 kB) typed React component and hook that loads the assistant via the script method in an isolated Shadow DOM container. - Direct Script Tag (
widget.js): Add the<Script>component directly to your Next.js root layout with zero npm dependencies.
Building a mobile app? For React Native and Expo applications, use the official native mobile package @personaliai/react-native (see Mobile SDKs), which renders true native View and Text components without WebViews.
Method 1: Official React Package (@personaliai/react-widget)
The official @personaliai/react-widget package provides a plug-and-play React component and hook that automates script injection and exposes typed controls.
1. Install
npm install @personaliai/react-widget
# or
yarn add @personaliai/react-widget
# or
pnpm add @personaliai/react-widget2. Add <ChattyWidget /> to Your Layout
import { ChattyWidget } from "@personaliai/react-widget";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
{children}
{/* Mounts Chatty via script method into isolated Shadow DOM */}
<ChattyWidget
botId="YOUR_BOT_UUID"
position="right"
color="#4F46E5"
/>
</body>
</html>
);
}Component Props
| Prop | Type | Default | Description |
|---|---|---|---|
botId | string | Required | Your bot's unique UUID from the Chatty dashboard. |
position | "right" | "left" | "right" | Corner anchor position for launcher trigger button. |
color | string | Dashboard color | Hex color override for launcher trigger button (e.g. #4F46E5). |
style | string | Dashboard style | Design preset override ("minimal", "playful", etc.). |
mobileFullscreen | boolean | true | When true, expands full-screen on mobile viewports. |
teaser | boolean | true | Whether to display the greeting teaser bubble after delay. |
sound | boolean | true | Whether to play sound chimes on incoming AI replies. |
widgetUrl | string | "https://chatty.personaliai.com/widget.js" | Custom widget script URL (for self-hosting). |
Method 2: Direct Script Embed (Zero Dependencies)
If you prefer not to install any npm packages, you can use Next.js's built-in next/script component:
Next.js (App Router & Pages Router)
import Script from "next/script";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
{children}
{/* Chatty Web Widget Script */}
<Script
src="https://chatty.personaliai.com/widget.js"
data-id="YOUR_BOT_ID"
strategy="afterInteractive"
/>
</body>
</html>
);
}Always use the attribute data-id (not data-bot-id). The widget loader specifically queries for data-id to initialize your bot.
Plain React (Vite / CRA / Remix)
Paste the script tag into your index.html right before </body>:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>My App</title>
</head>
<body>
<div id="root"></div>
<!-- Chatty Widget -->
<script
src="https://chatty.personaliai.com/widget.js"
data-id="YOUR_BOT_ID"
defer
></script>
</body>
</html>Programmatic Control with useChatty() Hook
Whether you install @personaliai/react-widget or embed the script directly, you can control the chat panel programmatically via the useChatty() hook:
"use client";
import { useChatty } from "@personaliai/react-widget";
export function ContactButton() {
const { open, close, toggle } = useChatty();
return (
<button
onClick={open}
className="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 text-white rounded-lg font-medium shadow-sm transition-colors"
>
💬 Chat with Support
</button>
);
}If you're using the direct script tag without the npm package, you can define useChatty yourself:
"use client";
export function useChatty() {
const open = () => {
if (typeof window !== "undefined" && (window as any).Chatty) {
(window as any).Chatty.open();
}
};
const close = () => {
if (typeof window !== "undefined" && (window as any).Chatty) {
(window as any).Chatty.close();
}
};
const toggle = () => {
if (typeof window !== "undefined" && (window as any).Chatty) {
(window as any).Chatty.toggle();
}
};
return { open, close, toggle };
}Why the Script Method?
| Advantage | Benefit |
|---|---|
| Zero CSS Conflicts | Mounts inside an isolated Shadow DOM root, completely preventing host styles from bleeding in or widget styles from leaking out. |
| Ultra-Lightweight | Bundle size in your application is < 2 kB (or 0 kB with direct script tag). |
| Instant Server Sync | When you edit your bot's colors, welcome text, or system prompt in the dashboard, changes show up immediately for your users without needing a code redeployment. |
| 100% Crisp Vector Sharpness | Uses native SVG and DOM elements rather than an iframe bitmap. |