> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/calcom/cal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# React Component Embed

> Embed Cal.com in React applications using the @calcom/embed-react package

The `@calcom/embed-react` package provides a React component and hooks for seamlessly integrating Cal.com into your React applications with full TypeScript support.

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @calcom/embed-react
  ```

  ```bash yarn theme={null}
  yarn add @calcom/embed-react
  ```

  ```bash pnpm theme={null}
  pnpm add @calcom/embed-react
  ```
</CodeGroup>

### Peer Dependencies

The package requires React 18+ or React 19+:

```json theme={null}
{
  "peerDependencies": {
    "react": "^18.2.0 || ^19.0.0",
    "react-dom": "^18.2.0 || ^19.0.0"
  }
}
```

## Quick Start

### Inline Embed Component

The simplest way to embed Cal.com is using the `Cal` component:

```tsx theme={null}
import Cal from "@calcom/embed-react";

function BookingPage() {
  return (
    <Cal
      calLink="organization/event-type"
      style={{ width: "100%", height: "100%", overflow: "scroll" }}
    />
  );
}
```

### With Configuration

Prefill booking information and customize the appearance:

```tsx theme={null}
import Cal from "@calcom/embed-react";

function BookingPage() {
  return (
    <Cal
      calLink="pro"
      config={{
        name: "John Doe",
        email: "johndoe@gmail.com",
        notes: "Test Meeting",
        guests: ["janedoe@gmail.com"],
        theme: "dark",
        layout: "month_view"
      }}
      style={{ width: "100%", height: "100%", overflow: "scroll" }}
    />
  );
}
```

## Component Props

The `Cal` component accepts the following props:

### CalProps Interface

```typescript theme={null}
type CalProps = {
  calLink: string;                           // Required: Cal.com booking link
  calOrigin?: string;                        // Cal.com origin URL (default: https://cal.com)
  namespace?: string;                        // Namespace for multiple embeds
  config?: PrefillAndIframeAttrsConfig;     // Configuration and prefill data
  initConfig?: {
    debug?: boolean;                         // Enable debug logging
    uiDebug?: boolean;                       // Enable UI debug mode
  };
  embedJsUrl?: string;                       // Custom embed.js URL
} & React.HTMLAttributes<HTMLDivElement>;   // Accepts all div attributes
```

### Configuration Options (config prop)

```typescript theme={null}
type PrefillAndIframeAttrsConfig = {
  // Prefill fields
  name?: string;
  email?: string;
  notes?: string;
  guests?: string[];
  
  // UI Configuration
  theme?: "light" | "dark" | "auto";
  layout?: "month_view" | "week_view" | "column_view";
  "ui.color-scheme"?: string;
  "ui.autoscroll"?: "true" | "false";
  
  // Feature flags
  "flag.coep"?: "true" | "false";
  useSlotsViewOnSmallScreen?: "true" | "false";
  
  // Iframe attributes
  iframeAttrs?: {
    id?: string;
    [key: string]: string;
  };
  
  // Any additional query params
  [key: string]: string | string[] | Record<string, string>;
};
```

## Using getCalApi

For more advanced use cases, use the `getCalApi` function to interact with the Cal API programmatically:

### Basic Usage

```tsx theme={null}
import { useEffect } from "react";
import { getCalApi } from "@calcom/embed-react";

function App() {
  useEffect(() => {
    (async function () {
      const cal = await getCalApi();
      
      cal("inline", {
        elementOrSelector: "#my-cal-inline",
        calLink: "organization/event-type"
      });
    })();
  }, []);
  
  return <div id="my-cal-inline" />;
}
```

### With Namespace

```tsx theme={null}
import { useEffect } from "react";
import { getCalApi } from "@calcom/embed-react";

function App() {
  useEffect(() => {
    (async function () {
      const cal = await getCalApi({ namespace: "booking" });
      
      cal("inline", {
        elementOrSelector: "#my-cal",
        calLink: "organization/event-type"
      });
    })();
  }, []);
  
  return <div id="my-cal" />;
}
```

## Event Handling

Listen to booking events using the event system:

### Type-Safe Event Handling

```tsx theme={null}
import { useEffect } from "react";
import { getCalApi, type EmbedEvent } from "@calcom/embed-react";

function App() {
  useEffect(() => {
    (async function () {
      const cal = await getCalApi({ namespace: "inline" });
      
      // Listen to booking success events
      const bookingSuccessCallback = (e: EmbedEvent<"bookingSuccessfulV2">) => {
        const data = e.detail.data;
        console.log("Booking created:", {
          title: data.title,
          startTime: data.startTime,
          endTime: data.endTime
        });
      };
      
      cal("on", {
        action: "bookingSuccessfulV2",
        callback: bookingSuccessCallback
      });
      
      // Cleanup
      return () => {
        cal("off", {
          action: "bookingSuccessfulV2",
          callback: bookingSuccessCallback
        });
      };
    })();
  }, []);
  
  return <div id="my-cal" />;
}
```

### Available Events

```tsx theme={null}
// Listen to all events
cal("on", {
  action: "*",
  callback: (event) => {
    console.log(event.detail);
  }
});

