Skip to content

fix(demo): unblock Cal.com booking embed and align work-email validation#5335

Merged
waleedlatif1 merged 3 commits into
stagingfrom
worktree-fix-demo-scheduler-slow
Jul 1, 2026
Merged

fix(demo): unblock Cal.com booking embed and align work-email validation#5335
waleedlatif1 merged 3 commits into
stagingfrom
worktree-fix-demo-scheduler-slow

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Root cause of the slow / never-loading demo calendar: /demo was served cross-origin-isolated (COEP: credentialless + COOP: same-origin from the catch-all header rule in next.config.ts). That degrades the third-party Cal.com booking iframe — the booker loads under a Storage-Access handshake and often never finishes rendering slots (perpetual skeleton). This is the same class of issue the Google Drive Picker already carries an exclusion for. Fix excludes /demo from the isolation headers and gives it the permissive unsafe-none / same-origin-allow-popups policy.
  • Pin the Cal embed theme/layout in the inline config so the calendar renders light from first paint (fixes a dark-on-light race where cal('ui', { theme }) resolved after the iframe was created); cal('ui') now carries only genuinely UI-only settings (brand color, hide event details).
  • Gate the demo form's Continue on the same work-email rule the server already enforces, via a shared isFreeEmailDomain helper. Previously the form accepted personal emails that the request schema rejected, so those sales notifications silently failed.
  • Extract isFreeEmailDomain into lib/messaging/email/free-email.ts (colocated with the other email utils) — isolated from validation.ts so the sizable free-domain list only ships to bundles that need the work-email check, not every consumer of quickValidateEmail.
  • Trim redundant comments in the demo components.

Type of Change

  • Bug fix

Testing

  • Verified the Cal embed request/headers against the reported behavior; confirmed /demo will serve Cross-Origin-Embedder-Policy: unsafe-none after this change (curl -sI /demo).
  • Cross-checked the @calcom/embed-react usage against Cal.com's current embed docs.
  • bunx tsc, biome, and bun run check:api-validation all pass; added unit tests for isFreeEmailDomain (4 passing).

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

- Exclude /demo from cross-origin isolation headers (COEP credentialless /
  COOP same-origin) that degraded the third-party Cal.com booking iframe,
  mirroring the existing Google Drive Picker exclusion; the booker no longer
  loads under a Storage-Access handshake that often never finished
- Pin the Cal embed theme/layout in the inline config to fix a dark-on-light
  theme race; keep cal('ui') to UI-only settings
- Gate the demo form's Continue on the same work-email rule the server
  enforces via a shared isFreeEmailDomain helper, bundle-isolated in
  lib/messaging/email/free-email.ts so it doesn't bloat other email bundles
- Trim redundant comments in the demo components
@vercel

vercel Bot commented Jul 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 1, 2026 9:27pm

Request Review

@cursor

cursor Bot commented Jul 1, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Scoped security-header relaxation on /demo is intentional for the embed; work-email changes are validation-only with shared client/server logic.

Overview
Fixes the demo booking flow where the Cal.com iframe often never finished loading, and stops visitors from advancing with personal emails the API already rejects.

Cal.com embed: /demo is excluded from the catch-all COEP: credentialless / COOP: same-origin headers and gets the same permissive unsafe-none / same-origin-allow-popups treatment as Drive Picker routes, so the third-party booker is not stuck behind cross-origin isolation. Theme and layout (light, month_view) move into the embed’s inline config for correct first paint; cal('ui') only sets branding and hides event-type details.

Work email: Shared isFreeEmailDomain in lib/messaging/email/free-email.ts replaces duplicated domain-list logic in the demo-request Zod schema. The demo form uses it to disable Continue and show distinct errors for invalid vs personal addresses, matching server validation. Vitest coverage added for the helper.

Comment-only cleanup in demo-booking.tsx.

Reviewed by Cursor Bugbot for commit cc04263. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes the demo page's Cal.com booking embed (which was blocked by cross-origin isolation headers) and aligns client-side work-email validation with the server-side rule that was already rejecting personal addresses.

  • COEP/COOP headers: /demo and its sub-paths are excluded from the strict credentialless/same-origin policy and given unsafe-none/same-origin-allow-popups instead, unblocking the Cal.com iframe's Storage-Access handshake.
  • Cal embed config: theme, layout, and ui.color-scheme are moved to the inline config prop so the booker picks them up before the iframe is created, closing the dark-mode race where cal('ui') resolved too late.
  • Work-email gating: isFreeEmailDomain is extracted to its own module (lib/messaging/email/free-email.ts), shared by both the Zod contract and the demo form's canSubmit guard, so the Continue button is disabled for personal domains and surfaces a clear error message before the request ever hits the server.

