Next.js Quick Start
This tutorial walks you through adding Inngest to a Next.js app. By the end, you'll have a working function that runs in the background, triggered by an event, with full visibility into its execution in the Inngest Dev Server.
The guide takes about ten minutes. You'll need an existing Next.js project, or you can create one as part of the setup below.
Before you start
You can use any existing Next.js project for this tutorial. If you don't have one, create a new one by running:
npx create-next-app@latest --ts --eslint --tailwind --src-dir --app --import-alias='@/*' inngest-guide
Once your project is ready, start the development server. If you're using the v4 SDK, set INNGEST_DEV=1 so your app connects to the local Dev Server instead of Inngest Cloud:
INNGEST_DEV=1 npm run dev
You can also add INNGEST_DEV=1 to your .env.local file so you don't need to pass it inline every time.
1. Install Inngest
In a new terminal tab, run the following in your project's root directory:
npm install inngest
2. Run the Inngest Dev Server
The Inngest Dev Server is a local environment where you can send events, trigger functions, and inspect runs in real time. Start it with:
npx inngest-cli@latest dev
Open http://localhost:8288 to see the Dev Server UI. You'll use this to monitor function runs as you work through the tutorial.
3. Create an Inngest client
Inngest invokes your functions through an API endpoint at /api/inngest. The serve handler at this endpoint lets Inngest discover which functions your app has and execute them when triggered. To set that up, you need an Inngest client and a serve route handler.
// src/inngest/client.ts
import { Inngest } from "inngest";
export const inngest = new Inngest({ id: "my-app" });
For the App Router, you also need to create a route handler that serves the Inngest API:
src/app/api/inngest/route.tsimport { serve } from "inngest/next";
import { inngest } from "../../../inngest/client";
export const { GET, POST, PUT } = serve({
client: inngest,
functions: [],
});
4. Write your first function
In this step you'll write a function that processes a task in the background. The function waits for a trigger event, runs a sequence of steps, and returns a result.
This pattern is useful for anything you don't want running in a request/response cycle: sending emails, calling an AI model, processing a file upload, or chaining multiple operations together.
Define the function:
// src/inngest/functions.ts
import { inngest } from "./client";
export const processTask = inngest.createFunction(
{ id: "process-task", triggers: { event: "app/task.created" } },
async ({ event, step }) => {
const result = await step.run("handle-task", async () => {
return { processed: true, id: event.data.id };
});
await step.sleep("pause", "1s");
return { message: `Task ${event.data.id} complete`, result };
}
);
Then register the function with your serve handler:
// src/app/api/inngest/route.ts
import { serve } from "inngest/next";
import { inngest } from "../../../inngest/client";
import { processTask } from "../../../inngest/functions";
export const { GET, POST, PUT } = serve({
client: inngest,
functions: [processTask],
});
5. Trigger your function
There are two ways to trigger a function: from the Dev Server UI, or by sending an event from your app code.
From the Dev Server
Open http://localhost:8288/functions and find process-task. Click Invoke, then send a payload like this:
{
"data": {
"id": "task_001"
}
}
Click Invoke Function. Switch to the Runs tab to see the execution in progress. Click into the run to see each step, its output, and the timeline.
From your app
To trigger the function from code, send an event using the inngest.send() method.
// src/app/api/create-task/route.ts
import { NextResponse } from "next/server";
import { inngest } from "../../../inngest/client";
export async function POST() {
await inngest.send({
name: "app/task.created",
data: { id: "task_001" },
});
return NextResponse.json({ message: "Event sent" });
}
Send a request to your new endpoint:
curl -X POST http://localhost:3000/api/create-task
You'll see a new run appear in the Dev Server. In practice, you would call inngest.send() from the places in your app that send events: form submissions, webhook handlers, API routes, and so on.
Next steps
You now have Inngest running locally in a Next.js app. From here, a few directions worth exploring:
- Configure checkpointing for serverless. v4 enables checkpointing by default, which lets multiple steps run in a single request. If you're on Vercel or another serverless platform, set
maxRuntimeon your client andmaxDurationon your/api/inngestroute to avoid timeout issues. See the Vercel deployment guide for details. - Deploy to production. Connect your app to Inngest Cloud and sync your functions. See the deployment guide if you're on Vercel.
- Build a multi-step workflow. Add branching logic, retries, and parallel steps. The Inngest Functions overview covers what's available.
- Orchestrate AI workflows. Use
step.ai.wrap()to make LLM calls durable and retryable, orstep.waitForSignal()to pause a workflow until a human approves an action. See the AI orchestration guide.