Quickstart: React SDK
Build your first AI-powered React component in 5 minutes.
Step 1 — Install the React SDK
pnpm add @arlopass/react
Step 2 — Wrap your app in ArlopassProvider
The provider connects to the browser extension and manages the AI client lifecycle.
import { ArlopassProvider } from "@arlopass/react";
function App() {
return (
<ArlopassProvider appId="my-app">
<YourApp />
</ArlopassProvider>
);
}
Step 3 — Add ChatReadyGate
The gate handles loading, missing-provider, and error states so your chat component only renders when everything is ready.
import { ChatReadyGate } from "@arlopass/react";
function YourApp() {
return (
<ChatReadyGate
connecting={<p>Connecting to extension...</p>}
noProvider={<p>Please select a provider in the extension.</p>}
error={(err) => <p>Error: {err.message}</p>}
>
<Chat />
</ChatReadyGate>
);
}
Step 4 — Use the useConversation hook
The hook gives you the message list, a streaming send function, and status flags. No manual state management needed.
import { useConversation } from "@arlopass/react";
function Chat() {
const { messages, stream, isStreaming } = useConversation();
async function handleSend(text: string) {
await stream({
messages: [...messages, { role: "user", content: text }],
});
}
return /* your UI */;
}
Step 5 — Build the UI
Wire up an input and a message list. The hook handles the rest.
import { useState } from "react";
import { useConversation } from "@arlopass/react";
function Chat() {
const { messages, stream, isStreaming } = useConversation();
const [input, setInput] = useState("");
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
if (!input.trim() || isStreaming) return;
const text = input;
setInput("");
await stream({
messages: [...messages, { role: "user", content: text }],
});
}
return (
<div>
<div>
{messages.map((msg, i) => (
<div key={i}>
<strong>{msg.role}:</strong> {msg.content}
</div>
))}
</div>
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Type a message..."
disabled={isStreaming}
/>
<button type="submit" disabled={isStreaming}>
Send
</button>
</form>
</div>
);
}
Complete example
Here’s a full working chat component you can drop into any React app:
import { useState } from "react";
import {
ArlopassProvider,
ChatReadyGate,
useConversation,
} from "@arlopass/react";
function Chat() {
const { messages, stream, isStreaming } = useConversation();
const [input, setInput] = useState("");
return (
<div>
<div>
{messages.map((msg, i) => (
<div key={i}>
<strong>{msg.role}:</strong> {msg.content}
</div>
))}
</div>
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Type a message..."
disabled={isStreaming}
/>
<button type="submit" disabled={isStreaming}>
Send
</button>
</form>
</div>
);
}
export default function App() {
return (
<ArlopassProvider appId="my-app">
<ChatReadyGate
connecting={<p>Connecting...</p>}
noProvider={<p>Select a provider in the Arlopass extension.</p>}
error={(err) => <p>Error: {err.message}</p>}
>
<Chat />
</ChatReadyGate>
</ArlopassProvider>
);
}
React SDK vs Web SDK
The React SDK wraps the same Web SDK calls in hooks and components. Here’s the same “send a message” feature in both:
React SDK
import { useConversation } from "@arlopass/react";
function Chat() {
const { messages, stream, isStreaming } = useConversation();
async function send(text: string) {
await stream({
messages: [...messages, { role: "user", content: text }],
});
}
}
Web SDK
import { ArlopassClient } from "@arlopass/web-sdk";
const client = new ArlopassClient({ transport: window.arlopass });
await client.connect({ appId: "my-app" });
const providers = await client.listProviders();
await client.selectProvider(providers[0].id);
const response = await client.chat.send({
messages: [{ role: "user", content: "Hello!" }],
});