Skip to content

Conversation

@PeerRich
Copy link
Member

@PeerRich PeerRich commented Jan 24, 2026

What does this PR do?

Adds native video call support to the Cal.com companion app by integrating the Daily.co React Native SDK and configuring deep linking for app.cal.com/video/* URLs.

When users tap a Cal.com video link on their mobile device, the app will now open natively and join the video call using the Daily SDK instead of opening in a web browser.

Changes:

  • Added @daily-co/react-native-daily-js SDK and required dependencies
  • Configured iOS/Android permissions for camera, microphone, and background audio
  • Set up deep linking via iOS Associated Domains and Android Intent Filters
  • Created new video call screen at app/video/[bookingUid].tsx that fetches the booking to get the Daily meeting URL and joins the call
  • Added utility functions for video URL handling in deep-links.ts

Updates since last revision

  • Moved URL validation logic outside try/catch block entirely to satisfy React Compiler requirements (the compiler doesn't support any logical expressions inside try/catch)
  • Fixed URL validation bug: Cal.com video URLs were incorrectly checking for /video/ in the hostname instead of the pathname
  • Added strict hostname matching to prevent domain spoofing (e.g., cal.com.evil.com is now rejected)
  • Fixed NativeEventEmitter crash: The Daily SDK was crashing the app on startup because it tries to initialize native modules at import time. Now uses dynamic imports (await import()) to defer SDK loading until the video screen is actually rendered. Added fallback UI with "Open in Browser" button for environments where native modules aren't available (Expo Go, web).
  • Fixed React Compiler build error: The "use no memo" directive alone wasn't sufficient to exclude the file from React Compiler. Added a sources filter in babel.config.js to explicitly exclude app/video/[bookingUid].tsx from compilation since dynamic import() expressions are not yet supported by the compiler.

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. N/A - no docs changes needed.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

  1. Build the companion app for iOS or Android (requires a development build, not Expo Go)
  2. Open a Cal.com video URL (e.g., https://app.cal.com/video/{bookingUid}) on the device
  3. Verify the app opens and attempts to join the video call
  4. Test camera/microphone toggle controls
  5. Test leaving the call
  6. Test in Expo Go to verify the fallback UI appears with "Open in Browser" button

Important notes:

  • Deep linking requires the app to be installed on a real device or emulator
  • iOS Universal Links require the apple-app-site-association file to be hosted on app.cal.com/.well-known/
  • The booking must have a valid Daily meeting URL in the meetingUrl or location field
  • Video calls will NOT work in Expo Go - a development build with native modules is required

Checklist for reviewers

  • Verify the booking API returns the Daily meeting URL correctly in meetingUrl or location field
  • Verify deep link configuration is correct for production
  • Test on actual iOS and Android devices with a development build
  • Review the dynamic import pattern in loadDailySDK() - this defers SDK loading to prevent startup crashes
  • Note: app.cal.com is hardcoded in deep-links.ts and video screen URL validation - self-hosted instances will need adjustment
  • Review the ~600 line video call screen for edge cases (error handling, participant state management)
  • Consider if unit tests should be added for the video URL utility functions

Link to Devin run: https://app.devin.ai/sessions/a7772bf3d12d43bebc665dfbdffd54d0
Requested by: @PeerRich

- Add @daily-co/react-native-daily-js SDK and dependencies
- Configure deep linking for app.cal.com/video/* URLs
- Add video call screen with Daily SDK integration
- Add camera/microphone permissions for iOS and Android
- Add utility functions for video URL handling

Co-Authored-By: peer@cal.com <peer@cal.com>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

devin-ai-integration bot and others added 2 commits January 24, 2026 09:08
@PeerRich PeerRich marked this pull request as ready for review January 24, 2026 09:28
@PeerRich PeerRich requested a review from a team as a code owner January 24, 2026 09:28
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

4 issues found across 6 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="companion/utils/deep-links.ts">

<violation number="1" location="companion/utils/deep-links.ts:176">
P2: Use the configured Cal.com base URL instead of hard-coding `app.cal.com`, otherwise self-hosted deep links will never match.</violation>

<violation number="2" location="companion/utils/deep-links.ts:191">
P2: Extract the host from `getCalWebUrl()` when validating video URLs so self-hosted domains are supported.</violation>
</file>

<file name="companion/app/video/[bookingUid].tsx">

<violation number="1" location="companion/app/video/[bookingUid].tsx:64">
P2: URL validation is too permissive; `hostname.includes("daily.co")` will accept non‑Daily domains. Restrict to exact Daily hostnames (e.g., `daily.co` or subdomains ending with `.daily.co`).</violation>

<violation number="2" location="companion/app/video/[bookingUid].tsx:65">
P1: Cal.com video deep links will always fail validation because the path check is performed on hostname. Check the pathname instead so `app.cal.com/video/*` is accepted.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

export function extractBookingUidFromVideoUrl(url: string): string | null {
try {
const urlObj = new URL(url);
if (urlObj.hostname === "app.cal.com" && urlObj.pathname.startsWith("/video/")) {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 24, 2026

Choose a reason for hiding this comment

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

P2: Extract the host from getCalWebUrl() when validating video URLs so self-hosted domains are supported.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At companion/utils/deep-links.ts, line 191:

<comment>Extract the host from `getCalWebUrl()` when validating video URLs so self-hosted domains are supported.</comment>

<file context>
@@ -163,3 +163,40 @@ export async function openCancelBookingInWeb(bookingUid: string): Promise<void>
+export function extractBookingUidFromVideoUrl(url: string): string | null {
+  try {
+    const urlObj = new URL(url);
+    if (urlObj.hostname === "app.cal.com" && urlObj.pathname.startsWith("/video/")) {
+      const pathParts = urlObj.pathname.split("/");
+      // URL format: /video/{bookingUid}
</file context>
Fix with Cubic

Copy link
Member Author

Choose a reason for hiding this comment

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

Devin ignore this. for now we only provide support for companion for our own apps, not self-hosters. maybe later

@github-actions
Copy link
Contributor

github-actions bot commented Jan 24, 2026

Devin AI is addressing Cubic AI's review feedback

New feedback has been sent to the existing Devin session.

View Devin Session


✅ Pushed commit 23935f7

…URLs

Co-Authored-By: peer@cal.com <peer@cal.com>
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="companion/app/video/[bookingUid].tsx">

<violation number="1" location="companion/app/video/[bookingUid].tsx:66">
P2: `hostname.includes("cal.com")` is overly permissive and will accept spoofed domains like `cal.com.evil.com`. Restrict the hostname to trusted Cal domains before allowing `/video/` paths.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 24, 2026

Devin AI is addressing Cubic AI's review feedback

New feedback has been sent to the existing Devin session.

View Devin Session


✅ No changes pushed

cubic-dev-ai bot and others added 5 commits January 26, 2026 13:38
…fing (#27239)

Co-authored-by: cubic-dev-ai[bot] <1082092+cubic-dev-ai[bot]@users.noreply.github.com>
… Expo Go

Co-Authored-By: peer@cal.com <peer@cal.com>
…t Compiler

Co-Authored-By: peer@cal.com <peer@cal.com>
…nfig

Co-Authored-By: peer@cal.com <peer@cal.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants