Aelio
PlatformsReact

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                  memory

Install widget

npm install @aelio/chat

Vite + 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:3010

Fetch 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:3010

Script 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:

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 default

Widget 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.

On this page