Gemini AI Basic
Used in this guide:Next.js 16.0.1
google/genai 1.29.0
Introduction
This guide walks you through the basic setup for integrating Google Gemini AI into a Next.js project using the official @google/genai SDK. You’ll learn how to install the package, set up your API key securely with environment variables, create a simple API route to handle Gemini requests, and build a basic front-end page to send prompts and display AI responses.
1. Install Google GenAI SDK
npm install @google/genaiAPI Key Setup
Get your API Key at Google AI Studio
Click create API Key. Note that you can also create a project at the same time. I'll use the below values for my test project:
- project name: test-gemini-01
- api key name: test-gemini-01
Store API Key in a Environment Variable
GEMINI_API_KEY=_your_api_key_3. Create Gemini API Route
import { GoogleGenAI } from "@google/genai";
import { NextRequest, NextResponse } from "next/server";
// Create GoogleGenAI Client
const genAI = new GoogleGenAI({
apiKey: process.env.GEMINI_API_KEY
});
export async function POST(req: NextRequest) {
try {
const { prompt } = await req.json() as { prompt: string };
if (!prompt) {
return NextResponse.json({ error: "Missing 'prompt' in request body."}, { status: 400 })
}
const res = await genAI.models.generateContent({
model: "gemini-2.5-flash",
contents: prompt,
});
const output = res.text;
return NextResponse.json({ output });
} catch (error) {
console.error("Gemini API Error:", (error as Error).message);
return NextResponse.json({ error: "Failed to generate content."}, { status: 500 });
}
}4. Use in a Next.js Page
"use client"
import { useState } from "react"
export default function GeminiExamplePage() {
const [prompt, setPrompt] = useState("");
const [response, setResponse] = useState('Type a prompt and click "Generate" to ask Gemini AI.');
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState("");
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError("");
if (!prompt.trim()) {
setError("Please enter a prompt first.");
return;
}
setIsLoading(true);
try {
const res = await fetch('/api/gemini', {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ prompt }),
});
const data = await res.json();
if (!res.ok || data.error) {
setError(data.error || `Error: Status ${res.status}`);
setResponse("Failed to get a response from Gemini.");
};
setResponse(data.output);
} catch (error) {
console.error("Fetch error: ", error);
setError("Error: A network error occurred. Check your connection or server status.");
setResponse("Failed to connect to Gemini.");
} finally {
setIsLoading(false);
}
}
return (
<div className="flex flex-col gap-4 w-full max-w-2xl p-8">
<div className="">
<h1 className="font-bold text-md">Gemini API Example</h1>
<p className="text-sm text-gray-400">This page calls your secure Next.js API Route which then talks to the Gemini API.</p>
</div>
<form onSubmit={handleSubmit}>
<textarea
placeholder="Ask Gemini anything..."
value={prompt}
rows={4}
disabled={isLoading}
onChange={(e) => setPrompt(e.target.value)}
className="bg-gray-700 rounded-lg w-full p-4 text-sm"
/>
<div className="flex w-full justify-end">
<button
type="submit"
disabled={isLoading}
className="bg-sky-600 py-2 px-4 rounded-md text-sm cursor-pointer"
>
{isLoading ? "Generating response...": "Submit"}
</button>
</div>
</form>
{error && (
<div className="text-amber-500">
<p>{error}</p>
</div>
)}
<div className="space-y-4 text-sm">
<h2>Gemini AI Response</h2>
{isLoading && !response.startsWith("Type a prompt") ? (
<p>Thinking...</p>
) : (
<div className="border border-gray-700 rounded-lg p-4 leading-8">
<p>{response}</p>
</div>
)}
</div>
</div>
)
}