// Specific events
cal("on", {
  action: "bookingSuccessfulV2",
  callback: (e: EmbedEvent<"bookingSuccessfulV2">) => {
    // Handle successful booking
  }
});

cal("on", {
  action: "bookerReady",
  callback: (e: EmbedEvent<"bookerReady">) => {
    // Handle when booker is ready
  }
});
```

## Customizing UI

Customize the embed appearance dynamically:

```tsx theme={null}
import { useEffect } from "react";
import { getCalApi } from "@calcom/embed-react";

function App() {
  useEffect(() => {
    (async function () {
      const cal = await getCalApi({ namespace: "inline" });
      
      // Apply custom styles
      cal("ui", {
        theme: "dark",
        styles: {
          branding: {
            brandColor: "#000000"
          }
        },
        hideEventTypeDetails: false,
        cssVarsPerTheme: {
          light: {
            "cal-border-booker": "red",
            "cal-border-booker-width": "20px"
          },
          dark: {
            "cal-border-booker": "blue",
            "cal-border-booker-width": "5px"
          }
        }
      });
    })();
  }, []);
  
  return <div id="my-cal" />;
}
```

## Modal Embed

Create a modal embed triggered by a button:

```tsx theme={null}
import { useEffect } from "react";
import { getCalApi } from "@calcom/embed-react";

function App() {
  useEffect(() => {
    (async function () {
      const cal = await getCalApi({ namespace: "modal" });
      
      cal("ui", {
        styles: { 
          branding: { 
            brandColor: "#000000" 
          } 
        },
        hideEventTypeDetails: false
      });
    })();
  }, []);
  
  return (
    <button
      data-cal-namespace="modal"
      data-cal-link="organization/event-type"
      data-cal-config='{"layout":"month_view", "theme":"dark"}'
    >
      Book a meeting
    </button>
  );
}
```

## Floating Button

Add a persistent floating button:

```tsx theme={null}
import { useEffect } from "react";
import { getCalApi } from "@calcom/embed-react";

function App() {
  useEffect(() => {
    (async function () {
      const cal = await getCalApi({ namespace: "floating" });
      
      cal("floatingButton", {
        calLink: "organization/event-type",
        config: {
          theme: "dark"
        }
      });
      
      cal("ui", { 
        styles: { 
          branding: { 
            brandColor: "#000000" 
          } 
        }, 
        hideEventTypeDetails: false 
      });
    })();
  }, []);
  
  return null;
}
```

## Multiple Embeds with Namespaces

Use namespaces to have multiple embeds on the same page:

```tsx theme={null}
import Cal from "@calcom/embed-react";

function BookingPage() {
  return (
    <>
      <Cal
        namespace="embed1"
        calLink="organization/event-type-1"
        config={{ theme: "light" }}
        style={{ width: "100%", height: "600px" }}
      />
      
      <Cal
        namespace="embed2"
        calLink="organization/event-type-2"
        config={{ theme: "dark" }}
        style={{ width: "100%", height: "600px" }}
      />
    </>
  );
}
```

## TypeScript Support

The package includes full TypeScript definitions:

```tsx theme={null}
import type { EmbedEvent, PrefillAndIframeAttrsConfig } from "@calcom/embed-react";

// Type-safe event handling
const handleBooking = (e: EmbedEvent<"bookingSuccessfulV2">) => {
  const { title, startTime, endTime } = e.detail.data;
  // TypeScript knows the exact shape of the data
};

// Type-safe configuration
const config: PrefillAndIframeAttrsConfig = {
  name: "John Doe",
  email: "john@example.com",
  theme: "dark",
  layout: "month_view"
};
```

## Custom Embed URL

For self-hosted instances, specify a custom embed URL:

```tsx theme={null}
import Cal from "@calcom/embed-react";

function BookingPage() {
  return (
    <Cal
      calLink="organization/event-type"
      calOrigin="https://cal.example.com"
      embedJsUrl="https://cal.example.com/embed/embed.js"
    />
  );
}
```

## Best Practices

<AccordionGroup>
  <Accordion title="Use namespaces for multiple embeds">
    When you have multiple embeds on the same page, always use unique namespaces to prevent conflicts.
  </Accordion>

  <Accordion title="Clean up event listeners">
    Always remove event listeners in the cleanup function to prevent memory leaks.
  </Accordion>

  <Accordion title="Handle loading states">
    The `getCalApi` function is asynchronous. Handle loading states appropriately in your UI.
  </Accordion>

  <Accordion title="Responsive container">
    Ensure the container has appropriate dimensions. The embed will fill its container.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Customization" icon="palette" href="/embed/customization">
    Learn about theme and styling options
  </Card>

  <Card title="JavaScript Snippet" icon="js" href="/embed/embed-snippet">
    Alternative implementation for non-React apps
  </Card>
</CardGroup>
