---
title: "Next.js"
description: "Run an eve agent and a Next.js app as one project with withEve."
---

`eve/next` connects a Next.js app to one or more eve agents. Wrap your Next.js config with `withEve(nextConfig)` to run the app and agents with one development command and deploy them as one Vercel project. Browser requests use same-origin routes; the agent runtimes remain separate services.

Use this integration when Next.js owns the application's development and deployment lifecycle. If the frontend is a peer of an agent workspace, compose the services with [`eve/vercel`](../deployment/vercel#compose-agents-with-other-vercel-services) on Vercel or your [self-hosted process manager and proxy](../deployment/self-hosting#run-workspace-members). A peer frontend can use `eve/react` without `eve/next`. See [Project Structure](/docs/concepts/project-structure#configure-a-web-deployment) for the choice.

## Prerequisites

- The `eve` package installed in your project (`npm install eve@latest`).
- An existing eve agent directory. If you don't have one, start from [Getting Started](../../getting-started).
- A Next.js app, or a single-agent project where you want to generate one below.

## Add the generated Web Chat app

For a single-agent project, install the generated Next.js Web Chat app:

```bash
eve add channel/web
```

The installer adds a Next.js application and wraps `next.config.ts` with `withEve()`. The generated chat calls the unnamed agent through same-origin `/eve/v1/*` routes.

