---
title: SvelteKit
description: Run an Eve agent and a SvelteKit app as one project with the eveSvelteKit Vite plugin.
---

# SvelteKit



`eve/sveltekit` runs a SvelteKit frontend and an Eve agent as one project instead of two services. The `eveSvelteKit()` Vite plugin puts both on one dev server and one Vercel deploy, and [`useEveAgent`](./use-eve-agent-svelte) finds the mounted routes on its own. 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 SvelteKit app to mount the agent in.

## Register the Vite plugin

Add `eveSvelteKit()` before `sveltekit()`:

```ts title="vite.config.ts"
import { sveltekit } from "@sveltejs/kit/vite";
import { eveSvelteKit } from "eve/sveltekit";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [eveSvelteKit(), sveltekit()],
});
```

The plugin looks for an `agent/` folder in the SvelteKit project root. Pass `eveRoot` when the agent lives elsewhere:

```ts
export default defineConfig({
  plugins: [
    eveSvelteKit({
      eveRoot: "../my-agent",
    }),
    sveltekit(),
  ],
});
```

The plugin accepts only two options, `eveRoot` and `eveBuildCommand`.

## Call the binding

With the plugin in `vite.config.ts`, components call [`useEveAgent`](./use-eve-agent-svelte) from `eve/svelte` and don't pass a host:

```svelte
<script lang="ts">
  import { useEveAgent } from "eve/svelte";

  const agent = useEveAgent();
  let message = $state("");
  let isBusy = $derived(agent.status === "submitted" || agent.status === "streaming");

  async function handleSubmit() {
    const text = message.trim();
    if (!text || isBusy) return;
    message = "";
    await agent.send({ message: text });
  }
</script>

<form onsubmit={(event) => {
  event.preventDefault();
  void handleSubmit();
}}>
  <input bind:value={message} disabled={isBusy} />
  <button type="submit" disabled={isBusy}>Send</button>
</form>
```

The default Eve channel is fail-closed. With no `agent/channels/eve.ts` authored, Eve registers `eveChannel({ auth: [localDev(), vercelOidc()] })`: `localDev()` opens the routes on localhost, `vercelOidc()` admits Vercel OIDC callers in production, and everything else gets a `401`. To set your 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: [localDev(), vercelOidc()] });
```

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 SvelteKit and proxies the Eve routes to it, so the browser only ever hits the SvelteKit origin. `npm run build && npm run preview` behaves the same way: the preview server gets its own Eve route proxy and either reuses the shared Eve server or starts one.

* **Vercel.** The SvelteKit app and the Eve runtime deploy as a single project. The web app is public; the Eve runtime sits behind it on the same origin. Use `eveBuildCommand` for a project-specific agent build:

  ```ts
  export default defineConfig({
    plugins: [
      eveSvelteKit({
        eveBuildCommand: "npm run build:eve",
      }),
      sveltekit(),
    ],
  });
  ```

* **Non-Vercel hosts.** When the Eve service runs on a separate origin, pass `host` directly to `useEveAgent`:

  ```ts
  const agent = useEveAgent({
    host: "https://agent.example.com",
  });
  ```

## What to read next

* [`useEveAgent` (Svelte)](./use-eve-agent-svelte): the binding API
* [Auth & route protection](../auth-and-route-protection)
* [Deployment](../deployment)


---

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)