@agentiachat/react
v0.5.1
Published
Embeddable Agentia chat widget for React — streaming AI chat with theming, floating launcher, and admin-driven settings
Downloads
82
Maintainers
Readme
@agentiachat/react
Embeddable Agentia chat widget for React — streaming AI chat with a floating launcher, full theming, and admin-driven settings. See the docs for guides and the full API reference.
- Zero runtime dependencies — only
react/react-domas peers (18 or 19) - Streaming responses via Server-Sent Events
- Style-isolated — renders in a shadow root, so host-page CSS can't break it (and its styles can't leak out); no CSS import needed
- SSR-safe — works in Next.js (Pages and App Router) without
next/dynamic - Themeable — CSS custom properties (they pierce the shadow boundary) and
::part()hooks, plus dark mode and admin-configured appearance - Headless option — use the
useChathook with your own UI - ESM + CJS builds with full TypeScript types
Install
npm i @agentiachat/react
# peer deps: react@^18||^19, react-dom@^18||^19Quick start
import { ChatProvider, FloatingChat } from '@agentiachat/react';
// No CSS import needed — styles are injected into the widget's shadow root.
export function App() {
return (
<>
{/* your app */}
<ChatProvider chatId="YOUR_PUBLIC_CHAT_ID">
<FloatingChat />
</ChatProvider>
</>
);
}Note:
apiUrldefaults to the hosted Agentia API (https://api.agentia.chat/api), so embedding a chat hosted on Agentia needs onlychatId. Self-hosters passapiUrlpointing at their own deployment — it must include the API's global prefix (/apiby default), since the widget calls{apiUrl}/public/...endpoints.
Use Chat instead of FloatingChat to render the conversation inline:
<ChatProvider chatId="YOUR_PUBLIC_CHAT_ID">
<Chat title="Support" />
</ChatProvider>Components
ChatProvider
Wraps any chat UI and manages conversations, streaming, and visitor identity.
| Prop | Type | Default | Description |
| ----------- | -------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| chatId | string | — (required) | Public chat ID from your Agentia admin |
| apiUrl | string | https://api.agentia.chat/api | Agentia API base URL including the global prefix. Defaults to the hosted API; set it only when self-hosting. |
| visitorId | string | auto-generated | Stable visitor ID (persisted in localStorage if omitted) |
Chat
Full conversation UI (messages, composer, streaming indicator).
| Prop | Type | Default | Description |
| --------------- | ------------------------ | ------------- | --------------------------------------------------- |
| title | string | admin setting | Header title override |
| subtitle | string | admin setting | Header subtitle override |
| placeholder | string | admin setting | Composer placeholder (supports {variable} tokens) |
| variables | Record<string, string> | {} | Values for {variable} tokens in UI copy |
| showPoweredBy | boolean | true | "Powered by Agentia" footer |
| className | string | — | Extra class on the root element |
FloatingChat
Chat wrapped in a floating launcher button (popover / drawer / fullscreen —
driven by the chat's admin widget settings, including corner position).
Accepts all Chat props plus:
| Prop | Type | Default | Description |
| ------------- | --------- | ------- | ------------------------- |
| defaultOpen | boolean | false | Start with the panel open |
Headless usage
import { ChatProvider, useChat } from '@agentiachat/react';
function MyChatUi() {
const { messages, sendMessage, isThinking, isStreaming, streamingContent } = useChat();
// render your own UI
}
<ChatProvider chatId="..." apiUrl="...">
<MyChatUi />
</ChatProvider>;A/B experiments
When an experiment is running on a chat, the widget sends its visitorId with
the bootstrap request and renders the visitor's assigned variant. The
assignment is exposed as meta on the context
({ versionId, experimentId, variantId, variantKey }) for your own analytics.
Versions of this package older than 0.5.0 don't send a visitorId at
bootstrap: visitors still bucket into variant flows when they chat, but they
all see the control styling. Upgrade before running experiments that change
appearance or copy; flow/persona/provider experiments work on any version.
Theming & style isolation
The widget renders inside a shadow root, so the embedding page's CSS (resets, Tailwind preflight, component frameworks) can't reach in and break it, and the widget's own styles can't leak out. No CSS import is required — the stylesheet is injected automatically.
Theme it with CSS custom properties, which inherit across the shadow boundary.
Set them on the widget's host element, .agentia-chat-host:
.agentia-chat-host {
--agentia-primary: #6d28d9;
--agentia-primary-hover: #5b21b6;
--agentia-radius: 12px;
--agentia-font-family: 'Inter', sans-serif;
}Available tokens: --agentia-primary, --agentia-primary-hover,
--agentia-primary-text, --agentia-bg, --agentia-surface,
--agentia-text, --agentia-text-muted, --agentia-border,
--agentia-header-bg, --agentia-header-text, --agentia-input-bg,
--agentia-input-border, --agentia-user-bubble-bg,
--agentia-user-bubble-text, --agentia-assistant-bubble-bg,
--agentia-assistant-bubble-text, --agentia-launcher-bg,
--agentia-launcher-text, --agentia-launcher-shadow,
--agentia-launcher-ring, --agentia-font-family, --agentia-font-size,
--agentia-radius, --agentia-radius-sm, --agentia-shadow.
For deeper, structural overrides, target the exposed ::part() hooks from the
host page:
.agentia-chat-host::part(launcher) {
border-radius: 12px;
}
.agentia-chat-host::part(header) {
background: #111827;
}
.agentia-chat-host::part(bubble-user) {
background: #6d28d9;
}Exposed parts: launcher, panel, close, header, avatar, title,
subtitle, messages, message, message-user, message-assistant,
bubble, bubble-user, bubble-assistant, timestamp, composer, input,
send-button, welcome, greeting, prompt, powered.
Dark mode and full appearance can also be configured in the Agentia admin (settings are fetched at runtime).
Server-side rendering
The package guards all browser APIs (window, localStorage, EventSource).
The widget mounts into its shadow root on the client after hydration, so it
renders nothing on the server — safe for SSR / Next.js without next/dynamic
(and the chat isn't indexed as page content).
Embedding origins
No CORS setup is required to embed against the hosted Agentia API — it accepts
the widget's requests from any origin out of the box. Visitors are identified by
a visitorId (persisted in localStorage), not cookies, so there's nothing to
configure on the embedding site.
To restrict which sites may embed a chat, set an allowed origins list in the chat's security settings (Agentia admin). When the list is empty (the default), any origin is allowed; when it's non-empty, only the listed origins can load the widget and others are blocked by the browser. This is a browser-level embedding control (and cost hygiene), not a hard security boundary — request volume is bounded by per-chat rate limits.
Self-hosting: the public chat API applies this per-workspace allowlist automatically. The server-wide
ALLOWED_ORIGINSenv var only governs the admin API, not the embeddable/public/*widget endpoints.
License
MIT