Before accepting production browser traffic, replace the generated placeholder authorization policy. See [Authenticate browser requests](./overview#authenticate-browser-requests).

The Web Chat installer does not support eve agent workspaces. If you want Next.js to host the integration, create a root Next.js application and follow the steps below; `withEve(nextConfig)` discovers workspace members but does not generate a chat UI. To keep the frontend as a peer application instead, follow the [workspace layout guidance](/docs/concepts/project-structure#configure-a-web-deployment).

## Wrap the Next.js config

```ts title="next.config.ts"
import type { NextConfig } from "next";
import { withEve } from "eve/next";

const nextConfig: NextConfig = {};

export default withEve(nextConfig);
```

By default `withEve(nextConfig)` looks for an `agent/` folder inside your Next.js project root and mounts its API at `/eve/v1/*`. When the project root is an eve workspace with `agents/<name>/` members, it discovers every member and mounts each at `/eve/<name>/v1/*` instead. You do not need an explicit `agents` map for this layout.

If one agent lives somewhere else, point at it with `eveRoot`:

```ts
export default withEve(nextConfig, {
  eveRoot: "../my-agent",
});
```

## Mount agents outside a workspace

To mount agents that are not members of the project-level `agents/` workspace, use `agents`. String values are agent roots; object values can override the build command or private production service prefix for that agent:

```ts
export default withEve(nextConfig, {
  agents: {
    support: "./apps/support-agent",
    billing: {
      root: "./apps/billing-agent",
      buildCommand: "pnpm build:billing-agent",
      servicePrefix: "/_eve_internal/billing",
    },
  },
});
```

Named agents mount under `/eve/<name>/v1/*`. Call the matching agent from React with `agent`:

```tsx
const support = useEveAgent({ agent: "support" });
const billing = useEveAgent({ agent: "billing" });
```

Use either `eveRoot` or `agents`, not both. `eveRoot` remains the shorthand for a single unnamed agent mounted at `/eve/v1/*`.

Generated agent services build with `EVE_PUBLIC_ROUTE_PREFIX` set to the agent's public mount (for example `/eve/support`) so framework-minted callback URLs — OAuth connection callbacks and remote-subagent session callbacks — resolve to the public per-agent path. If you configure eve services manually in `vercel.json` instead, export that variable in each named agent's build command.

### `withEve` options

All fields are optional.

| Option               | Type                  | Default                  | Purpose                                                                                                                                                                                                                                          |
| -------------------- | --------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `eveRoot`            | `string`              | Next.js app root         | Path to one unnamed eve app root, relative to `process.cwd()` unless absolute. Do not combine with `agents`.                                                                                                                                     |
| `agents`             | `Record<string, ...>` | inferred for a workspace | Named eve agents to mount under `/eve/<name>/v1/*`. `withEve()` discovers project-level `agents/<name>/` members when neither `agents` nor `eveRoot` is set; otherwise each value is a root string or `{ root, buildCommand?, servicePrefix? }`. |
| `eveBuildCommand`    | `string`              | generated                | Build command for generated eve Vercel services. In multi-agent mode this is the default for agents without their own `buildCommand`.                                                                                                            |
| `servicePrefix`      | `string`              | `"/_eve_internal/eve"`   | Private route namespace for legacy manual Vercel service configs and non-Vercel production proxying. Named agents derive unique defaults from this prefix.                                                                                       |
| `devServerTimeoutMs` | `number`              | `180000`                 | Maximum time to wait for each eve development server to become available.                                                                                                                                                                        |

For slow cold starts, increase the development timeout:

```ts
export default withEve(nextConfig, {
  devServerTimeoutMs: 300_000,
});
```

## Call the hook

For a single unnamed agent, call [`useEveAgent`](./overview) without `agent` or `host`. For named agents, whether discovered from a workspace or configured explicitly, pass the name:

```tsx
"use client";

import { useEveAgent } from "eve/react";

export function SupportStatus() {
  const support = useEveAgent({ agent: "support" });
  return <p>{support.status}</p>;
}
```

See [Basic chat](./overview#basic-chat-react) for rendering messages and sending turns.

Bind each chat route to its agent, and include the agent identity in durable-session URLs so the UI does not restore a session through the wrong agent route. Remount the chat component when switching agents: the hook reads `agent` when it creates its store.

Requests are same-origin, so the browser sends application cookies to the agent. Each agent must verify those credentials through its own channel authentication policy. For non-cookie schemes, attach the credentials yourself:

```tsx
const agent = useEveAgent({
  headers: async () => ({
    authorization: `Bearer ${await getAccessToken()}`,
  }),
});
```

Configure authorization for every exposed agent before accepting production browser traffic. See [Authenticate browser requests](./overview#authenticate-browser-requests) for the default fail-closed behavior and channel configuration.

## Use the generated Web Chat routes

`eve init --channel-web-nextjs` and `eve add channel/web` generate a chat UI with URL-addressed durable sessions:

- `/` is the initial landing page.
- `/s` opens the conversation layout without creating an eve session. The first message creates the session.
- `/s/[sessionId]` attaches to that durable session, replays its transcript, and follows an in-flight turn.

After the first message is accepted, Web Chat replaces the browser URL with `/s/{sessionId}` without remounting the active stream. Reloading that URL passes the session to `useEveAgent` with `resume: true`, so completed history is replayed and an unfinished response continues streaming. **New chat** navigates to the sessionless `/s` route; it does not reset or delete the prior session, which remains available at its URL.

The generated UI keeps transcript scroll position in browser `sessionStorage`. This is presentation state only and is not written to the eve session.

For a custom Next.js chat route, pass the route session ID explicitly:

```tsx
const agent = useEveAgent({
  initialSession: { sessionId, streamIndex: 0 },
  resume: true,
});
```

See [Resumable sessions](./overview#resumable-sessions) for persistence and replay semantics.

## Dev vs deploy topology

- **Local dev.** `npm run dev` boots the eve dev server next to `next dev` and rewrites the eve routes over to it. The browser only ever talks to the Next.js origin.
- **Vercel.** The web app and the eve runtime deploy as a single project. `withEve()` writes Build Output `services` for eve and `routes` that send `/eve/v1/**` to that service before filesystem routing; the Next.js app itself remains the default app. Vercel assembles authored [schedules](../../schedules) into the project config as Vercel Cron Jobs, including correctly prefixed jobs for named agents, while cron entries owned by the Next.js app are preserved. By default, generated services run the installed eve binary from the agent root, so the agent directory does not need its own `package.json`. When the agent needs its own build step, set `eveBuildCommand`:

  ```ts
  export default withEve(nextConfig, {
    eveBuildCommand: "npm run build:eve",
  });
  ```

- **Local production build.** `next build && next start` serves the eve runtime from its built `.output/server/index.mjs` on a stable local port (`4274`) and proxies the eve routes to it. Run `eve build` first so that output exists. In an `agents/` workspace, build every member from its `agents/<name>/` directory before starting Next.js. Change the port with `EVE_NEXT_PRODUCTION_PORT`:

  ```bash
  export EVE_NEXT_PRODUCTION_PORT=5000
  npm run build && npm start
  ```

- **Non-Vercel hosts.** `withEve()` provides both agent process startup and Next.js proxy rewrites; self-hosters using this path do not need to recreate the browser-facing routing. The Vercel service output is a separate integration, not a self-hosting requirement. By default, `next start` runs each built eve service on its derived loopback port. If your host supervises eve services itself, run each service separately and set `EVE_NEXT_PRODUCTION_ORIGIN` to the origin that serves its private route prefix:

  ```bash
  export EVE_NEXT_PRODUCTION_ORIGIN=https://agent.example.com
  npm run build && npm start
  ```

  This setting disables automatic production agent startup. The destination includes `servicePrefix`: for named agents, the default is `/_eve_internal/eve/<name>/eve/v1/*`. Configure that routing on the destination host, and use the same origin setting when building and starting Next.js.

  If the public routing layer mounts an agent below a path, set `EVE_PUBLIC_ROUTE_PREFIX` in that agent's build and runtime environments so callback URLs use the public path. Process restarts, persistent workflow storage, sandbox configuration, and workflow callback routing remain hosting responsibilities; see [Self-host eve](../deployment/self-hosting).

## What to read next

- [Frontend overview](./overview): the `useEveAgent` API
- [Auth & route protection](../auth-and-route-protection)
- [Deployment](../deployment/overview)
