Skip to main content
⏱️ Duration: 10 minutes | Add AI superpowers to your Next.js apps!

What is Vercel AI SDK?

The Vercel AI SDK is a TypeScript library for building AI-powered applications. It works with multiple AI providers and makes it easy to integrate AI into your apps.

AI SDK Documentation

Official documentation for the Vercel AI SDK

The Journey of AI: From Games to Gemini

Before we dive into code, let’s understand how AI got here. It’s a fascinating story! The foundation of AI is search. Think about it:
  • 🎮 Pacman ghosts search for the best path to catch you
  • ♟️ Chess AI searches millions of moves to find the best one
  • 💬 ChatGPT searches through patterns in language
  • Gemini searches across text, images, video, and code
Why Google leads AI: Google is the world’s best at search—the foundation of AI. This is why they’re state-of-the-art across text generation, math reasoning, image generation, video generation, and more. When you use Gemini, you’re using decades of search innovation!

🎬 Want to Learn More? Watch These!

AI Providers Today


Getting Started

Install Dependencies

bun add ai @ai-sdk/google zod

Get Your API Key (Free!)

Google AI Studio

Get a free API key with generous usage limits

Environment Variables

Create .env.local in your project root:
GOOGLE_GENERATIVE_AI_API_KEY=your-api-key-here
Never commit API keys! Add .env.local to your .gitignore file.

Text Generation

The simplest way to use AI is generating text. Let’s start here!

Your First AI Call

import { generateText } from 'ai';
import { google } from "@ai-sdk/google";

const { text } = await generateText({
  model: google("gemini-2.5-flash"),
  system:
    'You are a professional writer. ' +
    'You write simple, clear, and concise content.',
  prompt: `Summarize the following article in 3-5 sentences: ${article}`,
});

console.log(text);
Why Gemini? Google offers free API access with generous limits—perfect for learning and prototyping!

Text Generation Docs

Learn more about text generation options

Structured Data Generation

Text is great, but what if you need data you can use programmatically?

The Problem with Plain Text

// ❌ Unstructured text - hard to use programmatically
const response = "Here's a recipe: Lasagna. You'll need pasta, cheese, sauce...";

// How do you extract the ingredients? The steps? 🤔

The Solution: Structured Output

// ✅ Structured data - easy to use!
const recipe = {
  name: "Lasagna",
  ingredients: [
    { name: "pasta sheets", amount: "12 sheets" },
    { name: "ricotta cheese", amount: "2 cups" },
    { name: "tomato sauce", amount: "3 cups" },
  ],
  steps: [
    "Preheat oven to 375°F",
    "Layer sauce, pasta, and cheese",
    "Bake for 45 minutes",
  ],
};

Using generateObject

The generateObject function generates structured data from a prompt:
import { generateObject } from 'ai';
import { google } from '@ai-sdk/google';
import { z } from 'zod';

// Define the shape of your data with Zod
const recipeSchema = z.object({
  name: z.string(),
  ingredients: z.array(
    z.object({
      name: z.string(),
      amount: z.string(),
    })
  ),
  steps: z.array(z.string()),
  prepTime: z.string(),
});

// Generate structured data
const { object: recipe } = await generateObject({
  model: google('gemini-2.5-flash'),
  schema: recipeSchema,
  prompt: 'Generate a recipe for chocolate chip cookies.',
});

// TypeScript knows the exact shape!
console.log(recipe.name); // "Chocolate Chip Cookies"
console.log(recipe.ingredients[0].name); // "flour"

Zod Schemas

Zod defines the shape of your data with TypeScript-first validation.

Common Schema Types

import { z } from 'zod';

// Basic types
const stringSchema = z.string();
const numberSchema = z.number();
const booleanSchema = z.boolean();

// Arrays
const arraySchema = z.array(z.string());

// Objects
const userSchema = z.object({
  name: z.string(),
  age: z.number(),
  email: z.string().email(),
});

Adding Descriptions (Important!)

Descriptions help the AI understand what you want:
const flashcardSchema = z.object({
  flashcards: z.array(
    z.object({
      front: z.string().describe('The question on the flashcard'),
      back: z.string().describe('The answer on the flashcard'),
    })
  ).describe('Array of 10 flashcards'),
});

Complete Example: AI Flashcard Generator

API Route: app/api/flashcards/route.ts

import { generateObject } from 'ai';
import { google } from '@ai-sdk/google';
import { z } from 'zod';
import { NextResponse } from 'next/server';

const flashcardSchema = z.object({
  flashcards: z.array(
    z.object({
      front: z.string().describe('Question'),
      back: z.string().describe('Answer'),
    })
  ),
});

export async function POST(request: Request) {
  const { topic } = await request.json();

  const { object } = await generateObject({
    model: google('gemini-2.5-flash'),
    schema: flashcardSchema,
    prompt: `Generate 5 flashcards about: ${topic}`,
  });

  return NextResponse.json(object);
}

Frontend Component

'use client';

import { useState } from 'react';

export default function FlashcardGenerator() {
  const [topic, setTopic] = useState('');
  const [flashcards, setFlashcards] = useState([]);
  const [loading, setLoading] = useState(false);

  const generate = async () => {
    setLoading(true);
    const res = await fetch('/api/flashcards', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ topic }),
    });
    const data = await res.json();
    setFlashcards(data.flashcards);
    setLoading(false);
  };

  return (
    <div className="p-8 max-w-2xl mx-auto">
      <h1 className="text-2xl font-bold mb-4">AI Flashcard Generator</h1>

      <div className="flex gap-2 mb-6">
        <input
          value={topic}
          onChange={(e) => setTopic(e.target.value)}
          placeholder="Enter a topic..."
          className="flex-1 p-2 border rounded"
        />
        <button
          onClick={generate}
          disabled={loading}
          className="px-4 py-2 bg-blue-500 text-white rounded"
        >
          {loading ? 'Generating...' : 'Generate'}
        </button>
      </div>

      <div className="grid gap-4">
        {flashcards.map((card, i) => (
          <div key={i} className="p-4 bg-white rounded-lg shadow">
            <p className="font-semibold">{card.front}</p>
            <p className="text-gray-600 mt-2">{card.back}</p>
          </div>
        ))}
      </div>
    </div>
  );
}

Key Takeaways

Start with Text

Use generateText for simple AI responses

Level Up with Schemas

Use generateObject for structured data

Google Gemini

Free API access for learning and prototyping

Type-Safe AI

Zod schemas give you TypeScript types automatically

Learn More


Next up: Next Steps & Resources →