diff --git a/apps/sim/app/(landing)/demo/components/demo-booking/demo-booking.tsx b/apps/sim/app/(landing)/demo/components/demo-booking/demo-booking.tsx
index 4b7a499704d..4597437ae31 100644
--- a/apps/sim/app/(landing)/demo/components/demo-booking/demo-booking.tsx
+++ b/apps/sim/app/(landing)/demo/components/demo-booking/demo-booking.tsx
@@ -3,10 +3,24 @@
import { type CSSProperties, useEffect, useRef, useState } from 'react'
import { chipBorderShadowRing, cn } from '@sim/emcn'
import dynamic from 'next/dynamic'
+import { preconnect } from 'react-dom'
import { DemoForm, type DemoLead } from '@/app/(landing)/demo/components/demo-form'
const importScheduler = () => import('@/app/(landing)/demo/components/demo-scheduler')
+/**
+ * Warm the entire booking path while the visitor fills the form: preconnect to
+ * app.cal.com, then load the scheduler chunk, Cal.com's embed.js, and the
+ * booker iframe assets (via the embed's `preload` instruction). Fired on first
+ * form focus so nothing Cal.com-related competes with initial page load — the
+ * connection handshake overlaps the chunk import, and it all finishes long
+ * before the visitor submits.
+ */
+function preloadScheduler() {
+ preconnect('https://app.cal.com')
+ return importScheduler().then((m) => m.preloadCalEmbed())
+}
+
/**
* Lazy-loaded so the Cal.com embed never enters the initial landing bundle - it
* loads only once a visitor reaches the booking step. `loading: () => null` (no
@@ -75,7 +89,7 @@ export function DemoBooking({ className }: DemoBookingProps) {
void importScheduler()}
+ onFocusCapture={() => void preloadScheduler()}
>
diff --git a/apps/sim/app/(landing)/demo/components/demo-scheduler/demo-scheduler.tsx b/apps/sim/app/(landing)/demo/components/demo-scheduler/demo-scheduler.tsx
index c86d0ea9fbf..c10cc3ea103 100644
--- a/apps/sim/app/(landing)/demo/components/demo-scheduler/demo-scheduler.tsx
+++ b/apps/sim/app/(landing)/demo/components/demo-scheduler/demo-scheduler.tsx
@@ -19,6 +19,30 @@ interface DemoSchedulerProps {
lead: DemoLead
}
+let calEmbedPreloaded = false
+
+/**
+ * Warm the Cal.com embed before the scheduler mounts. Loads `embed.js` and
+ * issues the embed's `preload` instruction, which fetches the booker in a
+ * hidden `?preload=true` iframe so its assets are already cached when the real
+ * embed renders on submit. Without this, nothing Cal.com-related starts
+ * downloading until the visitor presses Continue, which is why the calendar
+ * used to take several seconds to appear. Idempotent — repeat calls no-op
+ * while a warm-up is in flight or done, but a failed embed.js load resets the
+ * flag so a later focus can retry.
+ */
+export function preloadCalEmbed(): void {
+ if (calEmbedPreloaded) return
+ calEmbedPreloaded = true
+ getCalApi({ namespace: CAL_NAMESPACE })
+ .then((cal) => {
+ cal('preload', { calLink: CAL_LINK })
+ })
+ .catch(() => {
+ calEmbedPreloaded = false
+ })
+}
+
/**
* Step 2 of the booking card - the Cal.com scheduler, prefilled from the form's
* {@link DemoLead}. Rendered inside the card chrome owned by {@link DemoBooking}
diff --git a/apps/sim/app/(landing)/demo/components/demo-scheduler/index.ts b/apps/sim/app/(landing)/demo/components/demo-scheduler/index.ts
index 72290c7861f..a280b21282f 100644
--- a/apps/sim/app/(landing)/demo/components/demo-scheduler/index.ts
+++ b/apps/sim/app/(landing)/demo/components/demo-scheduler/index.ts
@@ -1 +1 @@
-export { DemoScheduler } from './demo-scheduler'
+export { DemoScheduler, preloadCalEmbed } from './demo-scheduler'