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.
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
npm install @calcom/embed-react
Peer Dependencies
The package requires React 18+ or React 19+:
{
"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:
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:
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
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)
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
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
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
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
// 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:
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:
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 >
);
}
Add a persistent floating button:
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:
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:
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:
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
Use namespaces for multiple embeds
When you have multiple embeds on the same page, always use unique namespaces to prevent conflicts.
Always remove event listeners in the cleanup function to prevent memory leaks.
The getCalApi function is asynchronous. Handle loading states appropriately in your UI.
Ensure the container has appropriate dimensions. The embed will fill its container.
Next Steps
Customization Learn about theme and styling options
JavaScript Snippet Alternative implementation for non-React apps