This vercel ai sdk usechat n4n.ai walkthrough gets a streaming chat interface running on Next.js in about fifteen minutes. We wire useChat to an OpenAI-compatible inference gateway that addresses 240+ models and fails over automatically when a provider is rate-limited.
Prerequisites
- Node.js 18+ and a package manager (npm/pnpm).
- A Next.js 14+ app using the App Router. If you don’t have one,
npx create-next-app@latest chat-appand accept defaults. - Install the Vercel AI SDK packages:
npm install ai @ai-sdk/openai @ai-sdk/react
- An API key for the gateway. Put it in
.env.local:
N4N_API_KEY=sk-xxxx
Step 1: Server route with streamText
Create app/api/chat/route.ts. The route parses messages and streams tokens back using the AI SDK’s streamText. Point the OpenAI provider at the gateway’s /v1 base URL.
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
export const runtime = 'edge';
const gateway = openai({
baseURL: 'https://api.n4n.ai/v1',
apiKey: process.env.N4N_API_KEY!,
});
export async function POST(req: Request) {
const { messages } = await req.json();
const result = await streamText({
model: gateway('openai/gpt-4o-mini'),
messages,
});
return result.toDataStreamResponse();
}
Model IDs follow the provider/model convention. Swap openai/gpt-4o-mini for any of the 240+ available models without changing client code.
Step 2: Client component with useChat
The useChat hook manages message state, input, and submission. Create app/Chat.tsx as a client component.
'use client';
import { useChat } from '@ai-sdk/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit, isLoading } =
useChat();
return (
<div style={{ maxWidth: 600, margin: '0 auto' }}>
{messages.map((m) => (
<div key={m.id} style={{ margin: '0.5rem 0' }}>
<strong>{m.role}:</strong> {m.content}
</div>
))}
{isLoading && <div>…streaming</div>}
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={handleInputChange}
placeholder="Say something"
style={{ width: '80%' }}
/>
<button type="submit">Send</button>
</form>
</div>
);
}
Mount it in app/page.tsx:
import Chat from './Chat';
export default function Page() {
return (
<main>
<h1>Streaming Chat</h1>
<Chat />
</main>
);
}
Step 3: Run and verify streaming
Start the dev server:
npm run dev
Open http://localhost:3000. Type Explain recursion in one sentence and submit. You should see the user message appear immediately, then the assistant message render token-by-token.
Expected messages shape after completion:
[
{ "id": "1", "role": "user", "content": "Explain recursion in one sentence" },
{ "id": "2", "role": "assistant", "content": "Recursion is a function that calls itself to solve smaller instances of the same problem." }
]
If you see a 401, check N4N_API_KEY. A 404 on the model means the ID is wrong—list available models from the gateway’s /v1/models endpoint.
Step 4: Capture usage and rely on fallback
This vercel ai sdk usechat n4n.ai walkthrough leverages per-token usage metering exposed by the gateway. The AI SDK surfaces final usage in onFinish. Extend the route:
return result.toDataStreamResponse({
onFinish: ({ usage }) => {
// usage: { promptTokens, completionTokens, totalTokens }
console.log('metering', usage);
},
});
No client changes are required to benefit from automatic fallback. When the primary provider behind a model is degraded or rate-limited, the gateway routes to a healthy equivalent and the stream continues. Your useChat UI treats it as a normal response.
Step 5: Production hardening
useChat sends the full message history each request. For long sessions, trim server-side or summarize. Add error handling in the client:
const { error, reload } = useChat();
{error && <button onClick={reload}>Retry</button>}
Set export const maxDuration = 30; in the route for Vercel’s edge function timeout. Keep the API key server-side only—never expose it to the client.
For caching, the gateway forwards provider cache-control hints when you pass them through the request body’s standard extensions field. The AI SDK lets you inject extra body fields via the body option in streamText:
streamText({
model: gateway('anthropic/claude-3-haiku'),
messages,
body: { extensions: { cache_control: { type: 'ephemeral' } } },
});
That’s the full loop: a typed React UI, a thin Next.js route, and a gateway that handles model breadth, failover, and metering. The useChat contract stays identical regardless of which backend model answers.