Skip to main content
Build a minimal voice-agent loop in Next.js: the browser captures speech, a server route decides what to say, and Rime speaks the reply. This starter uses browser speech recognition and a stub response function; replace both with production components. Keep RIME_API_KEY on the server. Call Rime over HTTPS with fetch; no Rime-specific npm package is required. The optional WebSocket bridge adds the only new dependency, ws. Architecture: the browser never talks to Rime directly. Your API key stays server-side, and the browser calls your own /api/tts route:

Prerequisites

  • A Rime API key from the API Tokens page. Put it in .env.local as RIME_API_KEY=...
  • A Next.js 14+ project using the App Router (npx create-next-app@latest defaults work)

1. Server: the TTS proxy route

Create app/api/tts/route.ts (or src/app/api/tts/route.ts if your project uses src/):
app/api/tts/route.ts
Verify it works before touching the frontend:
test.mp3 should be playable audio. If you get a 401, check that RIME_API_KEY is set in .env.local and the dev server was restarted after adding it.

2. Client: mic in, Rime audio out

Create app/voice-agent/page.tsx. It uses the browser’s built-in SpeechRecognition for input (Chrome/Edge/Safari), a stub respond() function as the agent brain, and your /api/tts route for the voice:
app/voice-agent/page.tsx
Open http://localhost:3000/voice-agent, select Speak, say something, and the agent answers in Rime’s astra voice.

3. Stream over WebSockets when latency matters

Legacy Coda /ws3. Use this section only for an existing /ws3 integration. For new clients, use the Coda v1 JSON quickstart. Its message format differs and it has no word timestamps.
This legacy bridge relays /ws3 events between your server and browser. It supports incremental synthesis and /ws3 word timestamps for interruption handling. Two things make the WebSocket setup different:
  1. Rime’s WebSocket endpoints authenticate with an Authorization header, which browser WebSockets cannot send. The bridge must live on your server, where it also keeps the API key off the client.
  2. Next.js route handlers can’t hold WebSocket connections, so you need a small custom server.
Install ws, then create server.mjs in the project root:
server.mjs
Point your dev/start scripts at it:
package.json
On the client, connect to your bridge and play chunks as they arrive:
This legacy bridge uses /ws3 events such as chunk, timestamps, done, and error, plus the flush, clear, and eos operations. See the legacy segmentation guide for buffering and completion behavior.

Production building blocks

Choose a WebSocket API

Compare Coda v1 and Mist endpoints, message formats, and synthesis controls.

Voices

Swap astra for any Coda voice. Coda covers nine languages, and each voice serves one of them.

Streaming formats

Choose between Opus, MP3, WAV, PCM, and μ-law for your latency budget.

LiveKit & Pipecat

Use the ready-made Rime plugins when a framework should own transport and orchestration.