--- title: "Deploy to any runtime" icon: "lucide/Server" description: Deploy the CopilotKit runtime on any backend framework — Node.js, Express, Hono, Bun, Deno, Cloudflare Workers, and more. --- The CopilotKit runtime is **framework-agnostic**. At its core, it's a pure Fetch handler — a function that takes a `Request` and returns a `Response`. This means it runs natively on any platform that supports the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), and thin adapters are provided for Node.js-based frameworks like Express and Hono. ## Quick Overview | Runtime | Import Path | Key Function | |---------|------------|--------------| | **Fetch-native** (Bun, Deno, CF Workers, Next.js App Router) | `@copilotkit/runtime/v2` | `createCopilotRuntimeHandler` | | **Node.js HTTP** | `@copilotkit/runtime/v2/node` | `createCopilotNodeHandler` / `createCopilotNodeListener` | | **Express** | `@copilotkit/runtime/v2/express` | `createCopilotExpressHandler` | | **Hono** | `@copilotkit/runtime/v2/hono` | `createCopilotHonoHandler` | ## Multi-Route vs Single-Route The runtime supports two endpoint modes: - **Multi-route** (default) — exposes individual URL endpoints: - `GET {basePath}/info` - `POST {basePath}/agent/:agentId/run` - `POST {basePath}/agent/:agentId/connect` - `POST {basePath}/agent/:agentId/stop/:threadId` - `POST {basePath}/transcribe` - **Single-route** — a single `POST {basePath}` endpoint that accepts a JSON envelope: ```json { "method": "agent/run", "params": { "agentId": "default" }, "body": { ... } } ``` Single-route mode is useful when your platform only allows a single route handler (e.g. a single serverless function), or when you prefer a simpler URL structure. ## Fetch-Native Runtimes If your platform supports the Fetch API natively (Bun, Deno, Cloudflare Workers, etc.), you can use `createCopilotRuntimeHandler` directly — no adapter needed. ```ts import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; // 1. Create the runtime with your agent(s) const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // 2. Create a Fetch handler — takes Request, returns Response const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", cors: true, }); // 3. Serve it (Bun example — works the same with Deno.serve, CF Workers, etc.) Bun.serve({ fetch: handler, port: 4000 }); ``` For framework-specific examples, see the sections below. ## Bun ```ts title="server.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; // Configure the runtime with your agent(s) const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // Create a Fetch handler with multi-route endpoints (GET /info, POST /agent/:id/run, etc.) const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", cors: true, }); // Bun natively supports Fetch handlers Bun.serve({ fetch: handler, port: 4000 }); ``` ```ts title="server.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // Single-route mode: one POST endpoint that dispatches via JSON envelope const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", mode: "single-route", cors: true, }); Bun.serve({ fetch: handler, port: 4000 }); ``` ```ts title="server.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const copilotHandler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", cors: true, }); Bun.serve({ port: 4000, fetch(request) { const url = new URL(request.url); // Route CopilotKit requests to the handler if (url.pathname.startsWith("/api/copilotkit")) { return copilotHandler(request); } // Your other routes if (url.pathname === "/health") { return Response.json({ status: "healthy" }); } return Response.json({ status: "ok" }); }, }); ``` ## Deno ```ts title="server.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", cors: true, }); // Deno.serve natively accepts a Fetch handler Deno.serve({ port: 4000 }, handler); ``` ```ts title="server.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // Single-route mode: one POST endpoint that dispatches via JSON envelope const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", mode: "single-route", cors: true, }); Deno.serve({ port: 4000 }, handler); ``` ```ts title="server.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const copilotHandler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", cors: true, }); Deno.serve({ port: 4000 }, (request) => { const url = new URL(request.url); // Route CopilotKit requests to the handler if (url.pathname.startsWith("/api/copilotkit")) { return copilotHandler(request); } // Your other routes if (url.pathname === "/health") { return Response.json({ status: "healthy" }); } return Response.json({ status: "ok" }); }); ``` ## Cloudflare Workers ```ts title="src/index.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; export interface Env { OPENAI_API_KEY: string; } export default { async fetch(request: Request, env: Env): Promise { const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // Workers use the Fetch API natively — handler plugs in directly const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", cors: true, }); return handler(request); }, }; ``` ```ts title="src/index.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; export interface Env { OPENAI_API_KEY: string; } export default { async fetch(request: Request, env: Env): Promise { const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // Single-route: one POST endpoint with JSON envelope dispatch const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", mode: "single-route", cors: true, }); return handler(request); }, }; ``` ```ts title="src/index.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; export interface Env { OPENAI_API_KEY: string; } export default { async fetch(request: Request, env: Env): Promise { const url = new URL(request.url); // Route CopilotKit requests to the handler if (url.pathname.startsWith("/api/copilotkit")) { const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", cors: true, }); return handler(request); } // Your other routes if (url.pathname === "/health") { return Response.json({ status: "healthy" }); } return Response.json({ status: "ok" }); }, }; ``` ## Next.js App Router ```ts title="app/api/copilotkit/[...path]/route.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", }); // Export as both GET and POST to handle all CopilotKit routes export { handler as GET, handler as POST }; ``` ```ts title="app/api/copilotkit/route.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // Single-route: only POST needed, no catch-all [...path] required const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", mode: "single-route", }); export { handler as POST }; ``` In single-route mode, no `[...path]` catch-all is needed — everything goes through a single `POST /api/copilotkit`. No `cors: true` needed for Next.js — same-origin requests don't require CORS headers. ## React Router (Framework Mode) React Router v7 in framework mode uses file-based routing with Fetch API handlers — the CopilotKit handler works directly as a resource route. ```ts title="app/routes/api.copilotkit.$.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; import type { Route } from "./+types/api.copilotkit.$"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", }); // loader handles GET requests (e.g. /info) export function loader({ request }: Route.LoaderArgs) { return handler(request); } // action handles POST requests (e.g. /agent/:id/run) export function action({ request }: Route.ActionArgs) { return handler(request); } ``` The `$` splat segment in the filename (`api.copilotkit.$.ts`) captures all subpaths under `/api/copilotkit/`, allowing the CopilotKit router to handle `/info`, `/agent/:id/run`, etc. ```ts title="app/routes/api.copilotkit.ts" import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; import type { Route } from "./+types/api.copilotkit"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // Single-route: only action (POST) needed, no splat segment required const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", mode: "single-route", }); export function action({ request }: Route.ActionArgs) { return handler(request); } ``` In single-route mode, no `$` splat is needed — the filename is just `api.copilotkit.ts` and all dispatch happens via the JSON envelope. ## TanStack Start TanStack Start uses API routes that receive standard `Request` objects and return `Response` objects. ```ts title="app/routes/api/copilotkit/$.ts" import { createAPIFileRoute } from "@tanstack/react-start/api"; import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", }); // The $ splat matches all subpaths — GET for /info, POST for /agent/:id/run, etc. export const APIRoute = createAPIFileRoute("/api/copilotkit/$")({ GET: ({ request }) => handler(request), POST: ({ request }) => handler(request), }); ``` The `$` in the filename is TanStack Start's splat parameter, matching all subpaths under `/api/copilotkit/`. ```ts title="app/routes/api/copilotkit.ts" import { createAPIFileRoute } from "@tanstack/react-start/api"; import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // Single-route: only POST needed, no $ splat required const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", mode: "single-route", }); export const APIRoute = createAPIFileRoute("/api/copilotkit")({ POST: ({ request }) => handler(request), }); ``` In single-route mode, no `$` splat is needed — the file is `copilotkit.ts` (not `$.ts`) and only `POST` is required. ## Node.js HTTP For vanilla Node.js HTTP servers, use the `/node` subpath which bridges Fetch to Node's `IncomingMessage`/`ServerResponse`. ```ts title="server.ts" import { createServer } from "node:http"; import { CopilotRuntime, BuiltInAgent } from "@copilotkit/runtime/v2"; import { createCopilotNodeListener } from "@copilotkit/runtime/v2/node"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // createCopilotNodeListener returns a Node request listener (req, res) => void // that bridges to the Fetch handler internally const listener = createCopilotNodeListener({ runtime, basePath: "/api/copilotkit", cors: true, }); createServer(listener).listen(4000, () => { console.log("Listening at http://localhost:4000/api/copilotkit"); }); ``` ```ts title="server.ts" import { createServer } from "node:http"; import { CopilotRuntime, BuiltInAgent } from "@copilotkit/runtime/v2"; import { createCopilotNodeListener } from "@copilotkit/runtime/v2/node"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const listener = createCopilotNodeListener({ runtime, basePath: "/api/copilotkit", mode: "single-route", cors: true, }); createServer(listener).listen(4000, () => { console.log("Listening at http://localhost:4000/api/copilotkit"); }); ``` ```ts title="server.ts" import { createServer } from "node:http"; import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; import { createCopilotNodeHandler } from "@copilotkit/runtime/v2/node"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // 1. Create the Fetch handler const copilotHandler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", cors: true, }); // 2. Wrap it as a Node (req, res) handler const copilotNodeHandler = createCopilotNodeHandler(copilotHandler); // 3. Use it in your existing server with manual routing const server = createServer(async (req, res) => { const url = new URL(req.url ?? "/", `http://${req.headers.host}`); // Route CopilotKit requests to the handler if (url.pathname.startsWith("/api/copilotkit")) { return copilotNodeHandler(req, res); } // Your other routes if (url.pathname === "/health") { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ status: "healthy" })); return; } res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ status: "ok" })); }); server.listen(4000, () => { console.log("Listening at http://localhost:4000"); }); ``` ## Express The Express adapter returns an Express `Router` that you mount with `app.use()`. ``` npm install express cors ``` ```ts title="server.ts" import express from "express"; import { CopilotRuntime, BuiltInAgent } from "@copilotkit/runtime/v2"; import { createCopilotExpressHandler } from "@copilotkit/runtime/v2/express"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const app = express(); // Mount the CopilotKit router — creates Express routes under /api/copilotkit app.use( createCopilotExpressHandler({ runtime, basePath: "/api/copilotkit", cors: true, }), ); app.listen(4000, () => { console.log("Listening at http://localhost:4000/api/copilotkit"); }); ``` ```ts title="server.ts" import express from "express"; import { CopilotRuntime, BuiltInAgent } from "@copilotkit/runtime/v2"; import { createCopilotExpressHandler } from "@copilotkit/runtime/v2/express"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const app = express(); // Single-route: one POST endpoint that dispatches via JSON envelope app.use( createCopilotExpressHandler({ runtime, basePath: "/api/copilotkit", mode: "single-route", cors: true, }), ); app.listen(4000, () => { console.log("Listening at http://localhost:4000/api/copilotkit"); }); ``` ```ts title="server.ts" import express from "express"; import { CopilotRuntime, BuiltInAgent } from "@copilotkit/runtime/v2"; import { createCopilotExpressHandler } from "@copilotkit/runtime/v2/express"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const app = express(); // Your existing routes app.get("/", (req, res) => { res.json({ status: "ok" }); }); app.get("/health", (req, res) => { res.json({ status: "healthy" }); }); // Mount CopilotKit alongside your existing routes app.use( createCopilotExpressHandler({ runtime, basePath: "/api/copilotkit", cors: true, }), ); app.listen(4000, () => { console.log("Listening at http://localhost:4000"); }); ``` ### Express Options | Option | Type | Default | Description | |--------|------|---------|-------------| | `runtime` | `CopilotRuntime` | *required* | The runtime instance | | `basePath` | `string` | *required* | URL path prefix (e.g. `"/api/copilotkit"`) | | `mode` | `"multi-route"` \| `"single-route"` | `"multi-route"` | Multi-route exposes individual endpoints; single-route uses a JSON envelope | | `cors` | `boolean` \| `CorsOptions` | `false` | CORS configuration. `true` for permissive defaults, or pass a `cors` options object | | `hooks` | `CopilotRuntimeHooks` | — | [Lifecycle hooks](#lifecycle-hooks) | The Express adapter is compatible with `express.json()` body parsing. If you have `app.use(express.json())` before the CopilotKit router, the adapter will detect the pre-parsed body and handle it correctly. ## Hono The Hono adapter returns a Hono app that you mount with `app.route()`. ``` npm install hono ``` ```ts title="server.ts" import { serve } from "@hono/node-server"; import { CopilotRuntime, BuiltInAgent } from "@copilotkit/runtime/v2"; import { createCopilotHonoHandler } from "@copilotkit/runtime/v2/hono"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // Returns a Hono app with CopilotKit routes mounted at basePath const endpoint = createCopilotHonoHandler({ runtime, basePath: "/api/copilotkit", }); // Serve the Hono app directly serve({ fetch: endpoint.fetch, port: 4000 }, () => { console.log("Listening at http://localhost:4000/api/copilotkit"); }); ``` ```ts title="server.ts" import { serve } from "@hono/node-server"; import { CopilotRuntime, BuiltInAgent } from "@copilotkit/runtime/v2"; import { createCopilotHonoHandler } from "@copilotkit/runtime/v2/hono"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // Single-route: one POST endpoint that dispatches via JSON envelope const endpoint = createCopilotHonoHandler({ runtime, basePath: "/api/copilotkit", mode: "single-route", }); serve({ fetch: endpoint.fetch, port: 4000 }, () => { console.log("Listening at http://localhost:4000/api/copilotkit"); }); ``` ```ts title="server.ts" import { Hono } from "hono"; import { serve } from "@hono/node-server"; import { CopilotRuntime, BuiltInAgent } from "@copilotkit/runtime/v2"; import { createCopilotHonoHandler } from "@copilotkit/runtime/v2/hono"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const app = new Hono(); // Your existing routes app.get("/", (c) => c.json({ status: "ok" })); app.get("/health", (c) => c.json({ status: "healthy" })); // Mount CopilotKit as a sub-app via app.route() app.route("/", createCopilotHonoHandler({ runtime, basePath: "/api/copilotkit" })); serve({ fetch: app.fetch, port: 4000 }, () => { console.log("Listening at http://localhost:4000"); }); ``` ## Elysia (Bun) Elysia runs on Bun and supports the Fetch API natively, so you use `createCopilotRuntimeHandler` directly. ``` bun add elysia ``` ```ts title="server.ts" import { Elysia } from "elysia"; import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // Create a Fetch handler — Elysia passes the raw Request through const handler = createCopilotRuntimeHandler({ runtime, cors: true }); new Elysia() .all("/api/copilotkit/*", ({ request }) => handler(request)) .listen(4000); ``` ```ts title="server.ts" import { Elysia } from "elysia"; import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); // Single-route: one POST endpoint, no wildcard needed const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", mode: "single-route", cors: true, }); new Elysia() .post("/api/copilotkit", ({ request }) => handler(request)) .listen(4000); ``` ```ts title="server.ts" import { Elysia } from "elysia"; import { CopilotRuntime, createCopilotRuntimeHandler, BuiltInAgent } from "@copilotkit/runtime/v2"; const runtime = new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: "openai/gpt-4o-mini" }), }, }); const handler = createCopilotRuntimeHandler({ runtime, cors: true }); new Elysia() // Your existing routes .get("/", () => ({ status: "ok" })) .get("/health", () => ({ status: "healthy" })) // Mount CopilotKit .all("/api/copilotkit/*", ({ request }) => handler(request)) .listen(4000); ``` ## Lifecycle Hooks All adapters support lifecycle hooks for cross-cutting concerns like authentication, logging, and response modification. ```ts const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", hooks: { // Before routing — auth, correlation IDs onRequest: async ({ request, path, runtime }) => { const token = request.headers.get("authorization"); if (!token) { throw new Response("Unauthorized", { status: 401 }); } }, // After routing — route-specific authorization onBeforeHandler: async ({ request, route }) => { console.log(`Handling ${route.method} for agent ${route.agentId}`); }, // After handler — modify response headers onResponse: async ({ response, request }) => { const headers = new Headers(response.headers); headers.set("x-request-id", crypto.randomUUID()); return new Response(response.body, { status: response.status, headers, }); }, // On error — custom error responses onError: async ({ error, request }) => { console.error("Handler error:", error); }, }, }); ``` | Hook | When | Can modify | |------|------|------------| | `onRequest` | Before routing | Throw `Response` to short-circuit | | `onBeforeHandler` | After routing, before handler | Access `route` info (method, agentId, threadId) | | `onResponse` | After handler | Return a new `Response` to replace it | | `onError` | On unhandled error | Log or produce a custom error response | ## CORS Configuration ### Fetch-native runtimes Pass `cors: true` for permissive defaults (`Access-Control-Allow-Origin: *`), or provide a config object: ```ts const handler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", cors: { origin: "https://myapp.com", credentials: true, }, }); ``` ### Express Pass `cors: true` for permissive defaults, or pass a [cors](https://www.npmjs.com/package/cors) options object: ```ts createCopilotExpressHandler({ runtime, basePath: "/api/copilotkit", cors: { origin: "https://myapp.com", credentials: true, }, }); ``` ### Hono Pass a `cors` config with explicit origin: ```ts createCopilotHonoHandler({ runtime, basePath: "/api/copilotkit", cors: { origin: "https://myapp.com", credentials: true, }, }); ``` When using `credentials: true`, you must specify an explicit origin — wildcard (`*`) is not allowed by the CORS spec. ## Connecting Your Frontend Once your runtime is running, point your frontend at it: ```tsx ``` For same-origin deployments (e.g. Next.js, React Router, TanStack Start), use a relative path: ```tsx ```