React Embed

Purpose and Scope

The React embed package is the React-facing wrapper for placing a Cal booking link inside an application UI. Its package description and README both frame the package as a way to embed a Cal link as a React component, which makes it the right entry point when a host application is already built with React rather than plain script tags. The important design point is that this package is not a separate booking engine. It sits on top of the shared embed runtime family, depending on the core and snippet packages that provide the lower-level embedding behavior.

Sources: packages/embeds/embed-react/README.md, packages/embeds/embed-react/package.json, packages/embeds/README.md

Use this package when you want React ergonomics around the same embed system described by the embeds workspace. The workspace README distinguishes the vanilla JavaScript core library, which manages the embed, from the snippet package, which can be installed on any website and automatically fetches the core library. The React package depends on both of those workspace packages, so developers should think of it as a framework adapter over the same runtime rather than a replacement for core behavior such as modal rendering, iframe communication, preloading, prerendering, and supported loader states.

Sources: packages/embeds/embed-react/package.json, packages/embeds/README.md

Relevant Source Files

  • packages/embeds/embed-react/README.md - Introduces cal-react, states that it embeds a Cal link as a React component, and documents local development and test commands.
  • packages/embeds/embed-react/package.json - Defines the package name, public export files, build scripts, test scripts, peer dependencies, and dependencies on the shared embed runtime packages.
  • packages/embeds/README.md - Explains the broader embeds family, including core, snippet, publishing, skeleton loader support, prerendering, preloading, and parent-iframe runtime concepts.

Core Primitives

The main primitive exposed by this page is the React component package named @calcom/embed-react. Its package metadata declares browser-consumable entry points for module and CommonJS consumers, with generated type declarations under the dist output. React itself is intentionally a peer dependency, with support declared for React and React DOM version ranges covering modern React releases. That peer dependency design lets the host application keep ownership of its React runtime while the embed package provides the Cal-specific component implementation and delegates runtime details to shared embed packages.

Sources: packages/embeds/embed-react/package.json

The second primitive is the shared embed core. The embeds README describes core as the vanilla JavaScript library that manages the embed. That wording matters because the React package should not be understood as owning the whole embed lifecycle alone. The core runtime is where the embed architecture is documented: script loading, creation of the global Cal entry point, initialization of custom elements such as modal, floating button, and inline embed elements, and a namespace-based action manager for event handling. React usage should therefore remain compatible with non-React embed behavior.

Sources: packages/embeds/README.md

The third primitive is the snippet package. The embeds README says the snippet is vanilla JavaScript code that can be installed on any website and automatically fetches the core library. The React package lists @calcom/embed-snippet as a dependency alongside @calcom/embed-core, which signals that React integration participates in the same loading and bootstrap assumptions as the website snippet path. When troubleshooting, do not isolate React first; also consider whether the core library URL, web app URL, and shared embed bootstrap path are correct for the self-hosted or hosted environment.

Sources: packages/embeds/embed-react/package.json, packages/embeds/README.md

System-to-Code Mapping

At the package boundary, @calcom/embed-react publishes only built distribution files. The package metadata points main consumers to a UMD bundle, module consumers to an ES module file, and TypeScript users to emitted declaration files. Its exports map exposes the same package root with separate type, import, and require targets. That means application code should import from the package root rather than reaching into source or dist internals. The package also marks side effects as false, which allows bundlers to optimize unused imports when the component is not referenced.

Sources: packages/embeds/embed-react/package.json

Development and publishing are intentionally separated. For local work, the README tells contributors to run a hot reloading server, while the package script implements that server with Vite on port 3101 and opens the browser. For website integration work, the README adds an explicit reminder to run the build after every change. That reminder is practical: the website path may consume built files rather than the live TypeScript or JSX source, so a green dev server alone does not prove that the package output consumed elsewhere in the monorepo has been regenerated.

Sources: packages/embeds/embed-react/README.md, packages/embeds/embed-react/package.json

The package-level build pipeline removes the previous dist directory, runs Vite, copies the generated ES file to an .mjs name, and emits TypeScript declarations into dist. The prepack workflow then runs the repository lint target for the React embed package, builds with publish-oriented environment variables, and executes packaged tests. Those details are important for maintainers because a change can pass local interaction testing but still fail when consumed as an installed package if generated declarations, module filenames, or packaged test assumptions are out of sync.

