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

# Next.js



`eve/next` ships a Next.js frontend and an eve agent as a single project. Wrap your config with `withEve()` to run both from one dev server and one Vercel deploy. [`useEveAgent`](./overview) finds the mounted routes on its own, so there's no CORS to configure and no URL env vars to keep in sync.

## 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 to mount the agent in.

## 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()` looks for an `agent/` folder inside your Next.js project root. When the project root is an eve workspace with `agents/<name>/` members, it discovers every member and mounts each at `/eve/agents/<name>/eve/v1/*` instead.

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

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

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: "./agents/support",
    billing: {
      root: "./agents/billing",
      buildCommand: "pnpm build:billing-agent",
      servicePrefix: "/_eve_internal/billing",
    },
  },
});
```

Named agents mount under `/eve/agents/<name>/eve/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/agents/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/agents/<name>/eve/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

With `withEve()` in `next.config.ts`, the eve routes are same-origin, so client code can call [`useEveAgent`](./overview) without naming a host. Cookie-based auth (Auth.js or any session cookie) needs no extra wiring, since the browser already sends those cookies on every eve request. For non-cookie schemes, attach the credentials yourself:

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

The browser still needs a production authentication policy. 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
  EVE_NEXT_PRODUCTION_PORT=5000 npm run build && npm start
  ```

* **Non-Vercel hosts.** When the eve service lives on a separate origin, tell Next.js where to find it with `EVE_NEXT_PRODUCTION_ORIGIN`:

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

## What to read next

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


---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)