Developer docs

Embed booking

Drop MicroCal scheduling into Next.js, React, Vue, or any website. No API key. URLs in these snippets match this deployment.

Quick start

The most accurate snippet is the one on your booking link. These examples use placeholder paths on this origin.

  1. 01

    Open Share on a booking link

    In MicroCal, go to Booking links and choose Share, then Embed. That copy uses your real workspace and meeting slugs.
  2. 02

    Or start from the examples below

    Replace your-workspace and your-meeting with your slugs. The origin is already correct.
  3. 03

    Publish

    Guests book without leaving your page. Paid meetings open Stripe in the top window, then return to confirmation.

Snippets

Pick a stack and a widget type, then copy. Next.js works as a Server Component with next/script.

import Script from "next/script";

export function MicroCalEmbed() {
  return (
    <>
      <div
        className="microcal-inline-widget"
        data-url="https://www.microcalendar.com.au/book/your-workspace/your-meeting/embed"
        style={{ minWidth: 320, height: 700 }}
      />
      <Script src="https://www.microcalendar.com.au/embed.js" strategy="afterInteractive" />
    </>
  );
}

Paste into any App Router page. next/script loads embed.js once, even if you use this on more than one route. Snippets use www.microcalendar.com.au. Replace your-workspace and your-meeting, or copy from Share.

Load embed.js once in Next.js

If you already put Script in the root layout, you only need the widget markup on each page - next/script will not download embed.js twice.

app/layout.tsx

import Script from "next/script";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script src="https://www.microcalendar.com.au/embed.js" strategy="afterInteractive" />
      </body>
    </html>
  );
}

Page events

The iframe posts messages to the parent. Listen if you want to hide a banner, fire analytics, or continue a funnel after a booking.

resize
Content height changed. The widget uses this to avoid nested scrollbars.
view_changed
Guest moved between host, date, details, or confirmation.
scheduled
Booking confirmed. Payload includes guestEmail, startAt, and endAt.

Listen for a booking

window.addEventListener("message", (event) => {
  if (event.data?.source === "microcal" && event.data.event === "scheduled") {
    // Guest just booked. event.data.payload has guestEmail, startAt, endAt.
  }
});