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

# Overview

> Learn how our Tavus Conversational Video Interface (CVI) Component Library can help you go live in minutes.

## Overview

`@tavus/cvi-ui` is a CLI that copies React components, hooks, styles, and optional server helpers into your application. It is not a hosted widget or a runtime CDN package. After you run `init` and `add ...`, you import the generated files from your own project tree and can edit them like application code.

Use this path when you want Tavus-provided React UI and Daily-powered call state without building every media control yourself. For the fastest no-code UI, use an [iframe embed](/sections/integrations/embedding-cvi#iframe). For fully custom Daily call-object ownership, use the [Daily JS / React path](/sections/integrations/embedding-cvi#react--daily-createcallobject).

<CardGroup cols={2}>
  <Card title="Blocks" icon="layer-group" href="/sections/conversational-video-interface/component-library/blocks">
    Complete layouts such as `Conversation` and `HairCheck`.
  </Card>

  <Card title="Components" icon="puzzle-piece" href="/sections/conversational-video-interface/component-library/components">
    Building blocks such as `CVIProvider`, media controls, captions, chat, and `AudioWave`.
  </Card>

  <Card title="Hooks" icon="code" href="/sections/conversational-video-interface/component-library/hooks">
    React hooks for call lifecycle, media state, participants, captions, chat, and CVI events.
  </Card>

  <Card title="Server" icon="server" href="/sections/conversational-video-interface/component-library/server">
    Server routes and browser helpers that create and end conversations without exposing `TAVUS_API_KEY`.
  </Card>
</CardGroup>

## Mental model

| Piece                           | What it does                                                                                                         | Where to read next                                                                               |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `npx @tavus/cvi-ui@latest init` | Creates `cvi-components.json`, asks about TypeScript, and installs Daily/Jotai dependencies.                         | This page                                                                                        |
| `CVIProvider`                   | React wrapper that provides Daily context to child components and hooks. Put generated CVI UI under this provider.   | [Components](/sections/conversational-video-interface/component-library/components#cvi-provider) |
| `Conversation`                  | React block that renders the Tavus/Daily call UI from a `conversationUrl` and calls `onLeave` when the user leaves.  | [Blocks](/sections/conversational-video-interface/component-library/blocks#conversation-block)   |
| Server helpers                  | Generated server routes keep `TAVUS_API_KEY` server-only, and generated browser helpers call your own backend route. | [Server](/sections/conversational-video-interface/component-library/server)                      |

<Note>
  Generated imports are relative to where the CLI copied files in your app. Examples in these docs use paths such as `./components/cvi/components/conversation`; adjust them if your `cvi-components.json` components path is different.
</Note>

***

## Quick Start

### Prerequisites

Before getting started, ensure you have a React project set up.

Alternatively, you can start from our example project: [CVI UI Haircheck Conversation Example](https://github.com/Tavus-Engineering/tavus-examples/tree/main/examples/cvi-ui-haircheck-conversation) - this example already has the HairCheck and Conversation blocks set up.

### 1. Initialize CVI in Your Project

```bash theme={null}
npx @tavus/cvi-ui@latest init
```

This command:

* Creates `cvi-components.json`, which stores the generated component path and TypeScript preference.
* Prompts for TypeScript preference.
* Installs `@daily-co/daily-react`, `@daily-co/daily-js`, and `jotai`.

### 2. Add CVI Components and Server Helpers

```bash theme={null}
npx @tavus/cvi-ui@latest add conversation
npx @tavus/cvi-ui@latest add tavus-api
```

`add conversation` generates the `Conversation` block and the components/hooks it needs. `add tavus-api` generates a framework-specific backend route plus `lib/tavus-client.ts`, which exports `createTavusConversation(params?)` and `endTavusConversation(id)`.

For Vite projects with a server runtime, use:

```bash theme={null}
npx @tavus/cvi-ui@latest add tavus-api-vite-ssr
```

Plain client-only Vite is unsupported because it would require exposing `TAVUS_API_KEY` in browser JavaScript. Add a server runtime and use `tavus-api-vite-ssr`, or create your own backend route.

### 3. Wrap Your App with the CVI Provider

In your root directory (main.tsx or index.tsx):

```tsx theme={null}
import { CVIProvider } from './components/cvi/components/cvi-provider';

function App() {
  return <CVIProvider>{/* Your app content */}</CVIProvider>;
}
```

### 4. Add a Conversation Component

Learn how to create a conversation URL at [https://docs.tavus.io/api-reference/conversations/create-conversation](https://docs.tavus.io/api-reference/conversations/create-conversation). To create a conversation URL from your app without exposing your `TAVUS_API_KEY` in the browser, use the server helpers in [Server](/sections/conversational-video-interface/component-library/server) (`tavus-api` for Next.js/Remix/TanStack Start, or `tavus-api-vite-ssr` for Vite-with-server).

**Note:** The Conversation component requires a parent container with defined dimensions to display properly.

<Info>
  Ensure your body element has full dimensions (`width: 100%` and `height:
      100%`) in your CSS for proper component display.
</Info>

```tsx theme={null}
import { Conversation } from './components/cvi/components/conversation';

function CVI() {
  const handleLeave = () => {
    // handle leave
  };
  return (
    <div
      style={{
        width: '100%',
        height: '100%',
        maxWidth: '1200px',
        margin: '0 auto',
      }}
    >
      <Conversation
        conversationUrl='YOUR_TAVUS_MEETING_URL'
        onLeave={handleLeave}
      />
    </div>
  );
}
```

## Complete React example

This example assumes you ran:

```bash theme={null}
npx @tavus/cvi-ui@latest init
npx @tavus/cvi-ui@latest add conversation
npx @tavus/cvi-ui@latest add tavus-api
```

Set `TAVUS_API_KEY` only in your server environment. The browser code below calls the generated `createTavusConversation` and `endTavusConversation` helpers; those helpers call your generated `/api/tavus` route.

```tsx theme={null}
import { useState } from 'react';
import { CVIProvider } from './components/cvi/components/cvi-provider';
import { Conversation } from './components/cvi/components/conversation';
import {
  createTavusConversation,
  endTavusConversation,
} from './components/cvi/lib/tavus-client';

type TavusConversation = {
  conversation_id: string;
  conversation_url: string;
};

function TavusCall() {
  const [conversation, setConversation] = useState<TavusConversation | null>(null);
  const [isStarting, setIsStarting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function startConversation() {
    setIsStarting(true);
    setError(null);

    try {
      const nextConversation = await createTavusConversation({
        persona_id: 'pcb7a34da5fe',
        conversation_name: 'CVI UI example',
      });

      setConversation(nextConversation);
    } catch (error) {
      setError(error instanceof Error ? error.message : 'Failed to start conversation');
    } finally {
      setIsStarting(false);
    }
  }

  async function handleLeave() {
    if (conversation) {
      await endTavusConversation(conversation.conversation_id).catch(() => undefined);
    }

    setConversation(null);
  }

  if (!conversation) {
    return (
      <div>
        <button onClick={startConversation} disabled={isStarting}>
          {isStarting ? 'Starting...' : 'Start conversation'}
        </button>
        {error ? <p role="alert">{error}</p> : null}
      </div>
    );
  }

  return (
    <div style={{ width: '100%', height: '640px' }}>
      <Conversation
        conversationUrl={conversation.conversation_url}
        onLeave={handleLeave}
      />
    </div>
  );
}

export default function App() {
  return (
    <CVIProvider>
      <TavusCall />
    </CVIProvider>
  );
}
```

<Warning>
  `Conversation` needs a parent with defined dimensions. Give the parent an explicit height, or ensure the full chain (`html`, `body`, root element, and container) resolves to a real height.
</Warning>

***

## Documentation Sections

* **[Blocks](/sections/conversational-video-interface/component-library/blocks)** – High-level component compositions and layouts
* **[Components](/sections/conversational-video-interface/component-library/components)** – Individual UI components
* **[Hooks](/sections/conversational-video-interface/component-library/hooks)** – Custom React hooks for managing video call state and interactions
* **[Server](/sections/conversational-video-interface/component-library/server)** – Server-side helpers (`tavus-api`, `tavus-api-vite-ssr`) for creating and ending conversations without exposing your API key
