# Choose an integration

Compare the embed script, the iframe, the React components, the React hooks and the server SDK by what guests see, how much you can style, and what your code can react to.

There are five ways to put a clndr.pro booking page on your site. They trade the same two things against each other: how much of the booking UI you own, and how much code you write. The first two show the hosted UI, the one guests see at `www.clndr.pro/{username}/{slug}`. The other three render inside your own app.

|                              | Embed script                                                           | Iframe                               | React components                                                       | React hooks                    | Server SDK / REST                                                         |
| ---------------------------- | ---------------------------------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------- |
| Guest sees                   | clndr.pro's booking UI, inline, in a modal or behind a floating button | clndr.pro's booking UI in a frame    | A booking form rendered by your app                                    | Whatever you build             | Whatever you build                                                        |
| Styling                      | `theme`, `primaryColor`, hide the header                               | Same as the script, via query params | Your own `Button`, `Input`, `Label`… plus class names on every element | All of it                      | All of it                                                                 |
| Key                          | None                                                                   | None                                 | Publishable                                                            | Publishable                    | Secret (server)                                                           |
| You hear about bookings from | `onBookingSuccessful`                                                  | `postMessage` events                 | `onBooked(bookingId)`                                                  | The return value of `create()` | Your own handler; [polling](/tutorials/sync-bookings) for everything else |
| Private pages                | Pass the access code                                                   | Pass the access code (`?c=`)         | Works with the owner's key                                             | Works with the owner's key     | Works with the owner's key                                                |
| Needs                        | One `<script>` tag                                                     | One `<iframe>`                       | React 18+                                                              | React 18+                      | Any server runtime                                                        |

## Embed script

One script tag, then `Clndr.inline(...)`, `Clndr.modal(...)` or `Clndr.floatingButton(...)`. The script creates an iframe, sizes it to its content, and calls you back when a booking goes through. It's the right call for WordPress, Webflow, Squarespace or a static HTML page, and for React apps that want clndr.pro's own UI rather than their own.

You can't change the form's layout or fonts, only the theme and the accent colour. [Embed script](/embed/script) has the full API.

## Iframe

The script's iframe without the script: `https://www.clndr.pro/embed/{username}/{slug}`. Use it where you can't run JavaScript, like a CMS that strips `<script>` tags. You size the frame yourself, or listen for the resize events the page sends. See [Iframe embed](/embed/iframe).

## React components

`@clndr-pro/react` ships `<BookingInline>`, `<BookingForm>` and `<BookingModal>`: the full flow from date picker to confirmation, in your React tree. Pass it your design system's `Button`, `Input`, `Label` and `Card` and it renders with them, so it matches the rest of your app. The flow itself (date input, slot grid, form) is fixed. [Components](/react/components) and [Styling and slots](/react/styling) cover it.

## React hooks

`useBookingPage`, `useAvailableSlots` and `useCreateBooking` give you the data and the booking call, and nothing else. Use them when the flow itself should look different: a month calendar instead of a date input, slots grouped by morning and afternoon, a multi-step dialog. The [shadcn booking widget](/tutorials/shadcn-booking-widget) tutorial builds one end to end. See [Hooks](/react/hooks).

## Server SDK and REST

`@clndr-pro/sdk` (or plain HTTP against `https://www.clndr.pro/api/v1`) with a secret key, from a server action, route handler or backend job. Three reasons to go here:

* **Guest details stay on your server.** The browser posts to your own endpoint, you validate it (add a captcha, check the email against your CRM), and your server books. [Book through a server action](/tutorials/server-actions) shows the pattern.
* **You manage bookings.** Only a secret key can list, confirm and cancel. See [Approve bookings in your admin](/tutorials/approvals-dashboard).
* **You don't run React.** The [plain JavaScript](/tutorials/vanilla-js) tutorial calls the API with `fetch` and a publishable key.

## Private and team pages

On clndr.pro itself, a `private` page asks for an access code and a `team` page needs a signed-in team member. The embed and the iframe go through those same checks. Pass the code with `accessCode` or `?c=`, and expect team pages not to load inside an iframe: browsers don't send clndr.pro's sign-in cookie to a third-party frame.

The API works differently. An API key belongs to the page's owner, so it can read and book every page on that account, private or not. If you render a private page with the React components or the API, your site becomes the gate. That's often what you want (the page is private on clndr.pro because it belongs behind your members' login), but it's your decision to make, and clndr.pro won't make it for you.

## If in doubt

```mermaid title="Which integration?"
flowchart TD
  A{Does the site run React?} -->|No| B{Can it run a script tag?}
  B -->|Yes| S[Embed script]
  B -->|No| I[Iframe]
  A -->|Yes| C{Should the booking UI match the app?}
  C -->|clndr.pro's UI is fine| S
  C -->|Same components, same flow| R[React components]
  C -->|A different flow| H[React hooks]
  A -.-> D{Need to read, approve or cancel bookings?}
  D -->|Yes| K[Server SDK with a secret key]
```

For a Next.js or React app, start with `<BookingInline>` and your own components. It takes ten minutes ([quickstart](/quickstart)), and you can move to the hooks later without changing keys or env vars. Anywhere else, start with the [embed script](/embed/script).

The approaches combine. A common setup is `<BookingInline>` on the marketing site with a publishable key, plus a secret key on the server that copies new bookings into your CRM.
