Open-Source Wikis

/

Cal.com

/

Features

/

Embeds

calcom/cal.com

Embeds

Purpose

Cal.diy's embed product lets external sites place a Cal scheduling experience anywhere — inline on a marketing page, as a modal triggered by a button, or as a floating button. The runtime is the published embed.js bundle from packages/embeds/embed-core; the React wrapper is @calcom/embed-react.

This is a feature view. For the package architecture, see packages/embeds.

Pieces

Piece Where Audience
embed.js runtime packages/embeds/embed-core Any website
React wrapper packages/embeds/embed-react React sites
Snippet packages/embeds/embed-snippet Generates the cal() global
Embed-side SSR apps/web/app/WithEmbedSSR.tsx, apps/web/modules/embed/ The Cal app, when loaded inside an iframe
Embed-aware booking page packages/features/bookings/Booker/ When ?embed=... query is present

Embed handshake

The published bundle communicates with the embedded Cal page via postMessage. The full protocol diagrams are checked into packages/embeds/:

  • embed-handshake.mermaid
  • embed-message-protocol.mermaid
  • inline-embed-lifecycle.mermaid
  • modal-embed-lifecycle.mermaid
  • modal-prerendering-flow.mermaid

These are referenced from each package's README.

How an embed loads

sequenceDiagram
    participant Host as Host site
    participant Snippet
    participant Core as embed-core
    participant Iframe as Cal page (apps/web)
    participant SSR as WithEmbedSSR
    participant Booker as features/bookings/Booker

    Host->>Snippet: <script src="/wikis/cal-com/features/embed.js">
    Snippet->>Host: window.cal = ...
    Host->>Core: cal("init", "user/event")
    Core->>Iframe: insert iframe + handshake
    Iframe->>SSR: identifies as embed
    SSR->>Booker: render embed mode
    Booker-->>Iframe: slot picker
    Iframe-->>Core: postMessage("loaded")
    Core-->>Host: emit "loaded" event

Embed-side SSR

The Next.js app needs to render slightly differently when loaded inside an embed iframe:

  • No app shell or navigation (the host site provides those).
  • Custom theming based on host-passed CSS variables.
  • Shorter / simpler layout components.

apps/web/app/WithEmbedSSR.tsx and apps/web/modules/embed/ handle this conditional rendering. Routes opt in by wrapping their layout/page with WithEmbedSSR.

Pre-rendering

Modal-mode embeds support pre-rendering: embed-core creates a hidden iframe at page load and only reveals it when the user clicks. This is documented in modal-prerendering-flow.mermaid.

Atoms vs embeds

packages/platform/atoms (the React SDK) and packages/embeds/embed-react overlap conceptually. The difference:

  • Embeds are iframe-based and work for any host — minimal coupling, you embed the Cal site itself.
  • Atoms call the v2 REST API directly and render their own UI. Tighter SDK integration but requires a Platform OAuth client.

Both are maintained, with new SDK consumers usually starting with atoms.

Integration points

  • Web appapps/web/app/WithEmbedSSR.tsx, apps/web/modules/embed/ recognize the embed mode at the route level.
  • Booking pipeline — embed-mode bookings post the same data, but the success redirect is replaced with a postMessage event.
  • Cron / scripts — none. Embeds are a pure runtime.

Entry points for modification

  • New embed mode: see packages/embeds.
  • New embed-aware route: wrap with WithEmbedSSR, add the layout exception in apps/web/modules/embed/, and verify with the embed Playwright suite (yarn e2e:embed).

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Embeds – Cal.com wiki | Factory