Quickstart

Quickstart

Two paths. Pick the one that fits your situation.

Path A — RAIS CloudPath B — Self-hosted
Own AI provider accounts?Not neededRequired (Groq, OpenAI, or Anthropic)
Setup time~2 min after key arrives~5 min
Best forGetting started fastFull control, no third-party dependency

Path A — RAIS Cloud (recommended for most people)

You need a RAIS API key. Without it, the gateway returns 401 and nothing works.

Get your key

  1. Go to react-ai-stream-playground.vercel.app/cloud (opens in a new tab)
  2. Enter your email in the waitlist form
  3. Wait for the approval email — it contains your ras_test_... key
💡

Keys look like ras_test_a1b2c3d4e5f6... (free) or ras_live_... (paid). Keep it secret — it authorizes all your requests.

Install packages

npm install @react-ai-stream/react @react-ai-stream/ui

Add a proxy API route (keeps your key off the browser)

app/api/chat/route.ts
export const runtime = 'nodejs'
 
export async function POST(req: Request) {
  const body = await req.json()
 
  const upstream = await fetch(
    'https://react-ai-stream-gateway.vercel.app/api/v1/chat',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${process.env.RAIS_API_KEY}`,
      },
      body: JSON.stringify(body),
    }
  )
 
  return new Response(upstream.body, {
    headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' },
  })
}

Add to .env.local:

RAIS_API_KEY=ras_test_your_key_here

Add the chat UI

app/page.tsx
'use client'
import { useAIChat } from '@react-ai-stream/react'
import { Chat } from '@react-ai-stream/ui'
import '@react-ai-stream/ui/styles'
 
export default function Page() {
  const { messages, sendMessage, loading, stop } = useAIChat({
    endpoint: '/api/chat',
  })
 
  return (
    <div style={{ height: '80vh' }}>
      <Chat messages={messages} onSend={sendMessage} onStop={stop} loading={loading} />
    </div>
  )
}

Run it

npm run dev

Open http://localhost:3000. You have streaming AI chat — Groq by default, with automatic fallback to OpenAI and Anthropic.

No provider account. No API key juggling. RAIS Cloud handles Groq, OpenAI, Anthropic, and Gemini on its side. Your ras_test_... key is the only credential your app needs. See full RAIS Cloud docs →


Path B — Self-hosted (you manage your own provider keys)

Use this when you want zero external dependencies beyond the AI provider itself.

Install packages

npm install @react-ai-stream/react @react-ai-stream/ui

Get a provider API key

This example uses Groq (opens in a new tab) — free tier, instant sign-up. Add to .env.local:

GROQ_API_KEY=gsk_your_key_here

Create a streaming API route

app/api/chat/route.ts
import { NextRequest } from 'next/server'
 
export const runtime = 'edge'
 
export async function POST(req: NextRequest) {
  const { messages } = await req.json()
 
  const upstream = await fetch('https://api.groq.com/openai/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.GROQ_API_KEY}`,
    },
    body: JSON.stringify({
      model: 'llama-3.3-70b-versatile',
      messages,
      stream: true,
    }),
  })
 
  const stream = new ReadableStream({
    async start(controller) {
      const enc = new TextEncoder()
      const send = (data: object) =>
        controller.enqueue(enc.encode(`data: ${JSON.stringify(data)}\n\n`))
 
      const reader = upstream.body!.getReader()
      const decoder = new TextDecoder()
      let buf = ''
 
      while (true) {
        const { done, value } = await reader.read()
        if (done) break
        buf += decoder.decode(value, { stream: true })
        const parts = buf.split('\n\n')
        buf = parts.pop() ?? ''
        for (const part of parts) {
          for (const line of part.split('\n')) {
            if (!line.startsWith('data: ')) continue
            const data = line.slice(6).trim()
            if (data === '[DONE]') { send({ type: 'done' }); controller.close(); return }
            try {
              const ev = JSON.parse(data)
              const text = ev.choices?.[0]?.delta?.content
              if (text) send({ type: 'text', text })
            } catch { /* skip */ }
          }
        }
      }
      send({ type: 'done' })
      controller.close()
    },
  })
 
  return new Response(stream, {
    headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' },
  })
}

Use the hook in your component

app/page.tsx
'use client'
import { useAIChat } from '@react-ai-stream/react'
import { Chat } from '@react-ai-stream/ui'
import '@react-ai-stream/ui/styles'
 
export default function Page() {
  const { messages, sendMessage, loading, stop } = useAIChat({
    endpoint: '/api/chat',
  })
 
  return (
    <div style={{ height: '80vh' }}>
      <Chat
        messages={messages}
        onSend={sendMessage}
        onStop={stop}
        loading={loading}
      />
    </div>
  )
}

Done

You have a streaming AI chat backed by your own Groq account.


Bring your own UI

Both paths work without @react-ai-stream/ui. The hook has no UI dependency:

'use client'
import { useState } from 'react'
import { useAIChat } from '@react-ai-stream/react'
 
export default function Page() {
  const { messages, sendMessage, loading, stop } = useAIChat({
    endpoint: '/api/chat',
  })
  const [input, setInput] = useState('')
 
  return (
    <div>
      <div>
        {messages.map((m) => (
          <p key={m.id}><b>{m.role}:</b> {m.content}</p>
        ))}
      </div>
      <form onSubmit={(e) => { e.preventDefault(); sendMessage(input); setInput('') }}>
        <input value={input} onChange={(e) => setInput(e.target.value)} disabled={loading} />
        {loading
          ? <button type="button" onClick={stop}>Stop</button>
          : <button type="submit">Send</button>}
      </form>
    </div>
  )
}

Next steps