UNPKG

eve

Version:

Filesystem-first framework for durable backend AI agents that run anywhere.

128 lines (92 loc) 6.43 kB
--- title: "Next.js" description: "Run an eve agent and a Next.js app as one project with withEve." --- `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. If the agent lives somewhere else, point at it with `eveRoot`: ```ts export default withEve(nextConfig, { eveRoot: "../my-agent", }); ``` For multiple agents, 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/*`. ### `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, ...>` | unset | Named eve agents to mount under `/eve/agents/<name>/eve/v1/*`. 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 default eve channel is fail-closed. With no `agent/channels/eve.ts` authored, eve registers `eveChannel({ auth: [vercelOidc(), localDev()] })`: `vercelOidc()` gets the first chance to resolve a Vercel caller, `localDev()` opens the remaining localhost requests, and everything else gets a `401`. To run your app's own auth policy, add `agent/channels/eve.ts`: ```ts title="agent/channels/eve.ts" import { eveChannel } from "eve/channels/eve"; import { localDev, vercelOidc } from "eve/channels/auth"; export default eveChannel({ auth: [vercelOidc(), localDev()] }); ``` For a public demo, use `none()` (also from `eve/channels/auth`) to skip authentication. See [Channels](../../channels/overview) and [Auth & route protection](../auth-and-route-protection). ## 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. 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. 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)