Package
@releaseo/react
Headless React adapter for Releaseo, with provider state, widget actions, unread count, and SSR-safe snapshots.
Install
npm install @releaseo/sdk @releaseo/react
Provider
The adapter is headless. It initializes @releaseo/sdk, exposes React state and
actions, and keeps the update UI inside the Releaseo iframe.
import { ReleaseoProvider } from "@releaseo/react";
export function App() {
return (
<ReleaseoProvider config={{ publishKey: "pk_live_xxx" }}>
<AppShell />
</ReleaseoProvider>
);
}
For tenant, organization, or project switches, pass a stable resetKey.
<ReleaseoProvider config={releaseoConfig} resetKey={`${tenant.id}:${project.id}`}>
<AppShell />
</ReleaseoProvider>
Use resetOnUnmount only when the provider is intentionally tied to a route or
microfrontend lifecycle and should tear down the SDK after unmount.
Version behavior
The React adapter and @releaseo/sdk facade stay pinned in your package lock.
The facade loads the compatible host runtime from Releaseo’s stable /sdk/v0/
CDN channel, so compatible runtime fixes can arrive without reinstalling the
adapter. Upgrade the npm packages when you need adapter, facade, type, or public
API changes.
Open button and unread count
import { useReleaseo, useReleaseoUnread } from "@releaseo/react";
export function WhatsNewButton() {
const { isReady, open } = useReleaseo();
const unread = useReleaseoUnread();
return (
<button type="button" disabled={!isReady} onClick={() => void open()}>
What's new {unread > 0 ? `(${unread})` : null}
</button>
);
}
Identity sync
Use useReleaseoIdentity() after auth and tenant context are known.
import { useReleaseoIdentity } from "@releaseo/react";
export function ReleaseoIdentitySync({ viewer, workspace }: Props) {
useReleaseoIdentity({
userId: viewer?.id,
enabled: Boolean(viewer && workspace),
identityKey: viewer && workspace ? `${viewer.id}:${workspace.id}` : null,
properties:
viewer && workspace
? { email: viewer.email, name: viewer.name, workspaceId: workspace.id }
: undefined,
logoutOnDisable: true,
});
return null;
}
identityKey controls when the hook calls identify(). Include tenant or
organization ids when those should create a new SDK session.
Hooks
| Hook | Purpose |
|---|---|
useReleaseo() | Full snapshot plus runtime actions. |
useReleaseoStatus() | Derived status such as idle, ready, identified, or error. |
useReleaseoUnread() | Current unread count from the widget. |
useReleaseoSettings() | Resolved SDK/widget settings snapshot. |
useReleaseoError() | Runtime error state. |
useReleaseoIdentity(options) | Safe viewer identity handoff. |
useReleaseoSelector(selector) | Subscribe to a narrow slice of SDK state. |
Next.js App Router
Render the provider from a client component.
"use client";
import { ReleaseoProvider } from "@releaseo/react";
export function ReleaseoClientProvider({ children }: { children: React.ReactNode }) {
return <ReleaseoProvider config={{ publishKey: "pk_live_xxx" }}>{children}</ReleaseoProvider>;
}
The adapter is SSR-safe. Server rendering receives an idle snapshot and runtime work starts from client-side effects.
Client-side navigation works automatically — the underlying SDK detects DOM
swaps and re-attaches its launcher, iframe, and stylesheet. For zero-flicker
persistence, add a <div data-releaseo-host /> sentinel inside app/layout.tsx
so the SDK mounts inside the stable layout DOM. See
Installation → SPA frameworks
for details.
Thanks — your feedback helps us improve the docs.