@zuhile/nextjs
v0.2.0
Published
Next.js component for the Zuhile AI support chat widget (next/script optimised).
Maintainers
Readme
@zuhile/nextjs
Next.js component for the Zuhile AI support chat widget.
Loads via next/script
so it's deferred and never blocks your page.
Install
npm install @zuhile/nextjs
# or: pnpm add @zuhile/nextjs / yarn add @zuhile/nextjsUsage — App Router
Render <ZuhileWidget /> once in your root layout. next/script handles loading;
the launcher appears in the bottom-right corner.
// app/layout.tsx
import { ZuhileWidget } from '@zuhile/nextjs';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<ZuhileWidget publicKey="pk_live_xxx" />
</body>
</html>
);
}
<ZuhileWidget>is a Client Component (it usesnext/script'sonLoad), so it works inside a Server Component layout without adding'use client'yourself.
Usage — Pages Router
// pages/_app.tsx
import { ZuhileWidget } from '@zuhile/nextjs';
export default function App({ Component, pageProps }) {
return (
<>
<Component {...pageProps} />
<ZuhileWidget publicKey="pk_live_xxx" />
</>
);
}Get your public key from the dashboard → Settings → Embed.
Controlling it
'use client';
import { useZuhileWidget } from '@zuhile/nextjs';
export function SupportButton() {
const { open, ready } = useZuhileWidget();
return <button onClick={open} disabled={!ready}>Chat with us</button>;
}Or the imperative helpers: openZuhile(), closeZuhile(), toggleZuhile().
Props
| Prop | Type | Default | Description |
| ------------ | ---------------------------------------------------------- | ------------------------------ | ------------------------------------------------- |
| publicKey | string | — | Required. Your widget public key. |
| apiUrl | string | https://ai-api.usezuhile.com | API gateway base URL (set this for self-hosting). |
| brandColor | string | from dashboard | Optional hex brand colour override. |
| scriptUrl | string | Zuhile CDN | Override the hosted widget bundle URL. |
| strategy | 'afterInteractive' \| 'lazyOnload' \| 'beforeInteractive' | 'afterInteractive' | next/script loading strategy. |
The widget renders inside a closed shadow DOM, so it never clashes with your app's styles, and it's a singleton — safe to keep mounted across navigations.
