Skip to content

Commit ab6558b

Browse files
opti21omeraplak
andauthored
chore(docs): update next.js example to match template (#597)
* chore(docs): update next.js example to match template * chore: update zod version --------- Co-authored-by: Omer Aplak <[email protected]>
1 parent c442c2b commit ab6558b

File tree

1 file changed

+188
-95
lines changed

1 file changed

+188
-95
lines changed

website/docs/integrations/nextjs.md

Lines changed: 188 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ If you prefer to start directly with the completed example project, you can crea
1515
npm create voltagent-app@latest -- --example with-nextjs
1616
```
1717

18-
This command will scaffold the entire Next.js example project described in this guide.
18+
This command will scaffold an entire Next.js example for you. You can also peek at the full source code right here: [examples/with-nextjs](https://github.com/VoltAgent/voltagent/tree/main/examples/with-nextjs).
1919

2020
## Create a New Next.js Project
2121

@@ -30,157 +30,250 @@ Follow the prompts, selecting TypeScript and App Router.
3030

3131
## Install VoltAgent Dependencies
3232

33-
Install the necessary VoltAgent packages and the ai-sdk provider:
33+
Install the necessary VoltAgent packages and dependencies:
3434

3535
```bash
36-
npm install @voltagent/core @voltagent/cli @ai-sdk/openai zod@^3.25.0
36+
npm install @voltagent/core @ai-sdk/openai @ai-sdk/react ai zod@^3.25.76
3737
```
3838

3939
- `@voltagent/core`: The core VoltAgent library.
4040
- `@ai-sdk/openai`: The ai-sdk provider for OpenAI (or your preferred provider).
41-
- `@voltagent/cli`: The command-line interface for VoltAgent tasks.
41+
- `@ai-sdk/react`: React hooks for AI SDK integration.
42+
- `ai`: Core AI SDK library for streaming and chat functionality.
4243
- `zod`: Used when working with structured outputs.
4344

44-
## Configure `next.config.js`
45+
## Configure `next.config.ts`
4546

46-
Next.js might try to bundle server-side packages by default. To prevent issues with VoltAgent, you need to mark its packages as external in your `next.config.mjs` (or `.js` / `.ts`) file:
47+
Next.js might try to bundle server-side packages by default. To prevent issues with certain packages, you need to mark them as external in your `next.config.ts` file:
4748

48-
```typescript title="next.config.mjs // or next.config.ts"
49+
```typescript title="next.config.ts"
4950
import type { NextConfig } from "next";
5051

5152
const nextConfig: NextConfig = {
52-
experimental: {
53-
// Mark VoltAgent packages as external
54-
serverComponentsExternalPackages: ["@voltagent/*"],
55-
// If using other packages that need to run externally (like npm-check-updates in the example)
56-
// add them here too.
57-
// serverComponentsExternalPackages: ["@voltagent/*", "another-package"],
58-
},
53+
serverExternalPackages: [
54+
// Externalize only what's needed at runtime.
55+
// LibSQL client is safe to externalize; native platform packages are optional.
56+
"@libsql/client",
57+
],
5958
};
6059

6160
export default nextConfig;
6261
```
6362

64-
**Note:** The property was `serverExternalPackages` in older Next.js versions, but changed to `experimental.serverComponentsExternalPackages`. Ensure you use the correct one for your Next.js version.
65-
66-
## Initialize VoltAgent
67-
68-
Create a file to initialize an Agent, for example, `voltagent/index.ts` in your project root:
69-
70-
```typescript title="voltagent/index.ts"
71-
import { Agent } from "@voltagent/core";
72-
import { openai } from "@ai-sdk/openai"; // Or your preferred ai-sdk provider
63+
**Note:** The property used to be `experimental.serverComponentsExternalPackages` in older Next.js versions, but is now `serverExternalPackages`. Ensure you use the correct one for your Next.js version.
7364

74-
export const agent = new Agent({
75-
name: "nextjs-agent",
76-
instructions: "You are a helpful assistant",
77-
model: openai("gpt-4o"),
78-
});
79-
```
65+
## Environment Variables
8066

81-
Remember to set up your environment variables (e.g., `OPENAI_API_KEY`) in a `.env.local` file.
82-
Create a `.env.local` file in your project root if it doesn't exist, and add your necessary API keys:
67+
Set up your environment variables (e.g., `OPENAI_API_KEY`) in a `.env.local` file:
8368

8469
```env title=".env.local"
8570
OPENAI_API_KEY="your-openai-api-key-here"
8671
# Add other environment variables if needed
8772
```
8873

89-
## Create a Server Action
74+
## Create API Route
75+
76+
Create the main chat API route with the agent and singleton defined inline in `app/api/chat/route.ts`:
77+
78+
```typescript title="app/api/chat/route.ts"
79+
import { openai } from "@ai-sdk/openai";
80+
import { Agent, VoltAgent, createTool } from "@voltagent/core";
81+
import { honoServer } from "@voltagent/server-hono";
82+
import { z } from "zod";
83+
84+
// Simple calculator tool
85+
const calculatorTool = createTool({
86+
name: "calculate",
87+
description: "Perform basic mathematical calculations",
88+
parameters: z.object({
89+
expression: z
90+
.string()
91+
.describe("Mathematical expression to evaluate (e.g., '2 + 2', '10 * 5')"),
92+
}),
93+
execute: async (args) => {
94+
try {
95+
// Simple evaluation - in production, use a proper math parser
96+
const result = eval(args.expression);
97+
return { result, expression: args.expression };
98+
} catch {
99+
return { error: "Invalid mathematical expression", expression: args.expression };
100+
}
101+
},
102+
});
90103

91-
Define a Server Action to interact with the VoltAgent agent. Create `app/actions.ts`:
104+
// Main agent
105+
export const agent = new Agent({
106+
name: "CalculatorAgent",
107+
instructions:
108+
"You are a helpful calculator assistant. When users ask you to calculate something, use the calculate tool to perform the math and then explain the result clearly.",
109+
model: openai("gpt-4o-mini"),
110+
tools: [calculatorTool],
111+
});
92112

93-
```typescript title="app/actions.ts"
94-
"use server";
113+
// VoltAgent singleton (augments global scope during dev to avoid re-instantiation)
114+
declare global {
115+
var voltAgentInstance: VoltAgent | undefined;
116+
}
95117

96-
import { agent } from "@/voltagent"; // Adjust path if needed
118+
function getVoltAgentInstance() {
119+
if (!globalThis.voltAgentInstance) {
120+
globalThis.voltAgentInstance = new VoltAgent({
121+
agents: {
122+
agent,
123+
},
124+
server: honoServer(),
125+
});
126+
}
127+
return globalThis.voltAgentInstance;
128+
}
97129

98-
export async function calculateExpression(expression: string) {
99-
const result = await agent.generateText(
100-
`Calculate ${expression}. Only respond with the numeric result.`
101-
);
130+
export const voltAgent = getVoltAgentInstance();
102131

103-
return result.text;
132+
export async function POST(req: Request) {
133+
try {
134+
const { messages } = await req.json();
135+
const lastMessage = messages[messages.length - 1];
136+
137+
const result = await agent.streamText([lastMessage]);
138+
return result.toUIMessageStreamResponse();
139+
} catch (error) {
140+
return Response.json({ error: "Internal server error" }, { status: 500 });
141+
}
104142
}
105143
```
106144

107-
## Build the UI Component
145+
## Build the Chat UI Component (Client Component)
108146

109-
Create a client component to take user input and display the result. Create `app/components/calculator.tsx`:
147+
Create a client component in `app/components/chat.tsx`:
110148

111-
```typescript title="app/components/calculator.tsx"
149+
```typescript title="app/components/chat.tsx"
112150
"use client";
113151

114-
import { useState } from "react";
115-
import { calculateExpression } from "../actions";
152+
import { useChat } from "@ai-sdk/react";
153+
import { useEffect, useRef } from "react";
116154

117-
export function Calculator() {
118-
const [result, setResult] = useState<string | null>(null);
119-
const [loading, setLoading] = useState(false);
120-
const [expression, setExpression] = useState("");
155+
export function Chat() {
156+
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
157+
api: "/api/chat",
158+
});
121159

122-
async function handleSubmit(formData: FormData) {
123-
const expr = formData.get("expression") as string;
124-
if (!expr.trim()) return;
160+
const messagesEndRef = useRef<HTMLDivElement>(null);
125161

126-
setLoading(true);
127-
try {
128-
const calcResult = await calculateExpression(expr);
129-
setResult(calcResult);
130-
setExpression(expr);
131-
} catch (error) {
132-
console.error("Calculation error:", error);
133-
setResult("Error calculating expression");
134-
} finally {
135-
setLoading(false);
136-
}
137-
}
162+
// Auto-scroll to bottom when new messages arrive
163+
useEffect(() => {
164+
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
165+
}, [messages]);
138166

139167
return (
140168
<div>
141-
<h2>AI Calculator</h2>
142-
<form action={handleSubmit}>
143-
<label htmlFor="expression">Enter calculation:</label>
144-
<input
145-
id="expression"
146-
name="expression"
147-
type="text"
148-
placeholder="E.g. (5 + 3) * 2"
149-
required
150-
/>
151-
<button type="submit" disabled={loading}>
152-
{loading ? "Calculating..." : "Calculate"}
153-
</button>
154-
</form>
155-
156-
{result && (
157-
<div>
158-
<h3>Result:</h3>
159-
<p>{expression} = {result}</p>
160-
</div>
161-
)}
169+
<div>
170+
<h2>VoltAgent Calculator</h2>
171+
<p>Ask me to calculate anything!</p>
172+
</div>
173+
174+
{/* Messages */}
175+
<div>
176+
{messages.map((message) => (
177+
<div key={message.id}>
178+
<strong>{message.role === "user" ? "You" : "Agent"}:</strong>
179+
<div>{message.content}</div>
180+
</div>
181+
))}
182+
<div ref={messagesEndRef} />
183+
</div>
184+
185+
{/* Input */}
186+
<div>
187+
<form onSubmit={handleSubmit}>
188+
<input
189+
value={input}
190+
onChange={handleInputChange}
191+
disabled={isLoading}
192+
placeholder="Ask me to calculate something..."
193+
/>
194+
<button type="submit" disabled={isLoading}>
195+
{isLoading ? "Thinking..." : "Send"}
196+
</button>
197+
</form>
198+
</div>
162199
</div>
163200
);
164201
}
165202
```
166203

204+
## Optional: Server Action Example
205+
206+
Create a server action in `app/actions.ts`:
207+
208+
```typescript title="app/actions.ts"
209+
"use server";
210+
211+
import { agent } from "@/voltagent";
212+
213+
export async function calculate(formData: FormData) {
214+
const expression = String(formData.get("expression") || "");
215+
const result = await agent.generateText(
216+
`Calculate ${expression}. Only return the numeric result.`
217+
);
218+
return result.text;
219+
}
220+
```
221+
222+
Use it from a simple server component form in `app/server-action-example.tsx`:
223+
224+
```typescript title="app/server-action-example.tsx"
225+
import { calculate } from "@/app/actions";
226+
227+
export default function ServerActionExample() {
228+
return (
229+
<form action={calculate}>
230+
<input name="expression" placeholder="e.g. (5 + 3) * 2" />
231+
<button type="submit">Calculate</button>
232+
</form>
233+
);
234+
}
235+
```
236+
167237
_(Styling omitted for brevity. Refer to the example project for full styling)_
168238

169-
## Use the Component
239+
## Create the Main Page
170240

171-
Finally, import and use the `Calculator` component in your main page (`app/page.tsx`):
241+
Update your main page to use the chat component in `app/page.tsx`:
172242

173243
```typescript title="app/page.tsx"
174-
import { Calculator } from "./components/calculator";
244+
import { Chat } from "./components/chat";
175245

176-
export default function HomePage() {
246+
export default function Home() {
177247
return (
178-
<main>
179-
<h1>VoltAgent Next.js Example</h1>
180-
<Calculator />
181-
</main>
248+
<div>
249+
<div>
250+
<h1>VoltAgent Next.js Example</h1>
251+
<p>A simple calculator agent with tools</p>
252+
</div>
253+
254+
// highlight-next-line
255+
<Chat />
256+
257+
<div>
258+
<p>This example demonstrates VoltAgent with a custom tool for calculations.</p>
259+
</div>
260+
</div>
182261
);
183262
}
184263
```
185264

186-
Now you can run your Next.js development server (`npm run dev`) and test the AI calculator! This demonstrates a basic integration of VoltAgent within a Next.js application using Server Actions.
265+
## Run the Application
266+
267+
Now you can run your Next.js development server:
268+
269+
```bash
270+
npm run dev
271+
```
272+
273+
This creates a simple but powerful VoltAgent application with:
274+
275+
- **Single agent** with a custom calculator tool
276+
- **Streaming chat interface** with real-time updates
277+
- **Tool integration** showing how agents use tools
278+
279+
The agent will use the calculator tool when users ask for mathematical calculations, demonstrating how VoltAgent integrates tools seamlessly into conversations.

0 commit comments

Comments
 (0)