Quick Start
An easy to follow guide to setup the SDK and incorporate Orga AI into your React web app
Installation
Install the SDK from npm
npm install @orga-ai/react
Setup Backend Proxy
You need a secure backend proxy to protect your API key. The location of your environment variables depends on your chosen approach:
Add API key and User Email to .env
ORGA_API_KEY=sk_orga_ai_******
USER_EMAIL=your_email_here
Get your API key from the OrgaAI dashboard: https://platform.orga-ai.com/login
// app/api/orga-client-secrets/route.ts
import { NextResponse } from "next/server";
const ORGA_API_KEY = process.env.ORGA_API_KEY;
const fetchIceServers = async (ephemeralToken: string) => {
const URL = `https://api.orga-ai.com/v1/realtime/ice-config`;
try {
const iceServersResponse = await fetch(URL, {
method: "GET",
headers: {
Authorization: `Bearer ${ephemeralToken}`,
},
});
if (!iceServersResponse.ok) {
return NextResponse.json({ error: "Failed to fetch ICE servers" }, { status: 500 });
}
const data = await iceServersResponse.json();
return data.iceServers;
} catch (error) {
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
}
};
export const GET = async () => {
const USER_EMAIL = process.env.USER_EMAIL;
if (!ORGA_API_KEY) {
return NextResponse.json(
{ error: 'Missing ORGA_API_KEY environment variable' },
{ status: 500 }
);
}
if (!USER_EMAIL) {
return NextResponse.json(
{ error: 'Missing USER_EMAIL environment variable' },
{ status: 500 }
);
}
const apiUrl = `https://api.orga-ai.com/v1/realtime/client-secrets?email=${encodeURIComponent(USER_EMAIL)}`;
const ephemeralResponse = await fetch(apiUrl, {
method: "POST",
headers: {
Authorization: `Bearer ${ORGA_API_KEY}`,
},
});
if (!ephemeralResponse.ok) {
return NextResponse.json(
{ error: 'Failed to fetch ephemeral token' },
{ status: ephemeralResponse.status }
);
}
const data = await ephemeralResponse.json();
const iceServers = await fetchIceServers(data.ephemeral_token);
const returnData = {
iceServers,
ephemeralToken: data.ephemeral_token
}
return NextResponse.json(returnData);
}
Initialize the SDK
You must initialize the SDK before use, providing a fetchSessionConfig function. This function should securely fetch an ephemeral token and ICE servers from your backend using your API key.
Never expose your API key in client code
//app/providers/OrgaClientProvider.tsx (Client Component)
'use client'
import { OrgaAI, OrgaAIProvider } from '@orga-ai/react';
OrgaAI.init({
logLevel: 'debug',
fetchSessionConfig: async () => {
const response = await fetch('/api/orga-client-secrets');
const { ephemeralToken, iceServers } = await response.json();
return { ephemeralToken, iceServers };
},
// OR use sessionConfigEndpoint which points directly to your backend.
// Useful if you don't need any custom implementation.
// sessionConfigEndpoint: 'https://<url>/api/orga-client-secrets',
model: 'orga-1-beta',
voice: 'alloy',
});
export function OrgaClientProvider({ children }: { children: React.ReactNode }) {
return <OrgaAIProvider>{children}</OrgaAIProvider>;
}
Layout Provider
// app/layout.tsx
import { OrgaClientProvider } from './providers/OrgaClientProvider';
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>
<OrgaClientProvider>
{children}
</OrgaClientProvider>
</body>
</html>
);
}
Main Screen
// app/page.tsx (Client Component)
'use client'
import { useOrgaAI, OrgaVideo, OrgaAudio } from '@orga-ai/react';
export default function Home() {
const {
startSession,
endSession,
userVideoStream,
aiAudioStream,
connectionState,
isCameraOn,
toggleCamera,
toggleMic,
isMicOn,
} = useOrgaAI();
const handleStart = async () => {
await startSession({
onSessionConnected: () => {
console.log("Connected!");
},
});
};
return (
<div className="min-h-screen bg-gray-50 p-8">
<div className="max-w-2xl mx-auto">
<h1 className="text-3xl font-bold text-center mb-8">
OrgaAI SDK Quick Start
</h1>
<div className="bg-white rounded-lg shadow-md p-6 mb-6">
<h2 className="text-xl font-semibold mb-4">Camera Preview</h2>
<div className="relative bg-gray-900 rounded-lg overflow-hidden">
<OrgaVideo
stream={userVideoStream}
className="w-full h-64 object-cover"
/>
{!userVideoStream && (
<div className="absolute inset-0 flex items-center justify-center text-gray-400">
<p>Camera preview will appear here</p>
</div>
)}
</div>
</div>
<div className="bg-white rounded-lg shadow-md p-6 mb-6">
<h2 className="text-xl font-semibold mb-4">Controls</h2>
<div className="mb-4 p-3 bg-gray-100 rounded-lg">
<span className="font-medium">Status: {connectionState}</span>
</div>
<div className="space-y-3">
<button
onClick={handleStart}
disabled={
connectionState === "connected" ||
connectionState === "connecting"
}
className="w-full bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 text-white py-2 px-4 rounded-lg"
>
{connectionState === "connecting"
? "Connecting..."
: "Start Session"}
</button>
<button
onClick={endSession}
disabled={connectionState !== "connected"}
className="w-full bg-red-600 hover:bg-red-700 text-white py-2 px-4 rounded-lg"
>
End Session
</button>
<div className="grid grid-cols-2 gap-3">
<button
onClick={toggleCamera}
disabled={connectionState !== "connected"}
className={`py-2 px-4 rounded-lg ${
isCameraOn
? "bg-green-600 text-white"
: "bg-gray-200 text-gray-700"
}`}
>
{isCameraOn ? "Camera On" : "Camera Off"}
</button>
<button
onClick={toggleMic}
disabled={connectionState !== "connected"}
className={`py-2 px-4 rounded-lg ${
isMicOn
? "bg-green-600 text-white"
: "bg-gray-200 text-gray-700"
}`}
>
{isMicOn ? "Mic On" : "Mic Off"}
</button>
</div>
</div>
</div>
<OrgaAudio stream={aiAudioStream} />
</div>
</div>
);
}
For Next.js or SSR projects, ensure the provider and hooks are only used in client components.
Troubleshooting
ConfigurationError: OrgaAI must be initialized before use
Ensure that Orga.init is setup and has all of it required properties.
OrgaAI.init({
logLevel: 'debug',
fetchSessionConfig: async () => {
const response = await fetch('/api/orga-client-secrets');
const { ephemeralToken, iceServers } = await response.json();
return { ephemeralToken, iceServers };
}
});
Error: useOrgaAI must be used within an OrgaAIProvider
Wrap your app with the OrgaAIProvider
export default function RootLayout() {
return (
<OrgaAIProvider>
<Stack />
</OrgaAIProvider>
);
}