Framework recipes
Copy-paste integration recipes for React, Next.js (App Router), and Vue 3.
React
Include the Quickstart <script> snippet once in your app shell,
then use a small hook to identify the user on login and shut down on logout.
Calls made before the widget finishes loading are queued and replayed, so you
don't need to wait for it to be ready.
import { useEffect } from "react";
export function useSupportChat(user) {
useEffect(() => {
if (user) {
SupportChat("identify", {
user,
tokenProvider: () =>
fetch("/api/support-chat-token").then((r) => r.text()),
});
} else {
SupportChat("shutdown", { clearStorage: true });
}
}, [user?.id]);
}Next.js (App Router)
Load the widget with next/script and render it once in your root layout:
"use client";
import Script from "next/script";
export default function SupportChatLoader() {
return (
<Script id="support-chat" strategy="afterInteractive">
{`
window.SupportChatSettings = { workspaceId: "{YOUR_WORKSPACE_ID}", widgetId: "{YOUR_WIDGET_ID}" };
(function (w, d) {
w.SupportChat = w.SupportChat || function () {
(w.SupportChat.q = w.SupportChat.q || []).push(arguments);
};
var s = d.createElement("script");
s.async = true;
s.src = "https://clad-server-staging.up.railway.app/widget/v1/widget.js";
d.head.appendChild(s);
})(window, document);
`}
</Script>
);
}Vue 3
With the Quickstart <script> snippet included once in your
index.html, drive the widget from your components:
import { onMounted } from "vue";
export function useSupportChat(user) {
onMounted(() => {
if (user) {
SupportChat("identify", {
user,
tokenProvider: () =>
fetch("/api/support-chat-token").then((r) => r.text()),
});
}
});
}