Sources: packages/embeds/embed-react/package.json

Development Workflow

A typical local workflow starts inside the embed React package by running the documented development command. That launches the Vite server configured in the package scripts. If the change affects how the embed appears when used by the Cal web application, follow the README guidance and rebuild after the change so the downstream website consumer sees updated distribution output. The repository-level workspace scripts also expose embed-related commands, but the React package provides its own focused scripts for development, preview, linting, type checking, Playwright tests, packaged tests, and cleanup.

Sources: packages/embeds/embed-react/README.md, packages/embeds/embed-react/package.json

yarn dev
yarn build
yarn embed-tests-quick --update-snapshots

Testing has two layers in the visible package metadata. The README highlights the quick embed test command that updates snapshots and notes that snapshots are not currently treated as the main concern. The package scripts implement full Playwright-based embed tests, a quick mode using an environment flag, a CI snapshot update command, and packaged tests that type-check the packaged test project before running tests in a packaged embed mode. That separation helps catch both browser-level behavior and installation-consumer behavior, especially around exports, declarations, and bundled output.

Sources: packages/embeds/embed-react/README.md, packages/embeds/embed-react/package.json

The TODO notes in the README are useful signals for contributors. They say Playwright coverage still needs clearer ownership because embed-core already has tests, and the React package may only need to verify that the core API is called appropriately. The notes also call out distribution developer-experience issues: serving unbuilt JSX would be nicer, but webpack loaders do not automatically process node_modules, and TypeScript consumers in VS Code may jump to declaration files instead of function definitions. These are not installation blockers, but they are constraints to respect when changing build output.

Sources: packages/embeds/embed-react/README.md

Runtime Relationship to Shared Embeds

The shared embeds README describes runtime behavior that React users inherit. The embed architecture initializes through a loaded script, creates a global Cal object, registers custom elements for modal, floating button, and inline modes, and uses namespace-based actions. It also documents parent-to-iframe communication through a message-oriented interface. A React component can make this flow feel declarative, but the operational behavior remains an iframe-based embed managed by the shared runtime. That distinction explains why environment URLs and embed library publishing settings matter even when application code only renders a component.

Sources: packages/embeds/README.md, packages/embeds/embed-react/package.json

Loader and performance behavior also comes from the shared embed system. The embeds README says the skeleton loader is available for supported page types, including booking slots pages and partially supported booking form pages, while profile pages are not listed as supported. It also distinguishes preloading from prerendering: preloading warms static assets in an iframe, while prerendering continues on the preloaded iframe so the user books inside it. React integrations should preserve those runtime semantics instead of duplicating them in component state or assuming every page type has the same loader experience.

Sources: packages/embeds/README.md

API and Package Reference

The package reference is compact but important for consumers. The package name is @calcom/embed-react, the package version in the supplied metadata is 1.5.3, and the package description is Embed Cal Link as a React Component. The public package root exports types from the generated declaration path, ES module imports from the generated .mjs bundle, and CommonJS requires from the UMD bundle. The package lists only dist in its published files, so source-level imports should not be treated as stable public API.

Sources: packages/embeds/embed-react/package.json

Key scripts are organized by task. Use dev for the Vite hot reloading server, build for distribution generation and declaration emission, preview for Vite preview, type-check or type-check:ci for TypeScript validation, lint for Biome linting over source, embed-tests for Playwright tests, embed-tests-quick for quick Playwright mode, packaged:tests for packaged consumption checks, prepack for publish readiness, and clean to remove generated and dependency directories. The withEmbedPublishEnv script supplies the hosted embed library and web app URLs used during publish-oriented builds.

Sources: packages/embeds/embed-react/package.json

Next Steps

If you are adding a React embed feature, first decide whether the behavior belongs in the React wrapper or in embed-core. The package README already cautions that tests may only need to verify appropriate core API calls, which is a strong hint to keep shared runtime behavior centralized. After implementation, run the focused package commands, rebuild before testing website usage, and run packaged tests before publishing-sensitive changes. For broader context, read the embeds overview for core and snippet roles, then review the loader and publishing notes before changing output formats or release workflows.

Sources: packages/embeds/embed-react/README.md, packages/embeds/embed-react/package.json, packages/embeds/README.md