# Quickstart
URL: /docs/cloud/quickstart

From an empty project to a persisted, reported and titled conversation in the dashboard, and what to check when the first turn does not show up.

> For AI agents: a documentation index is available at [llms.txt](/llms.txt). Use `.md` for canonical markdown pages; `.mdx` is kept as a backwards-compatible alias on supported URL paths.

This guide takes the shortest path: an anonymous session, the AI SDK runtime and the assistant-ui components. The other guides swap the runtime; the cloud side stays the same.

1. ### Create a project

   Sign in at [cloud.assistant-ui.com](https://cloud.assistant-ui.com) and create a project. Copy its **Frontend API URL** from **Settings › General**; it looks like `https://proj-<id>.assistant-api.com`. A new project accepts anonymous sessions from any origin, so nothing else needs to be configured for a first run.

2. ### Configure the environment

   **React**

   ```
   NEXT_PUBLIC_ASSISTANT_BASE_URL=https://proj-<id>.assistant-api.com
   OPENAI_API_KEY=sk-…
   ```

   On Next.js, the React runtimes create an anonymous cloud client from this variable when you pass no `cloud`. Vite, React Router and TanStack Start expose only `VITE_` variables to the browser, so name it `VITE_ASSISTANT_BASE_URL` there.

3. ### Install and wire the runtime

   **React**

   ```bash
   npm install @assistant-ui/react @assistant-ui/ai-sdk ai @ai-sdk/openai
   ```

   ```
   "use client";

   import { AssistantRuntimeProvider } from "@assistant-ui/react";
   import { useChatRuntime } from "@assistant-ui/ai-sdk";
   import { ThreadList } from "@/components/assistant-ui/elements/thread-list.aui";
   import { Thread } from "@/components/assistant-ui/elements/thread.aui";

   export default function ChatPage() {
     const runtime = useChatRuntime();

     return (
       <AssistantRuntimeProvider runtime={runtime}>
         <div className="grid h-dvh grid-cols-[240px_1fr]">
           <ThreadList />
           <Thread />
         </div>
       </AssistantRuntimeProvider>
     );
   }
   ```

   `useChatRuntime()` reads the base URL from the environment on Next.js and posts chat requests to `/api/chat`, the AI SDK route you already have. On Vite, React Router or TanStack Start, create the client once, outside the component, and pass it as `useChatRuntime({ cloud })`:

   ```
   import { AssistantCloud } from "@assistant-ui/react";

   const cloud = new AssistantCloud({
     baseUrl: import.meta.env.VITE_ASSISTANT_BASE_URL,
     anonymous: true,
   });
   ```

4. ### Report model and usage

   The browser cannot see which model answered or how many tokens it used. Add a `messageMetadata` callback to your route so the run report carries them:

   ```
   import { convertToModelMessages, streamText } from "ai";
   import { openai } from "@ai-sdk/openai";

   export async function POST(req: Request) {
     const { messages } = await req.json();
     const model = openai("gpt-6-luna");
     const result = streamText({
       model,
       messages: await convertToModelMessages(messages),
     });

     return result.toUIMessageStreamResponse({
       messageMetadata: ({ part }) => {
         if (part.type === "finish") {
           return { usage: part.totalUsage, finishReason: part.finishReason };
         }
         if (part.type === "finish-step") {
           return { modelId: part.response.modelId, provider: model.provider };
         }
         return undefined;
       },
     });
   }
   ```

5. ### Send a message and look

   Send one message and open the dashboard. This is what the first turn leaves behind, and where to find it:

   | In the dashboard                | What you see                                                                         | Written by                                                                    |
   | ------------------------------- | ------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------- |
   | **Threads**                     | One thread for the anonymous visitor, with the two messages rendered on its page     | The runtime, as the response settles                                          |
   | **Threads**, the thread's title | A short title in place of *Untitled*, as the response starts                         | The cloud, from the first message, streamed back to the runtime's own request |
   | **Runs**                        | One completed run with its duration, time to first token, tokens, model and cost     | The runtime's report, with the model and usage from the route                 |
   | **Engagement**                  | One send, and the thread's satisfaction reading once a second turn or a copy happens | The runtime's events                                                          |
   | **Users**                       | One anonymous user, active this month                                                | The user's first message                                                      |

   The app shows the title as soon as the model writes it; [Thread titles](/docs/cloud/thread-titles) explains how.

## When the first turn does not show up

| What you see                                      | Why                                                                                                                                                                                                                         | What to do                                                                                                                                                                                                                                |
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| No thread appears                                 | No cloud client was created, so the thread list stayed in memory: the environment variable is missing, or the app is not on Next.js and passes no `cloud`; or the browser's origin is refused, so every cloud request fails | Set `NEXT_PUBLIC_ASSISTANT_BASE_URL` and restart the dev server, or on Vite, React Router and TanStack Start pass the client built from `VITE_ASSISTANT_BASE_URL`; check **Settings › Access** and the browser console for a CORS refusal |
| The thread exists but stays Untitled              | The title attempt failed, for instance because the title provider refused the call; the hourly sweep retries it up to three times                                                                                           | Open the thread in the dashboard: the Title row of its Details rail names the error. Fix the provider under **Settings › Thread titles**                                                                                                  |
| The run reads *No model reported* and has no cost | The route did not return `modelId` and `usage` in its metadata                                                                                                                                                              | Add the `messageMetadata` callback from the step above                                                                                                                                                                                    |
| A 402 in the console                              | The project's plan has reached its active user cap for the month                                                                                                                                                            | See [Plans and pricing](/docs/cloud/pricing)                                                                                                                                                                                              |

## Next

- Give users an identity of their own and lock down origins: [Authentication](/docs/cloud/authorization).
- Join your server's spans to the browser's report: [Traces](/docs/cloud/traces).
- Read what every field of a report means: [Run reports](/docs/cloud/run-reports).
- Start from a template instead: [cloud](https://github.com/assistant-ui/assistant-ui/tree/main/templates/cloud) with anonymous sessions, or [cloud-clerk](https://github.com/assistant-ui/assistant-ui/tree/main/templates/cloud-clerk) with Clerk sign in.