React
Integrate @aelio/chat widget in React apps — Vite, Create React App, and SPA patterns.
React apps use @aelio/chat for the frontend widget. The SDK (@aelio/sdk) runs on your separate backend — React SPAs don't run the SDK in the browser.
Architecture
React SPA (browser) Your Backend (Node/Python) Aelio Server
@aelio/chat widget → @aelio/sdk → runtime
mountAelioChat() aelio.expose() LLM + safety
WebSocket /widget/ws WebSocket /sdk memoryInstall widget
npm install @aelio/chatVite + React
Chat widget component
// src/components/AelioChat.tsx
import { useEffect, useRef } from 'react';
import { mountAelioChat, unmountAelioChat } from '@aelio/chat';
interface Props {
userId: string;
email: string;
authToken?: string;
}
export function AelioChat({ userId, email, authToken }: Props) {
const handleRef = useRef<ReturnType<typeof mountAelioChat>>(null);
useEffect(() => {
handleRef.current = mountAelioChat({
serverUrl: import.meta.env.VITE_AELIO_SERVER_URL,
customerId: userId,
authToken,
email,
title: 'Chat with us',
launcherLabel: 'Help',
});
return () => {
if (handleRef.current) unmountAelioChat(handleRef.current);
};
}, [userId, email, authToken]);
return null;
}Add to App
// src/App.tsx
import { AelioChat } from './components/AelioChat';
import { useAuth } from './hooks/useAuth';
function App() {
const { user } = useAuth();
return (
<div>
{/* Your app content */}
{user && <AelioChat userId={user.id} email={user.email} authToken={user.chatToken} />}
</div>
);
}Environment variables
# .env
VITE_AELIO_SERVER_URL=http://localhost:3010Fetch auth token from backend
Your React app should request a session token from your backend API:
// src/hooks/useChatToken.ts
import { useEffect, useState } from 'react';
export function useChatToken() {
const [token, setToken] = useState<string>();
useEffect(() => {
fetch('/api/chat-token', {
method: 'POST',
credentials: 'include',
})
.then(r => r.json())
.then(data => setToken(data.sessionToken));
}, []);
return token;
}Your backend issues the token using the magic link flow (see Widget Authentication).
Create React App
Same pattern as Vite, but use process.env.REACT_APP_AELIO_SERVER_URL:
mountAelioChat({
serverUrl: process.env.REACT_APP_AELIO_SERVER_URL!,
customerId: user.id,
email: user.email,
});# .env
REACT_APP_AELIO_SERVER_URL=http://localhost:3010Script tag alternative (no bundling)
If you prefer not to bundle @aelio/chat:
// src/components/AelioChatScript.tsx
import { useEffect } from 'react';
export function AelioChatScript({ userId, email }: { userId: string; email: string }) {
useEffect(() => {
const script = document.createElement('script');
script.src = `${import.meta.env.VITE_AELIO_SERVER_URL}/widget.js`;
script.dataset.serverUrl = import.meta.env.VITE_AELIO_SERVER_URL;
script.dataset.customerId = userId;
script.dataset.email = email;
document.body.appendChild(script);
return () => {
document.getElementById('aelio-widget-root')?.remove();
script.remove();
};
}, [userId, email]);
return null;
}Backend setup
Your React app's backend needs the SDK. See:
- Node.js + Express — if using Express API
- Vanilla Node.js — if using node:http
The SDK cannot run in the browser. It must run on your server.
CORS and origin
If your React dev server runs on a different port than Aelio server, add the origin:
# Aelio server config.yaml
channels:
web:
allowed_origins:
- "http://localhost:5173" # Vite default
- "http://localhost:3000" # CRA defaultWidget options reference
mountAelioChat({
serverUrl: string; // Required — Aelio server HTTP URL
customerId: string; // Required — your user ID
authToken?: string; // Session token (production)
email?: string; // Customer email
title?: string; // Panel header
launcherLabel?: string; // Button label
initialMessage?: string; // Empty-state hint
});Confirmation UI
Write-safety tools (checkout, cancel, etc.) automatically show Confirm/Cancel buttons in the widget. No extra React code needed.