Skip to content

Use Genkit in a Next.js app

This page shows how you can use Genkit flows in your Next.js applications using the official Genkit Next.js plugin. For complete API reference documentation, see the Genkit Next.js Plugin API Reference.

Before you begin

You should be familiar with Genkit’s concept of flows, and how to write them.

Create a Next.js project

If you don’t already have a Next.js project that you want to add generative AI features to, you can create one for the purpose of following along with this page:

Terminal window
npx create-next-app@latest

Install Genkit dependencies

Install the Genkit dependencies into your Next.js app:

  1. Install the core Genkit library and the Next.js plugin:

    Terminal window
    npm install genkit @genkit-ai/next
  2. Install at least one model plugin.

    For example, to use Google AI:

    Terminal window
    npm install @genkit-ai/googleai

    Or to use Vertex AI:

    Terminal window
    npm install @genkit-ai/vertexai
  3. Install the Genkit CLI globally. The tsx tool is also recommended as a development dependency, as it makes testing your code more convenient. Both of these dependencies are optional, however.

    Terminal window
    npm install -g genkit-cli
    npm install --save-dev tsx

Define Genkit flows

Create a new directory in your Next.js project to contain your Genkit flows. For example, create src/genkit/ and add your flow definitions there:

For example, create src/genkit/menuSuggestionFlow.ts:

import { googleAI } from '@genkit-ai/googleai';
import { genkit } from 'genkit';
const ai = genkit({
plugins: [googleAI()],
});
export const menuSuggestionFlow = ai.defineFlow('menuSuggestionFlow', async (restaurantTheme, streamingCallback) => {
const { text } = await ai.generate({
model: googleAI.model('gemini-2.0-flash'),
prompt: `Invent a menu item for a ${restaurantTheme} themed restaurant.`,
streamingCallback: (chunk) => streamingCallback?.(chunk.text),
});
return text;
});

Create API routes

Now, create API routes that expose your flows using the Genkit Next.js plugin. For each flow, create a corresponding route file:

Create src/app/api/menuSuggestion/route.ts:

import { menuSuggestionFlow } from '@/genkit/menuSuggestionFlow';
import { appRoute } from '@genkit-ai/next';
export const POST = appRoute(menuSuggestionFlow);

Call your flows from the frontend

In your frontend code, you can now call your flows using the Genkit Next.js client:

'use client';
import { useState } from 'react';
import { runFlow, streamFlow } from '@genkit-ai/next/client';
import { menuSuggestionFlow } from '@/genkit/menuSuggestionFlow';
export default function Home() {
const [menuItem, setMenuItem] = useState<string>('');
const [isLoading, setIsLoading] = useState(false);
const [streamedText, setStreamedText] = useState<string>('');
async function getMenuItem(formData: FormData) {
const theme = formData.get('theme')?.toString() ?? '';
setIsLoading(true);
try {
// Regular (non-streaming) approach
const suggestion = await runFlow<typeof menuSuggestionFlow>({
url: '/api/menuSuggestion',
input: theme,
});
setMenuItem(suggestion);
} catch (error) {
console.error('Error generating menu item:', error);
} finally {
setIsLoading(false);
}
}
async function streamMenuItem(formData: FormData) {
const theme = formData.get('theme')?.toString() ?? '';
setIsLoading(true);
setStreamedText('');
try {
// Streaming approach
const result = streamFlow<typeof menuSuggestionFlow>({
url: '/api/menuSuggestion',
input: theme,
});
// Process the stream chunks as they arrive
for await (const chunk of result.stream()) {
setStreamedText((prev) => prev + chunk.output);
}
// Get the final complete response
const finalOutput = await result.output();
setMenuItem(finalOutput);
} catch (error) {
console.error('Error streaming menu item:', error);
} finally {
setIsLoading(false);
}
}
return (
<main>
<form action={getMenuItem}>
<label htmlFor="theme">Suggest a menu item for a restaurant with this theme: </label>
<input type="text" name="theme" id="theme" />
<br />
<br />
<button type="submit" disabled={isLoading}>
Generate
</button>
<button
type="button"
disabled={isLoading}
onClick={(e) => {
e.preventDefault();
const formData = new FormData(e.currentTarget.form);
streamMenuItem(formData);
}}
>
Stream Generation
</button>
</form>
<br />
{streamedText && (
<div>
<h3>Streaming Output:</h3>
<pre>{streamedText}</pre>
</div>
)}
{menuItem && (
<div>
<h3>Final Output:</h3>
<pre>{menuItem}</pre>
</div>
)}
</main>
);
}

Authentication (Optional)

If you need to add authentication to your API routes, you can pass headers with your requests:

const result = await runFlow<typeof menuSuggestionFlow>({
url: '/api/menuSuggestion',
headers: {
Authorization: 'Bearer your-token-here',
},
input: theme,
});

Test your app locally

If you want to run your app locally, you need to make credentials for the model API service you chose available.

  1. Generate an API key for the Gemini API using Google AI Studio.

  2. Set the GEMINI_API_KEY environment variable to your key:

    Terminal window
    export GEMINI_API_KEY=<your API key>

Then, run your app locally as normal:

Terminal window
npm run dev

For Genkit development tools, you can still use:

Terminal window
genkit start -- npx tsx --watch src/genkit/menuSuggestionFlow.ts

Deploy your app

When you deploy your app, you will need to make sure the credentials for any external services you use (such as your chosen model API service) are available to the deployed app. See the following pages for information specific to your chosen deployment platform: