Skip to content

New Official SDKs for TypeScript, Python and Go

SerpKite
Get API key

Next.js App Router · @serpkite/ai-sdk

Next.js + SerpKite

Build a Next.js chatbot that searches Google before it answers: one route handler with streamText and serpkiteTools(), useChat on the client, and your API key never leaves the server.

Overview

What Next.js is, and where SerpKite fits

Next.js route handlers and server actions run on the server, which is where the SerpKite key belongs. The AI SDK streams the model's answer, including each tool call, to the browser.

@serpkite/ai-sdk gives the model search, news, maps, webpage, extract and crawl tools. Its client reads SERPKITE_API_KEY on the first call, so the module-level tool set doesn't break next build.

Setup

Set it up in 4 steps

  1. 1

    Get an API key

    Sign up (no card) and create a key in the dashboard. Put it in .env.local and in your Vercel project's environment variables. Never prefix it with NEXT_PUBLIC_.

    SERPKITE_API_KEY=skt_live_…
    OPENAI_API_KEY=sk-…
  2. 2

    Install

    Tools, the AI SDK core and React hooks, a model provider and zod.

    npm install @serpkite/ai-sdk ai @ai-sdk/react @ai-sdk/openai zod
  3. 3

    Add the route handler

    app/api/chat/route.ts streams the answer. maxDuration gives the model time to search and read a page or two.

  4. 4

    Render the chat

    useChat posts to /api/chat by default. Tool calls arrive as tool-<name> parts, so you can show what the model searched for.

Code

Complete example

import { openai } from "@ai-sdk/openai";
import { serpkiteTools } from "@serpkite/ai-sdk";
import { convertToModelMessages, stepCountIs, streamText, type UIMessage } from "ai";

export const maxDuration = 60;

const tools = serpkiteTools({ only: ["search", "news", "webpage"] });

export async function POST(req: Request) {
  const { messages }: { messages: UIMessage[] } = await req.json();
  const result = streamText({
    model: openai("gpt-5-mini"),
    system: "Search the web before answering questions about current facts. Cite the URLs you used.",
    messages: await convertToModelMessages(messages),
    tools,
    stopWhen: stepCountIs(5),
  });
  return result.toUIMessageStreamResponse();
}

Server actions

No chat UI? Call it from a server action

A server action can run the same tools with generateText and return the answer to a form or a server component.

app/actions.ts
"use server";

import { openai } from "@ai-sdk/openai";
import { serpkiteTools } from "@serpkite/ai-sdk";
import { generateText, stepCountIs } from "ai";

const tools = serpkiteTools({ only: ["search", "webpage"] });

export async function research(question: string) {
  const { text } = await generateText({
    model: openai("gpt-5-mini"),
    tools,
    stopWhen: stepCountIs(5),
    prompt: question,
  });
  return text;
}

Runtime

Edge, caching and long crawls

Add export const runtime = "edge" to the route to run it on the edge; both packages only use fetch.

To save credits on repeated questions, pin fixed: { max_age: 3600 } on a tool: cached results within that age cost half.

crawl returns a task id by default, and the model polls it with crawl_result. serpkiteCrawl({ wait: true }) waits for the pages instead; raise maxDuration first, since a crawl can run for minutes.

Keep the key on the server

Import `@serpkite/ai-sdk` only in route handlers, server actions and server components. A client component would bundle your key into the browser.

FAQ

Next.js and SerpKite: common questions

Start building

Give your Next.js project Google search

2,500 free credits, then 1,000 every month. No credit card.