Skip to content

Commit 55d793a

Browse files
chriscaninclaude
andcommitted
fix(react): use explicit experimental flag for headless runtime instead 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>
1 parent 0c84f42 commit 55d793a

3 files changed

Lines changed: 16 additions & 5 deletions

File tree

packages/expo/src/provider/ClerkProvider.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ export function ClerkProvider<TUi extends Ui = Ui>(props: ClerkProviderProps<TUi
282282
...experimental,
283283
// force the rethrowOfflineNetworkErrors flag to true if the asyncStorage is provided
284284
rethrowOfflineNetworkErrors: !!__experimental_resourceCache || experimental?.rethrowOfflineNetworkErrors,
285+
...(isNative() && { runtimeEnvironment: 'headless' as const }),
285286
}}
286287
>
287288
{children}

packages/react/src/isomorphicClerk.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,12 +279,17 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk {
279279
this.#eventBus.emit(clerkEvents.Status, 'loading');
280280
this.#eventBus.prioritizedOn(clerkEvents.Status, status => (this.#status = status));
281281

282-
// Only load entry chunks in standard browser environments (not React Native/headless)
283-
if (this.#publishableKey && this.options.standardBrowser !== false) {
284-
void this.getEntryChunks();
285-
} else if (this.#publishableKey && this.options.Clerk) {
286-
// For React Native/headless: initialize with the provided Clerk instance
282+
// TODO: Please check into refactoring the type logic here, the experimental type interface is using type Autocomplete<U extends T, T = string> = U | (T & Record<never, never>);
283+
// so we are casting options.experimental.runtimeEnvironment to avoid changing Autocomplete to use an intersection (&) instead of a union (|), as this could cause problems in other parts of the codebase if not also refactored.
284+
285+
if (
286+
this.#publishableKey &&
287+
(this.options.experimental as { runtimeEnvironment?: string } | undefined)?.runtimeEnvironment === 'headless' &&
288+
this.options.Clerk
289+
) {
287290
void this.loadHeadlessClerk();
291+
} else if (this.#publishableKey) {
292+
void this.getEntryChunks();
288293
}
289294
}
290295

packages/shared/src/types/clerk.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,6 +1254,11 @@ export type ClerkOptions = ClerkOptionsNavigation &
12541254
*/
12551255
rethrowOfflineNetworkErrors: boolean;
12561256
commerce: boolean;
1257+
/**
1258+
* When set to `'headless'`, Clerk will skip script/chunk loading and initialize
1259+
* directly with the provided Clerk instance. Used by React Native / Expo.
1260+
*/
1261+
runtimeEnvironment: 'headless';
12571262
},
12581263
Record<string, any>
12591264
>;

0 commit comments

Comments
 (0)