n4nAI

Deploying a Vercel AI SDK app with n4n.ai on the edge

Deploy a Vercel AI SDK streaming chat app to the edge runtime using n4n.ai as the model gateway, with runnable code and verification steps.

n4n Team3 min read738 words

Audio narration

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

The Vercel AI SDK makes streaming LLM responses straightforward, but most tutorials stop at the default OpenAI provider. Swapping in n4n.ai gives you one endpoint that reaches 240-plus models with automatic fallback when a provider degrades — useful when you’re running on the edge where cold starts and latency budgets are tight. This walkthrough takes you from a fresh repository to a verified edge deployment in six steps.

Step 1: Initialize the project with the edge runtime

Create a new Next.js app with the App Router and TypeScript. The edge runtime requires Next.js 13.4 or later.

npx create-next-app@latest ai-edge-chat \
  --typescript \
  --tailwind \
  --eslint \
  --app \
  --src-dir \
  --import-alias "@/*" \
  --use-npm
cd ai-edge-chat

Open next.config.js and ensure the experimental edge runtime flag is not blocking you — it’s stable now, so no flag needed. Verify your package.json includes the AI SDK dependencies:

npm install ai @ai-sdk/react

You’ll also need the OpenAI-compatible client since n4n.ai speaks the same wire protocol:

npm install openai

Step 2: Configure the n4n.ai client

Create a singleton client in src/lib/gateway.ts. Keep it out of the route handler so the connection pool survives across invocations on the edge.

// src/lib/gateway.ts
import OpenAI from "openai";

export const gateway = new OpenAI({
  baseURL: "https://api.n4n.ai/v1",
  apiKey: process.env.N4N_API_KEY,
  // Edge runtime doesn't support Node's default fetch; use the global one
  dangerouslyAllowBrowser: true,
});

Add your key to .env.local (never commit this):

# .env.local
N4N_API_KEY=n4n_sk_...

The dangerouslyAllowBrowser flag looks alarming but is the supported way to tell the OpenAI SDK to use the global fetch available in the edge runtime instead of Node’s http module.

Step 3: Build the edge route handler

Create src/app/api/chat/route.ts. This is where the streaming happens. Mark the runtime explicitly.

// src/app/api/chat/route.ts
import { gateway } from "@/lib/gateway";
import { streamText } from "ai";
import { createOpenAI } from "@ai-sdk/openai";

export const runtime = "edge";

const n4n = createOpenAI({
  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: n4n("gpt-4o-mini"),
    messages,
    temperature: 0.7,
    maxTokens: 512,
  });

  return result.toDataStreamResponse();
}

A few things matter here:

  • export const runtime = "edge" opts the route into the edge runtime. Without it, you get the Node.js runtime and lose the cold-start advantage.
  • createOpenAI from @ai-sdk/openai builds a provider that the AI SDK’s streamText understands. It handles the SSE framing and tool-call parsing for you.
  • The model string "gpt-4o-mini" is a routing directive. n4n.ai resolves it to the best available provider at request time and honors cache-control hints from upstream.

Step 4: Wire up the frontend

Replace src/app/page.tsx with a minimal chat interface using the useChat hook.

// src/app/page.tsx
"use client";

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

export default function Page() {
  const { messages, input, handleInputChange, handleSubmit } = useChat({
    api: "/api/chat",
  });

  return (
    <main className="flex min-h-screen flex-col items-center p-8">
      <div className="w-full max-w-2xl">
        <h1 className="mb-6 text-3xl font-semibold">Edge chat</h1>
        <div className="mb-4 h-[500px] overflow-y-auto border rounded-lg p-4">
          {messages.map((m) => (
            <div key={m.id} className="mb-4">
              <strong className="capitalize">{m.role}:</strong>
              <p className="mt-1 whitespace-pre-wrap">{m.content}</p>
            </div>
          ))}
        </div>
        <form onSubmit={handleSubmit} className="flex gap-2">
          <input
            value={input}
            onChange={handleInputChange}
            placeholder="Type a message…"
            className="flex-1 rounded border px-3 py-2"
            disabled={messages.some((m) => m.role === "assistant" && m.content === "")}
          />
          <button
            type="submit"
            disabled={messages.some((m) => m.role === "assistant" && m.content === "")}
            className="rounded bg-blue-600 px-4 py-2 text-white disabled:opacity-50"
          >
            Send
          </button>
        </form>
      </div>
    </main>
  );
}

The "use client" directive is required because useChat uses browser-only APIs. The hook posts to /api/chat automatically and renders the streaming tokens as they arrive.

Step 5: Deploy to Vercel

Push to a Git provider and import the repository in Vercel. The default settings work — Vercel detects Next.js and the edge runtime annotation.

git init
git add .
git commit -m "Initial edge chat app"
git branch -M main
git remote add origin https://github.com/your-org/ai-edge-chat.git
git push -u origin main

In the Vercel dashboard, add the environment variable N4N_API_KEY with the same value from .env.local. No other configuration is needed. The edge function will be deployed to Vercel’s global network automatically.

Step 6: Verify the deployment

Open the deployed URL. You should see the chat interface. Send a message and confirm:

  1. Streaming works — tokens appear incrementally, not in a single block after a long pause.
  2. Edge runtime is active — open the browser dev tools Network tab, filter for the /api/chat request, and check the response headers. You should see x-vercel-edge: 1 or similar indicating edge execution.
  3. Model routing works — the response should reflect gpt-4o-mini behavior (concise, fast). If you change the model string in route.ts to "claude-3-haiku" and redeploy, the same endpoint serves a different provider without code changes beyond the model name.

Run a quick latency check from a few regions using curl with the --resolve flag or a synthetic monitoring tool. Expect sub-200 ms time-to-first-token from most major metros when the model is warm.

curl -N -X POST https://your-deployment.vercel.app/api/chat \
  -H "Content-Type: application/json" \
  -d '{"messages":[{"role":"user","content":"Say hello in one word"}]}'

The -N flag disables buffering so you see the SSE stream in real time. You should get a data: line per token.

Common edge gotchas

Module not found errors on deploy — The edge runtime doesn’t support all Node.js built-ins. If you import a package that uses fs, crypto, or net at the top level, the build fails. The OpenAI SDK and AI SDK are edge-compatible; avoid adding heavy utilities like pdf-parse or sharp in the same route file.

Environment variables missing — Vercel does not copy .env.local to production. Add every secret in the Vercel dashboard under Settings → Environment Variables, then redeploy.

Streaming cuts off — The edge runtime has a default 30-second max execution time. If your maxTokens or model latency pushes past that, the stream truncates. Keep maxTokens conservative (512–1024) for edge chat, or move long generations to a background queue with a polling frontend.

CORS on custom domains — If you call the API from a different origin, add a middleware.ts to inject CORS headers on the edge:

// src/middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(req: NextRequest) {
  if (req.nextUrl.pathname.startsWith("/api/")) {
    const res = NextResponse.next();
    res.headers.set("Access-Control-Allow-Origin", "*");
    res.headers.set("Access-Control-Allow-Methods", "POST, OPTIONS");
    res.headers.set("Access-Control-Allow-Headers", "Content-Type");
    return res;
  }
  return NextResponse.next();
}

export const config = {
  matcher: "/api/:path*",
};

What you now have

A streaming chat application that runs on Vercel’s edge network, routes through a single gateway to hundreds of models, and fails over automatically when a provider hits rate limits or goes degraded. The same pattern scales to tool calling, structured outputs, and multi-step agents — just extend the streamText call and the frontend hook.

Tagsvercel-ai-sdkn4n-aiedgedeployment

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 on edge & serverless runtimes posts →