Skip to content

feat(expo): Chris/mobile 405 react native components release#7843

Merged
chriscanin merged 100 commits intomainfrom
chris/mobile-405-react-native-components-release
Mar 9, 2026
Merged

feat(expo): Chris/mobile 405 react native components release#7843
chriscanin merged 100 commits intomainfrom
chris/mobile-405-react-native-components-release

Conversation

@chriscanin
Copy link
Member

@chriscanin chriscanin commented Feb 13, 2026

Description

These changes can be tested by using the snapshot that will be commented in this PR discussion, and installing that into the expo quickstart repo on the branch: chris/mobile-343-bridge-android-to-a-native-module-that-is-available-in-the
(same branch name as here).

https://linear.app/clerk/issue/MOBILE-342/bridge-ios-to-a-native-module-that-is-available-in-the-expo-sdk
MOBILE-289
https://linear.app/clerk/issue/MOBILE-289/expo-google-universal-sign-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:

Summary by CodeRabbit

  • New Features

    • Native Expo UI: AuthView, InlineAuthView, UserButton, UserProfileView (modal & inline) and native plugin support
    • Native auth flows: Google Sign‑In and Apple Sign‑In; new native session/events hooks and client token access
  • Bug Fixes

    • More reliable native↔JS session sync, improved lifecycle/unmount guards, and clearer error handling
  • Documentation

    • Native iOS setup guide and native components README
  • Chores

    • Expo plugin, packaging, podspec and package version updates

- Implemented UserButton component to open UserProfileView on press.
- Created UserProfile component for comprehensive profile management.
- Integrated native ClerkExpo module for iOS functionality.
- Updated ClerkProvider to configure Clerk iOS SDK.
- Added exports for new components in the native index file.
- Adjusted TypeScript configuration to include additional files.
- Modified build process to temporarily skip declaration generation.
- Updated dependencies in pnpm-lock.yaml for compatibility.
…ge-ios-to-a-native-module-that-is-available-in-the-expo
…ge-android-to-a-native-module-that-is-available-in-the
…ling and UI presentation

- Consolidated Clerk SDK initialization and session management in ClerkExpoModule.
- Removed ClerkProfileActivity and replaced it with ClerkUserProfileActivity for better clarity and functionality.
- Introduced ClerkViewFactory to manage creation of intents for authentication and user profile activities.
- Enhanced error handling and promise management for asynchronous operations.
- Updated SignIn and UserProfile components to synchronize native and JS session states effectively.
- Improved user experience by ensuring the auth modal is always presented, allowing native UI to manage signed-in state.
- Added backward-compatible wrappers for SignedIn and SignedOut components.
- Updated `clerk-android` versions in `build.gradle` to `0.1.30` for API and `0.1.4` for UI.
- Added Kotlin metadata version check skip to address compatibility issues.
- Introduced packaging exclusions for duplicate META-INF files in Android.
- Enhanced `ClerkAuthActivity` to improve session handling and logging.
- Updated `ClerkExpoModule` to include detailed logging for session retrieval.
- Improved `ClerkUserProfileActivity` to handle sign-out detection and logging.
- Refined `SignIn` and `UserProfile` components to prevent duplicate auth callbacks and improve user state management.
- Added packaging exclusions in the Expo config plugin for Android to resolve dependency conflicts.
- Introduced AuthView component to handle sign-in and sign-up using native UI.
- Added AuthView types for better type safety.
- Removed deprecated SignIn component and its types.
- Updated UserButton and UserProfileView components with enhanced documentation.
- Refactored ClerkProvider to sync native sessions with JS SDK.
- Adjusted TypeScript configurations for improved declaration generation.
- packages/expo/package.json: merge new exports (./types) and file entries (google, apple)
- packages/expo/src/hooks/index.ts: use main's standard re-exports for useSignIn/useSignUp/useWaitlist
- packages/expo/src/provider/singleton/createClerkInstance.ts: use @clerk/clerk-js import (not headless subpath)
- packages/react/src/isomorphicClerk.ts: use main's ClerkUI loading pattern via options.ui
@vercel
Copy link

vercel bot commented Feb 13, 2026

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

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Mar 9, 2026 7:10pm

Request Review

@changeset-bot
Copy link

changeset-bot bot commented Feb 13, 2026

🦋 Changeset detected

Latest commit: a42091f

