> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vendo.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart: Next.js

> Install @vendoai/vendo in a Next.js app, mount the fetch handler under /api/vendo, drop in VendoRoot, and ship a first working agent turn.

## Install

```bash theme={null}
npm install @vendoai/vendo
npx vendo init
```

The init interview scans the app, recommends risk labels, extracts theme and
remix candidates, and proposes the handler and `<VendoRoot>` edits. It shows
each code diff before writing it.

## Mount the server

```ts theme={null}
import { createVendo, nextVendoHandler } from "@vendoai/vendo/server";

const vendo = createVendo({
  model,
  principal: async (request) => {
    const user = await resolveSession(request);
    return user ? { kind: "user", subject: user.id, display: user.name } : null;
  },
});

export const { GET, POST, DELETE } = nextVendoHandler(vendo);
```

Place the catch-all route under `/api/vendo`. `model` and `principal` are the
only required configuration. Returning `null` creates an ephemeral session
whose state does not persist.

## Add the root

```tsx theme={null}
import { VendoRoot } from "@vendoai/vendo/react";

export function Root({ children }: { children: React.ReactNode }) {
  return <VendoRoot>{children}</VendoRoot>;
}
```

Choose headless hooks from `@vendoai/ui` or a ready-made surface from
`@vendoai/ui/chrome`. Every read hook shares a
`{ data, error, isLoading, refresh }` shape with optional polling — see
[Headless hooks](/reference/hooks).

## Add the overlay

`VendoOverlay` from `@vendoai/ui/chrome` is the ready-made agent surface. It
ships a fixed, brand-styled launcher pill in the bottom-right corner and a
dialog panel that is portaled to `document.body`, locks page scroll, marks the
page behind the scrim `inert`, and restores focus to the invoking element on
close.

```tsx theme={null}
import { VendoOverlay } from "@vendoai/ui/chrome";

export function Assistant() {
  return <VendoOverlay />;
}
```

Move the launcher with `launcher="bottom-left"`, or set `launcher="none"` when
your host triggers the overlay itself (for example, from a dock or a Cmd/Ctrl+K
shortcut). Open state is uncontrolled by default and can be seeded with
`defaultOpen`, or fully controlled with `open` and `onOpenChange`.

For programmatic control, pair the component with the `useVendoOverlay` hook
from `@vendoai/ui`. Spread `overlayProps` onto the component and call `open`,
`close`, or `toggle` from your own shortcut or nav button.

```tsx theme={null}
"use client";

import { useEffect } from "react";
import { useVendoOverlay } from "@vendoai/ui";
import { VendoOverlay } from "@vendoai/ui/chrome";

export function Assistant() {
  const overlay = useVendoOverlay();

  useEffect(() => {
    const onKey = (event: KeyboardEvent) => {
      if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
        event.preventDefault();
        overlay.toggle();
      }
    };
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [overlay.toggle]);

  return <VendoOverlay {...overlay.overlayProps} launcher="none" />;
}
```

Closing the overlay hides the panel without discarding the conversation, so
reopening within the same page session restores the prior messages and thread.
To start fresh, call `overlay.newConversation()` from the hook, use the
new-conversation button in the panel header, or bump the `conversationKey`
prop from your own state.

## Send the first turn

Open your conversation surface and ask for a view, such as “Show my overdue
invoices by customer.” The client sends `POST /threads` and reads an AI SDK UI
message stream. App views arrive as `data-vendo-view` parts. Approval metadata
arrives as `data-vendo-approval` parts.

<Note>
  With no policy or judge configured, tool calls auto-run and are audited.
  Shipped chrome displays the unconfigured-policy notice.
</Note>

## Set the trusted origin

Init writes `VENDO_BASE_URL=http://localhost:3000` into `.env.example`.
Copy it into `.env.local` (or your deployment's environment) and set it to
the origin serving your app. Vendo forwards `authorization` and `cookie`
headers to same-origin tool calls only when the request origin matches this
value; without it, present-mode credential forwarding is silently disabled
and same-origin tools run without inbound auth. In production, set it to
your public HTTPS origin.

## Verify

```bash theme={null}
npx vendo doctor
npx vendo sync
```

Doctor checks wiring, probes `/status`, and runs live HTTP probes that
confirm present-mode credentials forward and that `actAs` (if configured)
mints material your host accepts. Sync extracts tools and remix baselines
for build and development flows. See the
[CLI reference](/reference/cli#vendo-doctor-dir) for the probe details.
