Frontend Overview
Purpose and Scope
Frontend integration in eve is the browser-facing layer that turns a durable backend agent into a chat or agent UI. The official overview frames the problem in two pieces: the UI needs a way to reach the agent's HTTP routes, and the application needs a stateful hook that can open a session, send user turns, consume streaming output, and project raw events into something renderable. This page explains that architecture so application developers can choose the right integration path before writing UI code.
Sources: docs/guides/frontend/overview.mdx
The main public primitive is useEveAgent(). It is designed for browser chat and agent interfaces, not for scripts or server-only automation. The hook opens a durable session, sends turns to the agent, streams replies back, and stores the client-side state needed by a composer and message list. React is the reference implementation through eve/react, while Vue and Svelte expose the same surface for teams using those frameworks.
Sources: docs/guides/frontend/overview.mdx
Relevant Source Files
docs/guides/frontend/overview.mdx- First-party frontend guide that defines the browser integration model, identifiesuseEveAgent()as the UI hook, shows the basic React chat example, and lists the returned hook state and commands.
Integration Model
A browser UI is a client of the eve channel's HTTP routes. In practice, eve encourages those routes to live on the same origin as the frontend application. Same-origin routing matters because the browser can call paths such as /eve/v1/session without crossing a CORS boundary and without needing a public agent URL in client-side environment variables. The frontend guide names this as the responsibility of the framework integration layer, while the hook focuses on session and stream state.
Sources: docs/guides/frontend/overview.mdx
The framework integration is the first layer. For Next.js, the integration is withEve from eve/next; for Nuxt, it is the eve/nuxt module; for SvelteKit, it is the eveSvelteKit Vite plugin. Each integration mounts eve routes into the web app's origin so the browser and agent can be deployed as one coherent surface. On other stacks, the hook can talk directly to same-origin /eve/v1/* routes, or the application can pass an explicit host.
Sources: docs/guides/frontend/overview.mdx
The hook is the second layer. useEveAgent() owns local session state, streaming state, errors, and composer status. This split keeps deployment and routing concerns out of UI components while keeping UI components free from low-level stream handling. A chat form can render projected messages and disable input during submission or streaming, while the framework integration and eve channel handle how requests reach the backend agent.
Sources: docs/guides/frontend/overview.mdx
Basic React Chat Flow
The basic React flow starts by importing useEveAgent from eve/react in a client component. The component calls the hook, reads agent.data.messages, computes whether the composer should be disabled from agent.status, and calls agent.send({ message }) when the user submits a non-empty text value. This is intentionally small: the application does not manually create sessions, poll for replies, or concatenate stream chunks into assistant messages.
Sources: docs/guides/frontend/overview.mdx
"use client";
import { useEveAgent } from "eve/react";
export function Chat() {
const agent = useEveAgent();
const isBusy = agent.status === "submitted" || agent.status === "streaming";
return (
<form onSubmit={(event) => {
event.preventDefault();
const form = new FormData(event.currentTarget);
const message = String(form.get("message") ?? "").trim();
if (message.length > 0) void agent.send({ message });
}}>
{agent.data.messages.map((message) => (
<article key={message.id}>
<header>{message.role}</header>
{message.parts.map((part, index) =>
part.type === "text" ? <p key={index}>{part.text}</p> : null,
)}
</article>
))}
<input name="message" disabled={isBusy} />
<button disabled={isBusy} type="submit">Send</button>
</form>
);
}The important design detail is that the UI renders projected state rather than the wire protocol directly. The guide describes data.messages as EveMessage[] following the AI SDK UIMessage convention, with message parts such as user text and assistant text. That makes the default state easy to plug into chat-oriented UI primitives, while still allowing advanced clients to drop down to raw events when they need an audit log or a custom projection.
Sources: docs/guides/frontend/overview.mdx
Returned State Reference
useEveAgent() returns both state and commands. Most applications begin with data.messages, status, and send, then add error, stop, or reset as product requirements grow. The session value is a serializable cursor containing session progress, including identifiers such as sessionId, continuationToken, and streamIndex. The events array exposes raw eve stream events for clients that need an authoritative record instead of only the rendered message projection.
Sources: docs/guides/frontend/overview.mdx
| Field | Purpose |
|---|---|
data | Projected UI state from the reducer; by default this includes messages. |
status | Composer lifecycle state: ready, submitted, streaming, or error. |
error | Last thrown Error, when a send or stream operation fails. |
events | Raw eve stream events for the current session. |
session | Serializable cursor with sessionId, continuationToken, and streamIndex. |
send | Sends text or a full turn payload, including multipart messages and human-in-the-loop responses. |
stop | Aborts the active request. |
reset | Clears local events, data, errors, and the local session cursor. |
Treat status as the source of truth for composer availability. The guide's example disables the input and button while the status is submitted or streaming, which prevents overlapping sends in a simple chat UI. More sophisticated interfaces can still render optimistic affordances, but they should make an explicit decision about concurrent user turns because the hook is tracking a durable session and an active stream, not just a local textarea value.
Sources: docs/guides/frontend/overview.mdx
Local Development and Deployment Wiring
In local development, the intended experience is that the frontend app can call the mounted eve routes without extra browser configuration. The same-origin model removes a common class of local setup errors: mismatched ports, missing public URLs, and CORS failures. The frontend overview points developers to the framework-specific pages for step-by-step wiring, because the exact mounting mechanism differs across Next.js, Nuxt, and SvelteKit even though the browser-facing hook surface stays the same.
Sources: docs/guides/frontend/overview.mdx
Deployment follows the same architectural shape. The framework integration should mount the agent routes on the app origin, and useEveAgent() should continue defaulting to those routes from the browser. If the application is not using one of the packaged integrations, the application must either provide compatible same-origin /eve/v1/* routes or configure an explicit host. That choice determines where session creation and stream requests go at runtime.
Sources: docs/guides/frontend/overview.mdx
When to Use the TypeScript SDK Instead
The frontend helpers are optimized for browser UI state. The guide explicitly directs scripts, server-to-server calls, evals, tests, and custom clients to the TypeScript SDK instead. That distinction is useful when deciding where to put logic: a React component should use useEveAgent() when it needs render-ready messages and composer state, while a test runner or backend job should use the lower-level client protocol because it does not need framework UI state.
Sources: docs/guides/frontend/overview.mdx
A practical next step is to pick the framework page that matches your web app, mount the eve routes, then build the smallest chat surface using data.messages, status, and send. Once that path works, add production concerns in layers: route authentication for browser traffic, richer message rendering for non-text parts, persistence or audit logging through events, and custom reset or stop controls for long-running sessions.
Sources: docs/guides/frontend/overview.mdx