@@ -8,8 +8,41 @@ import { useTrackingConsent } from '@/lib/consent/tracking-consent'
88import type { DemoLead } from '@/app/(landing)/demo/components/demo-form'
99
1010const CAL_NAMESPACE = 'demo'
11- /** The Cal.com event the demo books - set `NEXT_PUBLIC_CAL_LINK` to override. */
12- const CAL_LINK = process . env . NEXT_PUBLIC_CAL_LINK ?? 'team/sim/demo'
11+ const DEFAULT_CAL_ORIGIN = 'https://app.cal.com'
12+ const DEFAULT_CAL_LINK = 'team/sim/demo'
13+
14+ interface CalEmbedConfig {
15+ calLink : string
16+ calOrigin : string
17+ embedJsUrl : string
18+ }
19+
20+ function parseCalEmbedConfig ( link : string ) : CalEmbedConfig {
21+ const url = new URL ( link . replace ( / ^ \/ + / , '' ) , `${ DEFAULT_CAL_ORIGIN } /` )
22+ if ( ! [ 'http:' , 'https:' ] . includes ( url . protocol ) || url . username || url . password ) {
23+ throw new Error ( 'Cal link must use HTTP(S) without embedded credentials' )
24+ }
25+
26+ const calLink = `${ url . pathname . replace ( / ^ \/ + / , '' ) } ${ url . search } `
27+ if ( ! calLink ) throw new Error ( 'Cal link must include an event path' )
28+
29+ return {
30+ calLink,
31+ calOrigin : url . origin ,
32+ embedJsUrl : `${ url . origin } /embed/embed.js` ,
33+ }
34+ }
35+
36+ /** Resolves the configured booker, falling back safely when the environment value is invalid. */
37+ export function resolveCalEmbedConfig ( configuredLink ?: string ) : CalEmbedConfig {
38+ try {
39+ return parseCalEmbedConfig ( configuredLink ?. trim ( ) || DEFAULT_CAL_LINK )
40+ } catch {
41+ return parseCalEmbedConfig ( DEFAULT_CAL_LINK )
42+ }
43+ }
44+
45+ const CAL_EMBED = resolveCalEmbedConfig ( process . env . NEXT_PUBLIC_CAL_LINK )
1346
1447/**
1548 * Sim's brand color, matching the `--brand-agent` token. The embed renders in a
@@ -37,9 +70,9 @@ let calEmbedPreloaded = false
3770export function preloadCalEmbed ( ) : void {
3871 if ( calEmbedPreloaded ) return
3972 calEmbedPreloaded = true
40- getCalApi ( { namespace : CAL_NAMESPACE } )
73+ getCalApi ( { namespace : CAL_NAMESPACE , embedJsUrl : CAL_EMBED . embedJsUrl } )
4174 . then ( ( cal ) => {
42- cal ( 'preload' , { calLink : CAL_LINK } )
75+ cal ( 'preload' , { calLink : CAL_EMBED . calLink } )
4376 } )
4477 . catch ( ( ) => {
4578 calEmbedPreloaded = false
@@ -71,7 +104,7 @@ export function DemoScheduler({ lead }: DemoSchedulerProps) {
71104 }
72105 if ( marketing ) window . twq ?.( 'event' , X_DEMO_BOOKED_EVENT_ID , { } )
73106 }
74- const api = getCalApi ( { namespace : CAL_NAMESPACE } )
107+ const api = getCalApi ( { namespace : CAL_NAMESPACE , embedJsUrl : CAL_EMBED . embedJsUrl } )
75108 api
76109 . then ( ( cal ) => {
77110 if ( cancelled ) return
@@ -104,8 +137,10 @@ export function DemoScheduler({ lead }: DemoSchedulerProps) {
104137 < div className = 'mt-5 min-h-0 flex-1' >
105138 < Cal
106139 namespace = { CAL_NAMESPACE }
107- calLink = { CAL_LINK }
108- style = { { width : '100%' , height : '100%' , overflow : 'auto' } }
140+ calLink = { CAL_EMBED . calLink }
141+ calOrigin = { CAL_EMBED . calOrigin }
142+ embedJsUrl = { CAL_EMBED . embedJsUrl }
143+ className = 'size-full overflow-auto'
109144 config = { {
110145 name : lead . name ,
111146 email : lead . email ,
0 commit comments