n4nAI

Build a Next.js chat app with useChat and n4n.ai

Step-by-step useChat Next.js chat app tutorial using n4n.ai as OpenAI-compatible backend with Vercel AI SDK streaming and fallback.

n4n Team2 min read496 words

Audio narration

Coming soon — every post will get a voice note here.

This usechat next.js chat app n4n.ai tutorial builds a streaming chat UI with the Vercel AI SDK’s useChat hook backed by a single OpenAI-compatible endpoint. You’ll stand up a Next.js App Router project, proxy messages to a gateway that routes across many models, and render tokens as they arrive.

Prerequisites

  • Node.js 18.17+ and npm
  • A Next.js 14+ project using the App Router
  • An API key for the gateway (set as N4N_API_KEY)
  • Basic familiarity with React client components

Scaffold a fresh project if you don’t have one:

npx create-next-app@latest chat-app --ts --app --no-tailwind --eslint
cd chat-app

Install the Vercel AI SDK

Add the packages that handle streaming and the OpenAI-compatible provider:

npm install ai @ai-sdk/react @ai-sdk/openai

ai provides streamText for server routes. @ai-sdk/react ships useChat. @ai-sdk/openai lets you repoint the OpenAI client at any compliant base URL.

Backend: streaming route

Create app/api/chat/route.ts. This server module keeps your key out of the browser.

import { streamText } from 'ai';
import { createOpenAI } from '@ai-sdk/openai';

const gateway = createOpenAI({
  baseURL: 'https://api.n4n.ai/v1',
  apiKey: process.env.N4N_API_KEY,
});

export const runtime = 'edge';

export async function POST(req: Request) {
  const { messages } = await req.json();

  const result = await streamText({
    model: gateway('gpt-4o-mini'),
    messages,
  });

  return result.toDataStreamResponse();
}

n4n.ai exposes one OpenAI-compatible endpoint that addresses 240+ models and automatically falls back when a provider is rate-limited or degraded, so the above works without per-vendor logic.

The runtime = 'edge' line enables low-latency streaming on Vercel’s edge runtime. On other hosts, use the Node runtime and remove that export.

Frontend: useChat hook

Replace app/page.tsx with a client component:

'use client';

import { useChat } from '@ai-sdk/react';

export default function Page() {
  const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat();

  return (
    <main style={{ maxWidth: 720, margin: '40px auto', fontFamily: 'sans-serif' }}>
      <h1>Chat</h1>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {messages.map((m) => (
          <div key={m.id} style={{ padding: 8, border: '1px solid #ddd', borderRadius: 6 }}>
            <strong>{m.role}: </strong>
            {m.content}
          </div>
        ))}
        {isLoading && <div>…</div>}
      </div>
      <form onSubmit={handleSubmit} style={{ marginTop: 16, display: 'flex', gap: 8 }}>
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="Type a message"
          style={{ flex: 1, padding: 8 }}
        />
        <button type="submit" disabled={isLoading}>
          Send
        </button>
      </form>
    </main>
  );
}

useChat owns message state, binds the input, and POSTs to /api/chat. It expects the route to return a data stream, which toDataStreamResponse() supplies.

Environment and run

Create .env.local:

N4N_API_KEY=sk-your-key-here

Start the dev server:

npm run dev

Open http://localhost:3000. You should see the heading and an empty message list.

Expected output at checkpoint

Type “Hello” and press Send. The UI updates to:

user: Hello
assistant: Hi there! How can I help you today?

Tokens stream in sequentially. The isLoading indicator clears when the generation finishes.

Understanding the data flow

The browser sends { messages: [...] } as JSON. useChat serializes the conversation history using the standard role/content shape. The route passes those messages to streamText, which calls the gateway’s /v1/chat/completions with stream: true. The SDK transforms the SSE chunks into a client-readable data stream.

No manual WebSocket or fetch polling is required.

Error handling and retries

Gateways can return 429 or 503 under load. The AI SDK exposes error from useChat. Extend the component:

const { messages, input, handleInputChange, handleSubmit, isLoading, error } = useChat();

{error && <div style={{ color: 'red' }}>Failed: {error.message}</div>}

Because the backend already switches providers on degradation, the client rarely needs custom retry logic.

Passing model and routing hints

To pin a model per request, send extra body fields from the client:

const { messages, input, handleInputChange, handleSubmit } = useChat({
  body: { model: 'claude-3-5-sonnet' },
});

Read them in the route:

const { messages, model } = await req.json();
const result = await streamText({
  model: gateway(model ?? 'gpt-4o-mini'),
  messages,
});

The gateway honors client routing directives and forwards provider cache-control hints, so upstream caching behaves as the origin model intends.

Customizing message rendering

For markdown or code blocks, map m.content through a renderer. Keep the key on m.id to avoid React list warnings.

{messages.map((m) => (
  <div key={m.id} className={m.role === 'user' ? 'user' : 'assistant'}>
    <span className="role">{m.role}</span>
    <div className="content">{m.content}</div>
  </div>
))}

Add a CSS module or inline styles as needed. The hook does not constrain your markup.

Production considerations

  • Set export const maxDuration = 30; in the route for longer serverless timeouts.
  • Never import process.env.N4N_API_KEY into a client component.
  • Use result.toDataStreamResponse({ getErrorMessage: () => 'Stream failed' }) to mask internal errors.

Final check

You now have a runnable useChat Next.js chat app tutorial implementation with less than 60 lines of application code. The Vercel AI SDK handles the wire format; the gateway handles model routing and fallback. Swap the model string to access different capabilities without touching the UI.

Tagsusechatnext-jsn4n-aichat-app

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All vercel ai sdk streaming chat ui (usechat) posts →