Skip to content

Commit 2eb01db

Browse files
committed
fix(demo): preload the Cal.com booking embed while the visitor fills the form
The embed script, booker iframe, and its assets only started downloading after the visitor pressed Continue, so the calendar took several seconds to appear. Warm the whole path on first form focus via the embed's documented preload instruction (hidden ?preload=true iframe caches the booker assets) plus a preconnect to app.cal.com. Nothing Cal.com-related loads at initial page load, so Lighthouse/LCP are untouched.
1 parent 0cc6ed6 commit 2eb01db

3 files changed

Lines changed: 31 additions & 2 deletions

File tree

apps/sim/app/(landing)/demo/components/demo-booking/demo-booking.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,19 @@
33
import { type CSSProperties, useEffect, useRef, useState } from 'react'
44
import { chipBorderShadowRing, cn } from '@sim/emcn'
55
import dynamic from 'next/dynamic'
6+
import { preconnect } from 'react-dom'
67
import { DemoForm, type DemoLead } from '@/app/(landing)/demo/components/demo-form'
78

89
const importScheduler = () => import('@/app/(landing)/demo/components/demo-scheduler')
910

11+
/**
12+
* Warm the entire booking path while the visitor fills the form: the scheduler
13+
* chunk, Cal.com's embed.js, and the booker iframe assets (via the embed's
14+
* `preload` instruction). Fired on first form focus so none of it competes
15+
* with initial page load, and finished long before the visitor submits.
16+
*/
17+
const preloadScheduler = () => importScheduler().then((m) => m.preloadCalEmbed())
18+
1019
/**
1120
* Lazy-loaded so the Cal.com embed never enters the initial landing bundle - it
1221
* loads only once a visitor reaches the booking step. `loading: () => null` (no
@@ -42,6 +51,8 @@ interface DemoBookingProps {
4251
* hides/shows.
4352
*/
4453
export function DemoBooking({ className }: DemoBookingProps) {
54+
preconnect('https://app.cal.com')
55+
4556
const [lead, setLead] = useState<DemoLead | null>(null)
4657
const [formHeight, setFormHeight] = useState<number>()
4758
const formRef = useRef<HTMLDivElement>(null)
@@ -75,7 +86,7 @@ export function DemoBooking({ className }: DemoBookingProps) {
7586
<div
7687
className='w-full min-w-0 shrink-0'
7788
inert={showScheduler}
78-
onFocusCapture={() => void importScheduler()}
89+
onFocusCapture={() => void preloadScheduler()}
7990
>
8091
<div ref={formRef} className='p-6 max-sm:p-5'>
8192
<DemoForm onComplete={setLead} />

apps/sim/app/(landing)/demo/components/demo-scheduler/demo-scheduler.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,24 @@ interface DemoSchedulerProps {
1919
lead: DemoLead
2020
}
2121

22+
let calEmbedPreloaded = false
23+
24+
/**
25+
* Warm the Cal.com embed before the scheduler mounts. Loads `embed.js` and
26+
* issues the embed's `preload` instruction, which fetches the booker in a
27+
* hidden `?preload=true` iframe so its assets are already cached when the real
28+
* embed renders on submit. Without this, nothing Cal.com-related starts
29+
* downloading until the visitor presses Continue, which is why the calendar
30+
* used to take several seconds to appear. Idempotent — repeat calls no-op.
31+
*/
32+
export function preloadCalEmbed(): void {
33+
if (calEmbedPreloaded) return
34+
calEmbedPreloaded = true
35+
getCalApi({ namespace: CAL_NAMESPACE }).then((cal) => {
36+
cal('preload', { calLink: CAL_LINK })
37+
})
38+
}
39+
2240
/**
2341
* Step 2 of the booking card - the Cal.com scheduler, prefilled from the form's
2442
* {@link DemoLead}. Rendered inside the card chrome owned by {@link DemoBooking}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export { DemoScheduler } from './demo-scheduler'
1+
export { DemoScheduler, preloadCalEmbed } from './demo-scheduler'

0 commit comments

Comments
 (0)