The changes in this PR will be included in the next version bump.

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

Not sure what this means? Click here to learn what changesets are.

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

@clerk-cookie

This comment has been minimized.

clerk-android-ui 1.0.8 is compiled with Kotlin 2.1.20 but its
transitive dependency telemetry-api still ships Kotlin 2.3.x metadata.
The library module needs the flag to compile against these deps.
@chriscanin

This comment was marked as outdated.

@clerk-cookie

This comment has been minimized.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chriscanin

This comment was marked as outdated.

@clerk-cookie

This comment has been minimized.

The kotlin-stdlib 2.3.10 is still pulled in transitively even with
clerk-android-ui 1.0.9. The app-level config plugin must inject
-Xskip-metadata-version-check into the app's kotlinOptions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chriscanin
Copy link
Member Author

!snapshot

@clerk-cookie

This comment has been minimized.

chriscanin and others added 3 commits March 6, 2026 13:48
…ad of standardBrowser

Replace the `standardBrowser !== false` check with an explicit
`experimental.runtimeEnvironment === 'headless'` opt-in for the
`loadHeadlessClerk` path. This ensures only Expo native takes the
headless initialization path, while chrome-extension and all other
SDKs continue using `getEntryChunks` (matching main branch behavior).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chriscanin
Copy link
Member Author

What integration testing tools are available for react native / expo? Would be great to start seeing those get built out.

Maestro seems popular? https://docs.expo.dev/eas/workflows/examples/e2e-tests/

Yes, Maestro is a great option for E2E testing — it also has an MCP server that enables automated visual verification during development. I think the testing story here will be Maestro for E2E/integration tests paired with Jest for unit tests. @swolfand and I will work on getting that workflow set up.

@chriscanin
Copy link
Member Author

!snapshot

@clerk-cookie

This comment has been minimized.

const [nativeAuthState, setNativeAuthState] = useState<NativeAuthStateEvent | null>(null);

