Skip to content

feat(expo): add useNativeToWeb to open a signed-in system browser - #10825

Open
wobsoriano wants to merge 2 commits into
rob/mobile-450-add-native-to-web-apis-to-expofrom
rob/mobile-450-expo-open-external-browser
Open

wobsoriano wants to merge 2 commits into
rob/mobile-450-add-native-to-web-apis-to-expofrom
rob/mobile-450-expo-open-external-browser

Conversation

@wobsoriano

Copy link
Copy Markdown
Member

Description

Stacked on #10767, which adds the WebView half.

Today, when a signed-in Expo app opens a web page in the system browser, the user lands signed out and has to sign in again. This PR adds openExternalBrowser, which opens the destination in the default browser with the native user signed in.

import { useNativeToWeb } from '@clerk/expo/native-to-web';

const { openExternalBrowser } = useNativeToWeb();
await openExternalBrowser({ destination: 'https://app.example.com/billing' });

What to look at:

  • Android referrer. Chrome only accepts the sign-in URL when the intent names the app as referrer. The opener starts a VIEW intent through expo-intent-launcher with REFERRER_NAME set to android-app://<package>. expo-intent-launcher is a new optional peer.
  • iOS opens Safari with Linking.openURL.
  • Double taps. A second call while one is in flight opens one browser tab, not two.

Tested with an Expo SDK 58 app on a dev instance with the flag on:

Platform Result
iOS 27 simulator Safari, signed in
Android API 36 emulator Chrome, signed in

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

🤖 Generated with Claude under Rob's supervision.

Part of MOBILE-450

useNativeToWeb().openExternalBrowser mints a session transfer URL and
opens it in the default browser, so the destination loads with the
native user signed in. On Android it starts the VIEW intent through
expo-intent-launcher with REFERRER_NAME set to the app, which Chrome
needs before FAPI accepts the redeem.
@vercel

vercel Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
clerk-js-sandbox Ready Ready Preview Nov 14, 2026 2:22am UTC
swingset Ready Ready Preview Nov 14, 2026 2:22am UTC

Request Review

@changeset-bot

changeset-bot Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 96ce935

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes changesets to release 1 package
Name Type
@clerk/expo Minor

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@blacksmith-sh

blacksmith-sh Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

Blocked Android: Chrome opens signed in

blocked (environment) — Needs an Android emulator running a build of an app that calls openExternalBrowser, against an instance with session transfers on; the sandbox has no Android SDK, Java or such test-app screen.

Also checked · 4 match · 1 not run

Blocked iOS: Safari opens signed in · Blocked
Matches Android intent names the app as referrer
Matches iOS hands the URL to Linking.openURL
Matches Double tap opens one tab
Matches Missing expo-intent-launcher

Note

Proof planned 1 claim but was not able to run it:

Needs the iOS Simulator

  • iOS: Safari opens signed in

Proof on 96ce9356 (from 49568cd2) · mocked: react-native, expo-intent-launcher, expo... (no device runtime in the sandbox, so the harness swaps Linking, AppState, Platfo...), Clerk Frontend API (setting session transfers feature flag) · not run: Android emulator with Chrome (the sandbox has no Android SDK, Java or Gradle build of the expo-native test app...), iOS Simulator with Safari (the Linux sandbox cannot run the iOS Simulator) · Did Proof get it right? Yes · No

View full Proof report · React 👎 or comment @codesmith dismiss this proof to dismiss

This branch was successfully deployed

2 active deployments
Preview – swingset — 96ce9356 Deployed Nov 14, 2026 by vercel[bot]
Preview – clerk-js-sandbox — 96ce9356 Deployed Nov 14, 2026 by vercel[bot]
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.

1 participant