Confidence Score: 5/5

Safe to merge — all changes are targeted bug fixes with no regressions introduced.

All three fix paths (COEP header exclusion, Cal embed config placement, work-email client gating) are straightforward and well-scoped. The extracted isFreeEmailDomain module preserves the exact same lookup logic as the inline code it replaces, the header lookahead and permissive-rule pattern are kept in sync, and the new unit tests cover the edge cases. No existing behavior outside the /demo route is affected.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/next.config.ts Adds demo to the strict-COEP negative lookahead and demo.* to the permissive rule; the two patterns are now aligned so any path beginning with /demo consistently receives unsafe-none/same-origin-allow-popups rather than the cross-origin-isolating headers that were blocking the Cal.com iframe.
apps/sim/lib/messaging/email/free-email.ts New module that extracts isFreeEmailDomain and the FREE_EMAIL_DOMAINS Set into its own file; the domain is lowercased before lookup so it handles mixed-case addresses from both client and server call-sites correctly.
apps/sim/lib/messaging/email/free-email.test.ts New unit-test file covering known free providers, work domains, case-insensitivity, and the empty/no-domain edge cases.
apps/sim/lib/api/contracts/demo-requests.ts Replaces the inline FREE_EMAIL_DOMAINS Set with a call to the shared isFreeEmailDomain helper; behavior is identical because the value has already been lowercased by the preceding .transform before the refine runs.
apps/sim/app/(landing)/demo/components/demo-form/demo-form.tsx Adds client-side isFreeEmailDomain gate so the Continue button is disabled for personal email domains, matching the server-side constraint; distinguishes format errors from domain errors in the inline error message.
apps/sim/app/(landing)/demo/components/demo-scheduler/demo-scheduler.tsx Moves theme, layout, and adds ui.color-scheme to the inline config prop so the Cal.com booker picks them up on first iframe load, eliminating the dark-mode race where cal('ui') fired after iframe creation.
apps/sim/app/(landing)/demo/components/demo-booking/demo-booking.tsx Comment-only cleanup; no logic changes.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Visitor
    participant DemoForm
    participant isFreeEmailDomain
    participant Server as API /demo-request
    participant CalEmbed as Cal.com Iframe

    Visitor->>DemoForm: types work email
    DemoForm->>isFreeEmailDomain: check domain (client)
    isFreeEmailDomain-->>DemoForm: false (work domain)
    DemoForm-->>Visitor: Continue enabled

    Visitor->>DemoForm: Submit
    DemoForm->>Server: POST demo request
    Server->>isFreeEmailDomain: refine check (server)
    isFreeEmailDomain-->>Server: false passes
    Server-->>DemoForm: 200 OK

    DemoForm->>CalEmbed: mount with config theme layout ui.color-scheme
    Note over CalEmbed: COEP: unsafe-none on /demo, iframe loads without COEP block
    CalEmbed-->>Visitor: Cal.com booker rendered (light theme)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Visitor
    participant DemoForm
    participant isFreeEmailDomain
    participant Server as API /demo-request
    participant CalEmbed as Cal.com Iframe

    Visitor->>DemoForm: types work email
    DemoForm->>isFreeEmailDomain: check domain (client)
    isFreeEmailDomain-->>DemoForm: false (work domain)
    DemoForm-->>Visitor: Continue enabled

    Visitor->>DemoForm: Submit
    DemoForm->>Server: POST demo request
    Server->>isFreeEmailDomain: refine check (server)
    isFreeEmailDomain-->>Server: false passes
    Server-->>DemoForm: 200 OK

    DemoForm->>CalEmbed: mount with config theme layout ui.color-scheme
    Note over CalEmbed: COEP: unsafe-none on /demo, iframe loads without COEP block
    CalEmbed-->>Visitor: Cal.com booker rendered (light theme)
Loading

Reviews (3): Last reviewed commit: "fix(demo): use demo.* in permissive COEP..." | Re-trigger Greptile

Comment thread apps/sim/next.config.ts Outdated
Align the permissive-headers positive match with the strict-COEP negative
lookahead so any future /demo subroute still receives the permissive
COEP/COOP policy instead of falling through to no headers.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit eba8ecc. Configure here.

The demo(/.*)? form introduced a nested capturing group, which Next's
path-to-regexp route-source parser rejects ('Capturing groups are not
allowed'), failing the build. demo.* mirrors the strict-rule lookahead's
demo prefix without a nested group, matching the existing w/.* style.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit cc04263. Configure here.

@waleedlatif1 waleedlatif1 merged commit eb367de into staging Jul 1, 2026
17 checks passed
@waleedlatif1 waleedlatif1 deleted the worktree-fix-demo-scheduler-slow branch July 1, 2026 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant