# TanStack Start

> Mount the realtime avatar proxy in a TanStack Start app: a splat server route on the server, one component in the browser.

- Canonical: https://realtimeavatar.ai/docs/tanstack-start
- Updated: 2026-09-02

Your API key must never reach a browser, so the browser talks to your app and your app talks to us. In Start that is one server route.

## The server half

Mount at `routes/api/realtime-avatar/$.ts`. The trailing `$` is Start's splat segment and it is **load-bearing**: without it the handler only ever sees the mount path itself and answers 404 for every operation — the same trap Next.js's `[...path]` exists to avoid.

**TanStack Start**

```tsx
// routes/api/realtime-avatar/$.ts
import { createFileRoute } from "@tanstack/react-router";
import { realtimeAvatarServerRoute } from "realtime-avatar/tanstack-start";

export const Route = createFileRoute("/api/realtime-avatar/$")({
  server: {
    handlers: realtimeAvatarServerRoute({
      apiKey: process.env.REALTIME_AVATAR_API_KEY!,

      authorize: async ({ request, operation }) => {
        const user = await currentUser(request);
        if (!user) return new Response("Sign in", { status: 401 });
        if (operation === "connect" && !user.credits) {
          return Response.json({ code: "insufficient_credits" }, { status: 402 });
        }
      },

      session: async ({ avatarId }) => ({
        instructions: promptFor(avatarId),
      }),
    }),
  },
});
```

On Cloudflare Workers there is no `process.env`, so pass `apiKey` as a **factory** — `apiKey: () => getEnv().REALTIME_AVATAR_API_KEY` — and it is read per request instead of at module scope.

## The client half

**TanStack Start**

```tsx
import { AvatarCall, createProxyClient } from "realtime-avatar/react";

const client = createProxyClient({ proxyUrl: "/api/realtime-avatar" });

export function Call({ avatarId }: { avatarId: string }) {
  return <AvatarCall client={client} avatarId={avatarId} />;
}
```

## Next

- [Authentication](https://realtimeavatar.ai/docs/authentication) — keys, scopes, and what `authorize` is really gating.
- [Calls](https://realtimeavatar.ai/docs/sessions) — everything the `session` policy can decide.

---

Realtime Avatar — realtime AI avatar API & SDK. Docs: https://realtimeavatar.ai/docs · Agent guide: https://realtimeavatar.ai/llms.txt