useEffect(() => {
console.log(`[useNativeAuthEvents] INIT: isNativeSupported=${isNativeSupported}, ClerkExpo=${!!ClerkExpo}`);
Copy link
Member

Choose a reason for hiding this comment

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

should the console logs in this file be behind some debug flag? I'm guessing we don't want all of these logs by default

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch, I have now wrapped all runtime console.* calls across the expo package behind DEV.

Do we want to guard against this one, or should this appear in production: 225abee

This was here from before, and did not have a DEV guard. Was not sure if this is supposed to be in production or not, but seems like we should not be surfacing console.log in production.

Wrap all runtime console.log/warn/error calls in the expo package
with __DEV__ guards so they are stripped from production builds.
- Extract repeated native module init pattern into shared utils/native-module.ts
- Add __DEV__ console.warn to all empty catch blocks for observability
- Use unique ClerkRuntimeError codes for AuthView and InlineAuthView throws
- Lift getInitials() out of UserButton component to module scope
- Add __DEV__ logging to token cache and expo-web-browser catches in ClerkProvider
- Delete slop README.md from native directory
@chriscanin
Copy link
Member Author

@brkalow

Console logs behind __DEV__ - The logs in useNativeAuthEvents.ts have been updated and are now gated behind __DEV__.

Empty catches - Added __DEV__ console.warn to every empty catch block in the native components/hooks so errors are observable during development.

Repeated native module snippet - Extracted to utils/native-module.ts, exports isNativeSupported and ClerkExpoModule. Removed the duplicated pattern from all 7 files that had it. Note: the helper's early return when Platform.OS is not ios/android is intentionally silent — it's not an error, just "not applicable" on web.

ClerkRuntimeError - The only thrown user-facing errors in the native components are in AuthView and InlineAuthView. Both already used ClerkRuntimeError but shared the same code (clerk_instance_not_available). Updated to unique codes: expo_auth_view_clerk_instance_not_available and expo_inline_auth_view_clerk_instance_not_available.

README.md slop - Deleted packages/expo/src/native/README.md.

getInitials() - Lifted out of the UserButton component to a module-level function. There's a shared getInitials in @clerk/shared/internal but it's an internal export with a different signature (name fallback), so used a standalone function for now.

runtimeEnvironment in isomorphicClerk - We can't just check options.Clerk because web apps also pass bundled Clerk constructors via that prop and still need the full browser init (getEntryChunks → script loading, global.Clerk, UI chunks). We also can't use options.Clerk && !standardBrowser because @clerk/chrome-extension uses that same combo but still goes through the browser path. runtimeEnvironment === 'headless' is the explicit opt-in that says "skip all browser machinery entirely", it's the only signal that unambiguously means React Native / headless. Let me know if another solution is needed, but I believe things should be safe and guarded against other SDK's getting through this.

@chriscanin
Copy link
Member Author

!snapshot

1 similar comment
@chriscanin
Copy link
Member Author

!snapshot

@clerk-cookie
Copy link
Collaborator

Hey @chriscanin - the snapshot version command generated the following package versions:

Package Version
@clerk/agent-toolkit 0.3.2-snapshot.v20260309193756
@clerk/astro 3.0.2-snapshot.v20260309193756
@clerk/backend 3.0.2-snapshot.v20260309193756
@clerk/chrome-extension 3.1.0-snapshot.v20260309193756
@clerk/clerk-js 6.1.0-snapshot.v20260309193756
@clerk/dev-cli 0.1.1-snapshot.v20260309193756
@clerk/expo 3.1.0-snapshot.v20260309193756
@clerk/expo-passkeys 1.0.2-snapshot.v20260309193756
@clerk/express 2.0.2-snapshot.v20260309193756
@clerk/fastify 3.1.0-snapshot.v20260309193756
@clerk/hono 0.1.0-snapshot.v20260309193756
@clerk/localizations 4.1.0-snapshot.v20260309193756
@clerk/msw 0.0.2-snapshot.v20260309193756
@clerk/nextjs 7.0.2-snapshot.v20260309193756
@clerk/nuxt 2.0.2-snapshot.v20260309193756
@clerk/react 6.0.2-snapshot.v20260309193756
@clerk/react-router 3.0.2-snapshot.v20260309193756
@clerk/shared 4.1.0-snapshot.v20260309193756
@clerk/tanstack-react-start 1.0.2-snapshot.v20260309193756
@clerk/testing 2.0.2-snapshot.v20260309193756
@clerk/ui 1.1.0-snapshot.v20260309193756
@clerk/upgrade 2.0.2-snapshot.v20260309193756
@clerk/vue 2.0.2-snapshot.v20260309193756

Tip: Use the snippet copy button below to quickly install the required packages.
@clerk/agent-toolkit

npm i @clerk/agent-toolkit@0.3.2-snapshot.v20260309193756 --save-exact

@clerk/astro

npm i @clerk/astro@3.0.2-snapshot.v20260309193756 --save-exact

@clerk/backend

npm i @clerk/backend@3.0.2-snapshot.v20260309193756 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.1.0-snapshot.v20260309193756 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.1.0-snapshot.v20260309193756 --save-exact

@clerk/dev-cli

npm i @clerk/dev-cli@0.1.1-snapshot.v20260309193756 --save-exact

@clerk/expo

npm i @clerk/expo@3.1.0-snapshot.v20260309193756 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@1.0.2-snapshot.v20260309193756 --save-exact

@clerk/express

npm i @clerk/express@2.0.2-snapshot.v20260309193756 --save-exact

@clerk/fastify

npm i @clerk/fastify@3.1.0-snapshot.v20260309193756 --save-exact

@clerk/hono

npm i @clerk/hono@0.1.0-snapshot.v20260309193756 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.1.0-snapshot.v20260309193756 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.2-snapshot.v20260309193756 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.0.2-snapshot.v20260309193756 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@2.0.2-snapshot.v20260309193756 --save-exact

@clerk/react

npm i @clerk/react@6.0.2-snapshot.v20260309193756 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.0.2-snapshot.v20260309193756 --save-exact

@clerk/shared

npm i @clerk/shared@4.1.0-snapshot.v20260309193756 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.0.2-snapshot.v20260309193756 --save-exact

@clerk/testing

npm i @clerk/testing@2.0.2-snapshot.v20260309193756 --save-exact

@clerk/ui

npm i @clerk/ui@1.1.0-snapshot.v20260309193756 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.2-snapshot.v20260309193756 --save-exact

@clerk/vue

npm i @clerk/vue@2.0.2-snapshot.v20260309193756 --save-exact

Copy link
Member

@brkalow brkalow left a comment

Choose a reason for hiding this comment

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

🚢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants