Integrating the Anthropic Claude API into a Next.js App
A practical guide to adding Claude AI to your Node.js or Next.js application — covering streaming responses, tool use, prompt caching, and patterns that work in production.
Anthropic's Claude API is one of the most capable LLM APIs available. This guide covers integrating it into a Next.js application — from basic completions to streaming, tool use, and prompt caching — using patterns I've applied in production AI products.
Installation and Basic Setup
Install the Anthropic SDK and add your API key to environment variables. Your API key must never be exposed to the browser — always call the Claude API from a Next.js Route Handler or Server Action. The SDK works in both Node.js and edge runtimes.
npm install @anthropic-ai/sdk// app/api/chat/route.js
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
export async function POST(req) {
const { message } = await req.json();
const response = await client.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
messages: [{ role: 'user', content: message }],
});
return Response.json({ text: response.content[0].text });
}Streaming Responses
For conversational UI, streaming is essential. Users see output within milliseconds of submitting rather than waiting for the full response. The SDK's stream() method handles the SSE protocol and provides a clean async iterator over text chunks. Return a ReadableStream from your Route Handler and consume it on the client with the Fetch API.
// app/api/chat/route.js (streaming)
export async function POST(req) {
const { messages } = await req.json();
const stream = client.messages.stream({
model: 'claude-sonnet-4-6',
max_tokens: 2048,
messages,
});
const readable = new ReadableStream({
async start(controller) {
for await (const chunk of stream) {
if (
chunk.type === 'content_block_delta' &&
chunk.delta.type === 'text_delta'
) {
controller.enqueue(new TextEncoder().encode(chunk.delta.text));
}
}
controller.close();
},
});
return new Response(readable, {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
}Managing Conversation History
Claude's API is stateless — you send the full conversation history with every request. On the client, maintain messages as an array of {role, content} objects. Append user messages immediately for optimistic UI, then append the assistant's complete streamed response when finished. For long conversations approaching the context limit, implement a sliding window or summarisation step to keep costs manageable.
Prompt Caching for Cost Reduction
Prompt caching is one of the highest-ROI optimisations for production AI apps. If your application uses a long system prompt — documentation, a product catalogue, a knowledge base — mark the static portion with cache_control. Anthropic caches these tokens server-side for 5 minutes and reuses them across requests, reducing cost by up to 90% for cached tokens and cutting latency significantly.
const response = await client.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
system: [
{
type: 'text',
text: LARGE_KNOWLEDGE_BASE_TEXT, // thousands of tokens, rarely changes
cache_control: { type: 'ephemeral' },
},
],
messages: [{ role: 'user', content: userMessage }],
});
// Check cache performance in the response
console.log(response.usage.cache_read_input_tokens); // tokens served from cacheTool Use (Function Calling)
Claude's tool use lets the model call external functions — search APIs, your database, third-party services — and incorporate the results into its final response. Define tools as JSON schemas, implement an agentic loop that executes tool calls and feeds results back, and repeat until Claude returns a final text response.
const tools = [{
name: 'get_listing_details',
description: 'Retrieve marketplace listing details by ID',
input_schema: {
type: 'object',
properties: { listing_id: { type: 'string' } },
required: ['listing_id'],
},
}];
async function runAgent(userMessage) {
let messages = [{ role: 'user', content: userMessage }];
while (true) {
const response = await client.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
tools,
messages,
});
if (response.stop_reason === 'end_turn') {
return response.content.find((b) => b.type === 'text').text;
}
const toolUse = response.content.find((b) => b.type === 'tool_use');
const result = await executeToolCall(toolUse.name, toolUse.input);
messages = [
...messages,
{ role: 'assistant', content: response.content },
{ role: 'user', content: [{ type: 'tool_result', tool_use_id: toolUse.id, content: JSON.stringify(result) }] },
];
}
}Building a RAG Pipeline
For AI assistants over private data, combine Claude with a vector database. Embed the user's query using an embedding model (Voyage AI or OpenAI embeddings), retrieve the top-k most relevant chunks from your vector store (Pinecone, Supabase pgvector, or Chroma), and pass those chunks in Claude's system prompt with cache_control enabled. Since only the user's question changes between requests, the large document context is served from cache — making RAG applications dramatically cheaper at scale.
Rate Limiting and Error Handling
In production, implement per-user rate limiting at the Route Handler level. A Redis sliding window — for example, 10 requests per minute per authenticated user — prevents abuse. The Anthropic SDK retries on 529 and 5xx errors with exponential backoff automatically. Log every API call with user ID and token counts from response.usage — understanding usage patterns is essential for forecasting and cost control at scale.
Choosing the Right Model
Match the model to the task. Claude Sonnet 4.6 handles the majority of production use cases — conversational AI, code generation, document analysis — with an excellent cost-to-capability ratio. Claude Opus 4.8 is for tasks where quality matters more than cost: complex multi-step reasoning, nuanced creative work, or agentic workflows that require strong judgment. Claude Haiku 4.5 targets high-volume, latency-sensitive tasks where speed and cost are the priority.
Further Reading
Frequently Asked Questions
Which Claude model should I use for production?
For most production use cases, Claude Sonnet 4.6 offers the best balance of capability and cost. Use Claude Opus 4.8 for tasks requiring maximum reasoning — complex analysis or multi-step agentic workflows. Use Claude Haiku 4.5 for high-volume, low-latency tasks like classification or simple Q&A.
How do I implement streaming with the Claude API in Next.js?
Create a Next.js Route Handler that calls client.messages.stream() and returns a ReadableStream. On the client, consume the stream with the Fetch API and update state as chunks arrive. The Anthropic SDK's stream helper handles the SSE protocol automatically.
What is prompt caching and how much does it save?
Prompt caching lets you cache static parts of your prompt on Anthropic's servers. Cached tokens cost 90% less than regular input tokens and reduce latency significantly. For applications with long system prompts — RAG context, product catalogues, documentation — this is one of the most impactful cost optimisations available.
How does Claude tool use work?
You define tools as JSON schemas describing function names and parameters. Claude decides when to call a tool and returns a tool_use block. You execute the function and return the result. Claude incorporates the result into its final response. This is the foundation for building AI agents that interact with APIs, databases, and external services.
How do I prevent users from abusing my Claude API integration?
Implement per-user rate limiting at the Route Handler level with Redis. Never expose your API key to the browser. Validate and sanitise all inputs before sending to Claude. Set max_tokens to a reasonable limit. Log all API calls with user IDs and token counts for monitoring.
What is the context window limit for Claude?
Claude Sonnet 4.6 and Opus 4.8 both support a 200,000 token context window — approximately 150,000 words. This is large enough for entire codebases, long documents, or extended conversation histories.
Can I use the Claude API to build a RAG system?
Yes. A typical RAG pattern: embed the user's query, retrieve relevant chunks from a vector database (Pinecone, Supabase pgvector), and include those chunks in Claude's context with cache_control enabled. Claude answers based on the retrieved context. This is how you build AI assistants over private data.
How do I handle Claude API errors in production?
The Anthropic SDK retries on 529 (overload) and 5xx errors automatically with exponential backoff. For rate limit errors (429), implement your own request queue. Always handle overload errors gracefully in the UI — show a 'Try again' option rather than a hard error.
More Articles
Need help with this?
I'm available for Sharetribe Flex, Shopify, Next.js, and AI integration projects.
Get In Touch