n4nAI

Getting started with Vercel AI SDK and n4n.ai

Practical step-by-step tutorial to build a streaming chat app with Vercel AI SDK and n4n.ai's OpenAI-compatible gateway, from scaffold to working UI.

n4n Team3 min read603 words

Audio narration

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

This tutorial walks through vercel ai sdk n4n.ai getting started: standing up a Next.js app that streams chat completions from an OpenAI-compatible gateway. You’ll end with a runnable /api/chat route and a minimal useChat frontend that renders tokens as they arrive.

Prerequisites

  • Node.js 18.18 or later (20+ recommended)
  • A Next.js 14+ project (we scaffold one below)
  • An API key from n4n.ai, set as N4N_API_KEY
  • Basic TypeScript and React familiarity

n4n.ai exposes one OpenAI-compatible endpoint that addresses 240+ models, so we can reuse the standard Vercel AI SDK OpenAI provider without writing a custom adapter.

Scaffold the project

npx create-next-app@latest n4n-chat --ts --app --no-tailwind --no-eslint --no-src-dir --import-alias "@/*"
cd n4n-chat

This creates an App Router project with TypeScript. We’ll overwrite app/page.tsx and add an API route. The default styling is irrelevant; we’ll use inline styles to keep the example dependency-free.

Install the Vercel AI SDK and OpenAI provider

npm install ai@^4 @ai-sdk/openai@^1

ai ships generateText, streamText, and the React hooks. @ai-sdk/openai provides createOpenAI, which accepts a baseURL and apiKey. That’s the only glue needed for the vercel ai sdk n4n.ai getting started flow.

Configure environment variables

Create .env.local at the project root:

N4N_API_KEY=sk-your-key-here
N4N_BASE_URL=https://api.n4n.ai/v1

Next.js loads this file automatically in development. The gateway expects OpenAI-style auth: Authorization: Bearer <key>. The SDK handles that when you pass apiKey.

Verify connectivity with a script

Before building UI, prove the round trip works. Install tsx for quick TS execution:

npm install -D tsx

Create scripts/check.ts:

import { generateText } from "ai";
import { createOpenAI } from "@ai-sdk/openai";

const gateway = createOpenAI({
  baseURL: process.env.N4N_BASE_URL!,
  apiKey: process.env.N4N_API_KEY!,
});

async function main() {
  const { text } = await generateText({
    model: gateway("gpt-4o-mini"),
    prompt: "Reply with exactly: hello from gateway",
  });
  console.log(text);
}

main().catch(console.error);

Run it:

npx tsx scripts/check.ts

Expected output

hello from gateway

If you see that, the SDK serialized an OpenAI-compatible request and the gateway returned a completion. Any model id the gateway supports works here.

Understand the message format

Chat endpoints expect an array of { role, content } objects. The useChat hook and streamText use this shape natively. A typical payload to /api/chat looks like:

{
  "messages": [
    { "role": "user", "content": "What is 2+2?" }
  ]
}

The gateway forwards this to the selected upstream model and streams back delta tokens.

Build a streaming chat API route

Create app/api/chat/route.ts:

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

export const runtime = "nodejs";

const gateway = createOpenAI({
  baseURL: process.env.N4N_BASE_URL!,
  apiKey: process.env.N4N_API_KEY!,
});

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

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

  return result.toDataStreamResponse();
}

streamText begins streaming immediately. toDataStreamResponse() encodes the output as a text/event-stream with the framing the Vercel AI SDK React hooks expect. No manual ReadableStream wiring required.

Test the route without the browser:

curl -X POST http://localhost:3000/api/chat \
  -H "Content-Type: application/json" \
  -d '{"messages":[{"role":"user","content":"Say hi in three words"}]}'

Expected stream output (abridged)

data: {"type":"text-start","id":"1"}
data: {"type":"text-delta","id":"1","delta":"Hi"}
data: {"type":"text-delta","id":"1","delta":" there,"}
data: {"type":"text-delta","id":"1","delta":" friend."}
data: {"type":"text-end","id":"1"}
data: {"type":"message-end"}

The exact framing may vary by SDK version, but the hook parses it regardless.

Wire up the client with useChat

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 } = useChat();

  return (
    <main style={{ maxWidth: 600, margin: "2rem auto", fontFamily: "sans-serif" }}>
      <h1>Gateway Chat</h1>
      {messages.map((m) => (
        <div key={m.id} style={{ margin: "1rem 0" }}>
          <strong>{m.role}:</strong> {m.content}
        </div>
      ))}
      <form onSubmit={handleSubmit}>
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="Say something…"
          style={{ width: "100%", padding: "0.5rem" }}
        />
      </form>
    </main>
  );
}

On AI SDK v3, import useChat from ai/react. The hook defaults to posting to /api/chat and appending streamed assistant messages to local state.

Expected browser behavior

  1. npm run dev, open http://localhost:3000.
  2. Type “What is 2+2?” and submit.
  3. An assistant message appears, token by token, ending with “4”.

The network tab shows a single POST to /api/chat with a streaming response. No polling, no WebSocket.

Model routing and fallback notes

The vercel ai sdk n4n.ai getting started setup uses the standard provider adapter, so you keep full control of the model string. Pass "claude-3-5-sonnet", "llama-3-70b", or any gateway-supported id to gateway(). Because n4n.ai honors client routing directives and provides automatic fallback when a provider is rate-limited or degraded, a transient upstream outage won’t necessarily surface as a hard error if a secondary route is healthy.

If you need provider-specific cache control, pass headers in createOpenAI or per-call. The gateway forwards cache-control hints to the upstream, so repeated prompts can hit provider prompt caches when available.

Per-token usage metering

The gateway returns per-token usage in response headers (e.g., x-usage-prompt-tokens). In the route you can log or forward them:

const result = streamText({ model: gateway("gpt-4o-mini"), messages });
const response = result.toDataStreamResponse({
  headers: { "x-gateway-tag": "demo" },
});
return response;

For production, attach usage to your own analytics after result.usage resolves.

Cleanup and next steps

Delete scripts/check.ts if you don’t need it. Confirm .env.local is git-ignored (Next.js does this by default). From here, extend the route with tool calls, a system prompt, or auth middleware. Swap the model id to any of the 240+ addresses the gateway exposes and the same code path works.

You now have a minimal but production-shaped chat app: one SDK, one endpoint, zero custom transport code.

Tagsvercel-ai-sdkn4n-aigetting-startedsetup

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 getting started with n4n.ai posts →