# Prebuilt Components

Prebuilt components are drop-in React components that handle the entire call lifecycle in a single component. They manage client initialization, call joining, the complete meeting or livestream UI, and cleanup when the component is removed. You don't need to set up `StreamVideoClient`, wire up providers, or build any UI yourself.

Use `EmbeddedCall` for video and audio meetings, or `EmbeddedLivestream` for live streaming. Both components only require an API key, call type, call ID, and user identity to render a fully functional experience.

For full control over the UI and call behavior, see the [Quickstart](https://getstream.io/video/docs/react/v2/basics/quickstart/) for manual integration.

## Getting Started

### Installation

```bash
npm install @stream-io/video-react-sdk@beta
```

Import components from `/embedded` and the dedicated stylesheet:

```tsx
import {
  EmbeddedCall,
  EmbeddedLivestream,
} from "@stream-io/video-react-sdk/embedded";
import "@stream-io/video-react-sdk/dist/css/embedded.css";
```

Use `embedded.css` instead of `styles.css` when using prebuilt components.

### Call Creation

The call must exist before the prebuilt component can join it. Because the component manages the client internally, you need to create the call on your server using a [server-side SDK](https://getstream.io/video/docs/api/calls/#creating-calls). The `callType` and `callId` props must match the call you created on the server.

See also:

- [Permissions & Moderation](https://getstream.io/video/docs/react/v2/guides/permissions-and-moderation/) for assigning roles and capabilities
- [Call Types](https://getstream.io/video/docs/react/v2/guides/configuring-call-types/) for configuring permissions per call type

## EmbeddedCall

For video and audio meetings. The `callType` should match a [call type](https://getstream.io/video/docs/react/v2/guides/configuring-call-types/) configured on your dashboard (e.g., `"default"`).

### Lifecycle

1. **Lobby**: Camera/mic preview, device settings, display name.
2. **Joining**: Connects and sets up media streams.
3. **Active Call**: Full meeting UI with all controls.
4. **Feedback**: Star rating (1-5) and optional text feedback.

### Features

- Camera and microphone controls
- Screen sharing
- Reactions
- Recording controls
- Noise cancellation
- Background blur
- Participant sidebar
- Connection status notifications
- Call duration display
- Wake lock

```tsx
import { EmbeddedCall } from "@stream-io/video-react-sdk/embedded";
import "@stream-io/video-react-sdk/dist/css/embedded.css";

export const MyMeeting = () => (
  <EmbeddedCall
    apiKey="YOUR_API_KEY"
    callType="default"
    callId="my-meeting"
    user={{ type: "authenticated", id: "user-1", name: "John" }}
    token="user-token"
  />
);
```

## EmbeddedLivestream

For livestreaming. The component automatically shows either the host or viewer UI based on the user's permissions. Users with the `JOIN_BACKSTAGE` capability see the host UI; everyone else sees the viewer UI. You can configure this through [call type permissions](https://getstream.io/video/docs/react/v2/guides/configuring-call-types/) on the dashboard.

### Lifecycle

| Stage            | Host                                                            | Viewer                                           |
| ---------------- | --------------------------------------------------------------- | ------------------------------------------------ |
| **1. Pre-join**  | Lobby: camera/mic preview, device settings                      | Waiting lobby: countdown timer, auto-join option |
| **2. Connected** | Backstage: prepare before going live                            | _(waits for stream to start)_                    |
| **3. Live**      | Broadcasting: go-live/stop controls, viewer count, elapsed time | Watching: live stream with viewer count          |
| **4. End**       | Stops the stream                                                | Leaves or stream ends                            |
| **5. Feedback**  | Star rating and text feedback                                   | Star rating and text feedback                    |

### Host Features

- Go-live / stop-live controls
- Viewer count and elapsed stream time
- Backstage mode
- Camera, microphone, and screen sharing controls

### Viewer Features

- Countdown timer and auto-join on go-live
- Viewer count

```tsx
import { EmbeddedLivestream } from "@stream-io/video-react-sdk/embedded";
import "@stream-io/video-react-sdk/dist/css/embedded.css";

// Host: requires an authenticated user with JOIN_BACKSTAGE capability
export const HostView = () => (
  <EmbeddedLivestream
    apiKey="YOUR_API_KEY"
    callType="livestream"
    callId="my-stream"
    user={{ type: "authenticated", id: "host-1", name: "Jane" }}
    token="host-token"
  />
);

// Viewer: anonymous users see the viewer UI
export const ViewerView = () => (
  <EmbeddedLivestream
    apiKey="YOUR_API_KEY"
    callType="livestream"
    callId="my-stream"
    user={{ type: "anonymous" }}
  />
);
```

---

## Props

Both components accept the same props:

| Name            | Type                    | Description                                                                                                         | Default        |
| --------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------- | -------------- |
| `apiKey`        | `string`                | Stream API key. **Required.**                                                                                       |                |
| `callType`      | `string`                | [Call type](https://getstream.io/video/docs/react/v2/guides/configuring-call-types/) (e.g., `"default"`, `"livestream"`). **Required.** |                |
| `callId`        | `string`                | Unique call identifier. **Required.**                                                                               |                |
| `user`          | `EmbeddedUser`          | User identity. See [User Authentication](#user-authentication). **Required.**                                       |                |
| `token`         | `string`                | Static auth token. Required for authenticated users when `tokenProvider` is not set.                                | `undefined`    |
| `tokenProvider` | `() => Promise<string>` | Returns a fresh token. Recommended for production.                                                                  | `undefined`    |
| `logLevel`      | `LogLevel`              | Logging level: `"trace"`, `"debug"`, `"info"`, `"warn"`, `"error"`.                                                 | `undefined`    |
| `layout`        | `LayoutOption`          | Participant layout. See [Layout Options](#layout-options).                                                          | `"SpeakerTop"` |
| `theme`         | `CSSProperties`         | CSS variable overrides for theming. See [Styling](#styling).                                                        | `undefined`    |
| `onError`       | `(error: any) => void`  | Error callback.                                                                                                     | `undefined`    |
| `children`      | `ReactNode`             | Content rendered alongside the default UI.                                                                          | `undefined`    |

## User Authentication

The `user` prop supports three authentication modes:

### Authenticated

A registered user in your app. Requires either a `token` or `tokenProvider`.

```tsx
<EmbeddedCall
  apiKey="YOUR_API_KEY"
  callType="default"
  callId="my-meeting"
  user={{ type: "authenticated", id: "user-1", name: "John" }}
  token="user-token"
/>
```

In production, use `tokenProvider` instead so tokens are refreshed automatically:

```tsx
<EmbeddedCall
  apiKey="YOUR_API_KEY"
  callType="default"
  callId="my-meeting"
  user={{ type: "authenticated", id: "user-1", name: "John" }}
  tokenProvider={async () => {
    const res = await fetch("/api/stream-token");
    const data = await res.json();
    return data.token;
  }}
/>
```

### Guest

A temporary user with server-generated credentials. No token needed.

```tsx
<EmbeddedCall
  apiKey="YOUR_API_KEY"
  callType="default"
  callId="my-meeting"
  user={{ type: "guest", id: "guest-1", name: "Visitor" }}
/>
```

### Anonymous

Joins without any identity. Useful for open calls or public livestreams.

```tsx
<EmbeddedCall
  apiKey="YOUR_API_KEY"
  callType="default"
  callId="my-meeting"
  user={{ type: "anonymous" }}
/>
```

## Layout Options

| Layout            | Description                                     |
| ----------------- | ----------------------------------------------- |
| `"PaginatedGrid"` | Equal-sized tiles in a grid, paginated.         |
| `"SpeakerLeft"`   | Active speaker left, others right.              |
| `"SpeakerRight"`  | Active speaker right, others left.              |
| `"SpeakerTop"`    | Active speaker top, others below. **(Default)** |
| `"SpeakerBottom"` | Active speaker bottom, others above.            |

The layout automatically switches to a Speaker view when screen sharing starts.

```tsx
<EmbeddedCall
  apiKey="YOUR_API_KEY"
  callType="default"
  callId="my-meeting"
  user={{ type: "authenticated", id: "user-1", name: "John" }}
  token="user-token"
  layout="PaginatedGrid"
/>
```

## Error Handling

```tsx
<EmbeddedCall
  apiKey="YOUR_API_KEY"
  callType="default"
  callId="my-meeting"
  user={{ type: "authenticated", id: "user-1", name: "John" }}
  token="user-token"
  onError={(error) => {
    console.error("Call error:", error);
  }}
/>
```

`onError` is called when the client fails to initialize, the user cannot join the call, or a media device error occurs.

## Styling

The component expands to fill its parent container. To control the size, set dimensions on the wrapper element:

```tsx
// Full screen
<div style={{ width: "100vw", height: "100vh" }}>
  <EmbeddedCall {/* ...props */} />
</div>
```

### Via the `theme` prop

Pass CSS variables directly through the `theme` prop for per-instance theming:

```tsx
<EmbeddedCall
  apiKey="YOUR_API_KEY"
  callType="default"
  callId="my-meeting"
  user={{ type: "authenticated", id: "user-1", name: "John" }}
  token="user-token"
  theme={{
    "--str-video__primary-color": "#005fff",
    "--str-video__background-color0": "#ffffff",
    "--str-video__background-color1": "#f7f7f8",
    "--str-video__text-color1": "#1c1e22",
    "--str-video__text-color2": "#72767e",
    "--str-video__button-default-base": "#eff0f1",
    "--str-video__button-default-hover": "#e3e4e5",
    "--str-video__icon-default": "#4c535b",
  }}
/>
```

### Via CSS

Override CSS variables on `.str-video` in a stylesheet:

```css
.str-video {
  --str-video__primary-color: #6002ee;
  --str-video__secondary-color: #90ee02;
  --str-video__text-color1: #282b2b;
  --str-video__border-radius-circle: 15px;
}
```

Import SDK styles before your own for easier overrides:

```tsx
import "@stream-io/video-react-sdk/dist/css/embedded.css";
import "./my-styles.css";
```

Use [CSS cascade layers](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers) for finer control:

```css
@import url("@stream-io/video-react-sdk/dist/css/embedded.css")
layer(video-default);

.str-video__call-controls__button {
  padding: 20px;
}
```

All available variables are listed in the [theme variables file](https://github.com/GetStream/stream-video-js/blob/main/packages/styling/src/_global-theme-variables.scss). See the [Theme](https://getstream.io/video/docs/react/v2/ui-components/video-theme/) page for full theming documentation.

## Custom Children

Children are rendered alongside the default UI, not as a replacement:

```tsx
<EmbeddedCall
  apiKey="YOUR_API_KEY"
  callType="default"
  callId="my-meeting"
  user={{ type: "authenticated", id: "user-1", name: "John" }}
  token="user-token"
>
  <MyCustomSidePanel />
</EmbeddedCall>
```

Children have access to all SDK hooks since they render inside the `StreamVideo` and `StreamCall` providers. You can use this to respond to call state changes:

```tsx
import { useEffect } from "react";
import { CallingState, useCallStateHooks } from "@stream-io/video-react-sdk";
import { EmbeddedCall } from "@stream-io/video-react-sdk/embedded";
import "@stream-io/video-react-sdk/dist/css/embedded.css";

const CallStateListener = () => {
  const { useCallCallingState } = useCallStateHooks();
  const callingState = useCallCallingState();

  useEffect(() => {
    if (callingState === CallingState.LEFT) {
      console.log("User has left the call");
    }
  }, [callingState]);

  return null;
};

export const MyApp = () => (
  <EmbeddedCall
    apiKey="YOUR_API_KEY"
    callType="default"
    callId="my-meeting"
    user={{ type: "authenticated", id: "user-1", name: "John" }}
    token="user-token"
  >
    <CallStateListener />
  </EmbeddedCall>
);
```

## Audio Filters

To enable noise cancellation, install the `@stream-io/audio-filters-web` package:

```bash
npm install @stream-io/audio-filters-web@beta
```

The prebuilt components will automatically detect the package and enable or disable noise cancellation based on your [dashboard](https://getstream.io/signin/?product=video) configuration. See the [Noise Cancellation](https://getstream.io/video/docs/react/v2/guides/noise-cancellation/) guide for more details.

---

For the most recent version of this documentation, visit [https://getstream.io/video/docs/react/v2/basics/prebuilt/](https://getstream.io/video/docs/react/v2/basics/prebuilt/).