Skip to content

Conversation

@LauraBeatris
Copy link
Member

@LauraBeatris LauraBeatris commented Nov 5, 2025

Description

This PR allows developers to enable the organization's featureset in-app instead of having to go to the Clerk Dashboard, decreasing friction to build B2B apps.

The prompt only appears for development instances only.

CleanShot 2025-11-21 at 10 36 36

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

    • In-app development prompt to enable Organizations when org components/hooks are first used — lazy-loaded, themeable, shows success state, dashboard link, optional per-user personal-accounts toggle, queues across hydration and may refresh app on enable.
  • Chores

    • Bundle size budgets updated to include prompt assets and related entries.
  • Accessibility

    • Modal initial-focus control added for improved keyboard focus.
  • Tests

    • Added coverage for the enable-organizations prompt/enabling flow.

✏️ Tip: You can customize this high-level summary in your review settings.

@LauraBeatris LauraBeatris self-assigned this Nov 5, 2025
@changeset-bot
Copy link

changeset-bot bot commented Nov 5, 2025

🦋 Changeset detected

Latest commit: 21d53a9

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

This PR includes changesets to release 22 packages
Name Type
@clerk/clerk-js Minor
@clerk/shared Minor
@clerk/clerk-react Minor
@clerk/vue Minor
@clerk/chrome-extension Patch
@clerk/clerk-expo Patch
@clerk/agent-toolkit Patch
@clerk/astro Patch
@clerk/backend Patch
@clerk/elements Patch
@clerk/expo-passkeys Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/remix Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch
@clerk/themes Patch
@clerk/types Patch
@clerk/localizations Patch

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

@vercel
Copy link

vercel bot commented Nov 5, 2025

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

Project Deployment Preview Comments Updated (UTC)
clerk-js-sandbox Ready Ready Preview Comment Nov 24, 2025 5:07pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 5, 2025

Walkthrough

Adds an in-app development prompt to enable Organizations, new Clerk internal APIs and DevTools method, a lazy modal UI and provider, hook integrations to trigger prompt on first use, type and bundle manifest updates, and tests for the new enable flow.

Changes

Cohort / File(s) Summary
Version & bundle
\.changeset/flat-ravens-call.md, packages/clerk-js/bundlewatch.config.json
Bumped minor package versions; updated bundle maxSize thresholds and added enableOrganizationsPrompt*.js (~6.5KB) to manifests.
Core Clerk APIs & lifecycle
packages/clerk-js/src/core/clerk.ts, packages/react/src/isomorphicClerk.ts
Added internal methods __internal_attemptToEnableEnvironmentSetting, __internal_openEnableOrganizationsPrompt, __internal_closeEnableOrganizationsPrompt; premount queuing and hydration handling for prompt open/attempt flows.
DevTools resource & types
packages/clerk-js/src/core/resources/DevTools.ts, packages/shared/src/types/devtools.ts, packages/shared/src/types/index.ts
New DevTools resource with __internal_enableEnvironmentSetting PATCH endpoint; added EnableEnvironmentSettingParams and DevToolsResource types; exported from shared types index.
Public/shared types
packages/shared/src/types/clerk.ts, packages/shared/src/types/appearance.ts, packages/shared/src/types/index.ts
Added __internal_EnableOrganizationsPromptProps, __internal_AttemptToEnableEnvironmentSettingParams, __internal_AttemptToEnableEnvironmentSettingResult; added EnableOrganizationsTheme and enableOrganizations appearance field; removed __internal_ComponentNavigationContext.
Enable Organizations prompt UI
packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx
New lazy modal component implementing enable flow, animations, personal-account toggle, focus handling, DevTools call, and onSuccess/onClose hooks; exported EnableOrganizationsPrompt.
Shared dev-prompt utilities
packages/clerk-js/src/ui/components/devPrompts/shared.tsx
Added PromptContainer, basePromptElementStyles, PromptSuccessIcon, ClerkLogoIcon, and handleDashboardUrlParsing.
Keyless prompt refactor
packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx, packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/use-revalidate-environment.ts, packages/clerk-js/src/ui/components/KeylessPrompt/ClerkLogoIcon.tsx
Migrated KeylessPrompt to shared utilities, removed duplicate ClerkLogoIcon export, updated imports and styles.
Component system & lazy providers
packages/clerk-js/src/ui/Components.tsx, packages/clerk-js/src/ui/lazyModules/components.ts, packages/clerk-js/src/ui/lazyModules/providers.tsx
Added enableOrganizationsPrompt modal state/control, registered lazy EnableOrganizationsPrompt component, added LazyEnableOrganizationsPromptProvider with appearanceKey enableOrganizationsPrompt.
Appearance / Modal
packages/clerk-js/src/ui/customizables/parseAppearance.ts, packages/clerk-js/src/ui/elements/contexts/index.tsx, packages/clerk-js/src/ui/elements/Modal.tsx
Extended appearanceKey with enableOrganizationsPrompt; added flow literal enableOrganizations; Modal gained initialFocusRef prop forwarded to Popover.
Hook integrations (React & Vue)
packages/shared/src/organization.ts, packages/shared/src/react/hooks/useOrganization.tsx, packages/shared/src/react/hooks/useOrganizationList.tsx, packages/vue/src/composables/useOrganization.ts
New useAttemptToEnableOrganizations hook; invoked in useOrganization and useOrganizationList; Vue composable watches clerk and triggers a one-time attempt to enable organizations in dev.
Avoidance patterns & minor edits
packages/shared/src/react/hooks/useCheckout.ts, packages/clerk-js/src/ui/components/APIKeys/APIKeys.tsx
Comments and small refactors to avoid triggering in-app prompt unintentionally; APIKeys switched to useOrganizationContext.
Tests
packages/clerk-js/src/core/__tests__/clerk.test.ts, packages/shared/src/react/__tests__/payment-element.test.tsx
Added tests for __internal_attemptToEnableEnvironmentSetting (dev/prod cases); removed a useOrganization mock in a payment-element test.

Sequence Diagram(s)

sequenceDiagram
    participant App as App Component
    participant Hook as useOrganization / useOrganizationList
    participant Clerk as Clerk Instance
    participant UI as EnableOrganizationsPrompt (lazy)
    participant DevTools as DevTools API

    App->>Hook: mount (uses org-related API)
    Hook->>Clerk: __internal_attemptToEnableEnvironmentSetting({ for: "organizations", caller })
    alt isEnabled === true
        Clerk-->>Hook: { isEnabled: true }
        Hook-->>App: render organization UI
    else isEnabled === false and devInstance
        Clerk->>UI: __internal_openEnableOrganizationsPrompt(props)
        UI->>DevTools: __internal_enableEnvironmentSetting({ enable_organizations: true, ... })
        DevTools-->>UI: success
        UI->>Clerk: onSuccess (may trigger reload)
        Clerk->>App: reload (invalidate resources)
    else isEnabled === false and prod
        Clerk-->>Hook: { isEnabled: false }
        Hook-->>App: short-circuit rendering (no prompt)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx — accessibility, focus management, animations, and DevTools interaction.
  • packages/clerk-js/src/core/clerk.ts — prompt lifecycle, telemetry, and reload integration where feature-flag checks were replaced.
  • packages/react/src/isomorphicClerk.ts — premount queuing and SSR/CSR hydration edge cases for queued prompt calls.
  • packages/shared/src/organization.ts and hook integrations — correctness of one-time attempt guard across resource updates.
  • Lazy loading and bundle manifest entries — ensure prompt assets are correctly registered and lazy-loaded.

Poem

🐰 I nudged a prompt with a curious hop,

A coin did flip and toggles pop,
No dashboard trek for devs tonight,
Enable right here — a small delight,
Code and carrots, soft and bright.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(clerk-js,clerk-react,vue): Introduce development modal to enable organizations' directly describes the main change—adding a development modal for enabling organizations—and accurately reflects the changeset's primary objective.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch laura/enable-orgs

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
packages/clerk-js/src/core/clerk.ts (1)

787-794: Use eventPrebuiltComponentOpened for the enable-organizations prompt

Other modal-style entrypoints (e.g. openSignIn, __internal_openPlanDetails, __internal_openReverification) emit eventPrebuiltComponentOpened, while __internal_openEnableOrganizationsPrompt currently records eventPrebuiltComponentMounted. For consistency of telemetry semantics and dashboards, consider switching this to eventPrebuiltComponentOpened('EnableOrganizationsPrompt', props).

packages/shared/src/types/clerk.ts (1)

1449-1475: Unify caller unions between attempt params and prompt props to remove unsafe casts

__internal_EnableOrganizationsPromptProps['caller'] is missing 'CreateOrganization' and 'TaskChooseOrganization', which are present in __internal_AttemptToEnableEnvironmentSettingParams['caller']. This mismatch is currently papered over in Clerk.__internal_attemptToEnableEnvironmentSetting by casting the prompt props as __internal_EnableOrganizationsPromptProps, which defeats type checking and can hide future breakage if the prompt branches on caller.

Recommend:

  • Extract a shared alias, e.g. type __internal_OrganizationsCaller = 'OrganizationSwitcher' | 'OrganizationProfile' | 'OrganizationList' | 'CreateOrganization' | 'TaskChooseOrganization' | 'useOrganizationList' | 'useOrganization';
  • Use that alias for the caller field in both __internal_EnableOrganizationsPromptProps and __internal_AttemptToEnableEnvironmentSettingParams.
  • Then remove the as __internal_EnableOrganizationsPromptProps cast at the call site in packages/clerk-js/src/core/clerk.ts.

This keeps the internal surface self-consistent and lets the compiler enforce exhaustiveness as you add more callers.

🧹 Nitpick comments (1)
packages/clerk-js/src/core/__tests__/clerk.test.ts (1)

2512-2634: Align test keys and environment flags with test descriptions

The new tests correctly exercise the dev-only prompt behavior, but a couple of fixtures are slightly misleading:

  • In “does not open prompt if organizations is enabled in development”, productionPublishableKey is used; consider using developmentPublishableKey to match the description.
  • In “does not open prompt if organizations is disabled in production”, the stubbed environment sets isProduction: () => false while the test name mentions production.

These don’t affect correctness (the code gates on instanceType), but tightening them up will make the intent clearer for future readers.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6f4897e and 04f0eb7.

📒 Files selected for processing (3)
  • packages/clerk-js/src/core/__tests__/clerk.test.ts (1 hunks)
  • packages/clerk-js/src/core/clerk.ts (9 hunks)
  • packages/shared/src/types/clerk.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

All code must pass ESLint checks with the project's configuration

Files:

  • packages/clerk-js/src/core/__tests__/clerk.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/shared/src/types/clerk.ts
**/*.{js,jsx,ts,tsx,json,md,yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/clerk-js/src/core/__tests__/clerk.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/shared/src/types/clerk.ts
packages/**/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/clerk-js/src/core/__tests__/clerk.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/shared/src/types/clerk.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Follow established naming conventions (PascalCase for components, camelCase for variables)

Prefer importing types from @clerk/shared/types instead of the deprecated @clerk/types alias

Files:

  • packages/clerk-js/src/core/__tests__/clerk.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/shared/src/types/clerk.ts
packages/**/src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

packages/**/src/**/*.{ts,tsx,js,jsx}: Maintain comprehensive JSDoc comments for public APIs
Use tree-shaking friendly exports
Validate all inputs and sanitize outputs
All public APIs must be documented with JSDoc
Use dynamic imports for optional features
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Implement proper logging with different levels

Files:

  • packages/clerk-js/src/core/__tests__/clerk.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/shared/src/types/clerk.ts
**/*.{test,spec}.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{test,spec}.{ts,tsx,js,jsx}: Unit tests are required for all new functionality
Verify proper error handling and edge cases
Include tests for all new features

Files:

  • packages/clerk-js/src/core/__tests__/clerk.test.ts
**/*.ts?(x)

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

Files:

  • packages/clerk-js/src/core/__tests__/clerk.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/shared/src/types/clerk.ts
**/*.{test,spec,e2e}.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use real Clerk instances for integration tests

Files:

  • packages/clerk-js/src/core/__tests__/clerk.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Implement type guards for unknown types using the pattern function isType(value: unknown): value is Type
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details in classes
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Use mixins for shared behavior across unrelated classes in TypeScript
Use generic constraints with bounded type parameters like <T extends { id: string }>
Use utility types like Omit, Partial, and Pick for data transformation instead of manual type construction
Use discriminated unions instead of boolean flags for state management and API responses
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation at the type level
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Document functions with JSDoc comments including @param, @returns, @throws, and @example tags
Create custom error classes that extend Error for specific error types
Use the Result pattern for error handling instead of throwing exceptions
Use optional chaining (?.) and nullish coalescing (??) operators for safe property access
Let TypeScript infer obvious types to reduce verbosity
Use const assertions with as const for literal types
Use satisfies operator for type checking without widening types
Declare readonly arrays and objects for immutable data structures
Use spread operator and array spread for immutable updates instead of mutations
Use lazy loading for large types...

Files:

  • packages/clerk-js/src/core/__tests__/clerk.test.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/shared/src/types/clerk.ts
🧬 Code graph analysis (1)
packages/clerk-js/src/core/clerk.ts (2)
packages/shared/src/types/clerk.ts (3)
  • __internal_AttemptToEnableEnvironmentSettingParams (1461-1472)
  • __internal_AttemptToEnableEnvironmentSettingResult (1474-1476)
  • __internal_EnableOrganizationsPromptProps (1449-1459)
packages/clerk-js/src/utils/componentGuards.ts (1)
  • disabledOrganizationsFeature (21-23)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (1)
packages/clerk-js/src/core/clerk.ts (1)

872-886: Centralized organizations enablement guard is a solid improvement

Wiring all organization entrypoints (open/mount for OrganizationProfile, CreateOrganization, OrganizationSwitcher, OrganizationList, TaskChooseOrganization) through __internal_attemptToEnableEnvironmentSetting gives you a single place to manage dev-only prompting vs. silent no-op behavior when organizations are disabled. The pattern is consistent and the early return on !isEnabled keeps the call sites straightforward.

Also applies to: 907-923, 1056-1072, 1103-1119, 1141-1157, 1187-1203, 1389-1403

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx (1)

116-145: alignItems / justifyContent use invalid value 'flex-center'

At lines 134-135, alignItems: 'flex-center' and justifyContent: 'flex-center' are not valid CSS values and will be ignored, likely breaking centering in the expanded state.

Consider changing both to 'center':

-          '&[data-expanded="true"]': {
-            flexDirection: 'column',
-            alignItems: 'flex-center',
-            justifyContent: 'flex-center',
+          '&[data-expanded="true"]': {
+            flexDirection: 'column',
+            alignItems: 'center',
+            justifyContent: 'center',
♻️ Duplicate comments (6)
packages/vue/src/composables/useOrganization.ts (1)

59-72: Guard the watcher to avoid redundant enablement attempts and ensure cleanup

As written, every useOrganization() invocation creates a watcher that will call __internal_attemptToEnableEnvironmentSetting once and then unwatch(). If multiple components use this composable, they can all trigger the internal enablement call, which is unnecessary work and diverges from the guarded behavior in the React hooks.

To align with the React implementation and the earlier review, add a module-level idempotency guard and ensure unwatch() always runs:

-import { computed, watch } from 'vue';
+import { computed, watch } from 'vue';
+
+let hasAttemptedToEnableOrganizations = false;

 // ...

-  const unwatch = watch(
-    clerk,
-    value => {
-      if (value) {
-        // Optional chaining is important for `@clerk/vue` usage with older clerk-js versions that don't have the method
-        value.__internal_attemptToEnableEnvironmentSetting?.({
-          for: 'organizations',
-          caller: 'useOrganization',
-        });
-        unwatch();
-      }
-    },
-    { immediate: true },
-  );
+  const unwatch = watch(
+    clerk,
+    value => {
+      if (!value || hasAttemptedToEnableOrganizations) {
+        return;
+      }
+
+      hasAttemptedToEnableOrganizations = true;
+      try {
+        // Optional chaining is important for `@clerk/vue` usage with older clerk-js versions that don't have the method
+        value.__internal_attemptToEnableEnvironmentSetting?.({
+          for: 'organizations',
+          caller: 'useOrganization',
+        });
+      } finally {
+        unwatch();
+      }
+    },
+    { immediate: true },
+  );

This ensures the enablement attempt runs at most once across all useOrganization instances and that the watcher is always cleaned up, even if the internal method throws.

packages/react/src/isomorphicClerk.ts (1)

1490-1499: Return type inconsistency: missing return value when clerkjs not loaded.

The method declares __internal_AttemptToEnableEnvironmentSettingResult | void as return type, allowing the implicit void return in the else branch (line 1497). However, this creates an inconsistent contract: callers cannot determine whether the feature is enabled when invoked before clerkjs loads.

Since this method is designed to return synchronous enablement status, consider returning a concrete result immediately when clerkjs is unavailable rather than queueing the call:

 __internal_attemptToEnableEnvironmentSetting = (
   options: __internal_AttemptToEnableEnvironmentSettingParams,
 ): __internal_AttemptToEnableEnvironmentSettingResult | void => {
   const callback = () => this.clerkjs?.__internal_attemptToEnableEnvironmentSetting(options);
   if (this.clerkjs && this.loaded) {
     return callback() as __internal_AttemptToEnableEnvironmentSettingResult;
   } else {
-    this.premountMethodCalls.set('__internal_attemptToEnableEnvironmentSetting', callback);
+    // Return a result indicating enablement cannot be determined/performed yet
+    return { isEnabled: false };
   }
 };

This ensures callers always receive a typed response indicating the current enablement state.

packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx (1)

503-526: Add hover and focus-visible styles to Link component for accessibility.

The Link component lacks interactive states. Past review comments flagged this, but the styles are not yet present in the code. Without these states, keyboard users don't get clear focus indicators, and mouse users don't get hover feedback.

Apply this diff to add the missing styles:

 const Link = forwardRef<HTMLAnchorElement, React.ComponentProps<'a'> & { css?: SerializedStyles }>(
   ({ children, css: cssProp, ...props }, ref) => {
     return (
       <a
         ref={ref}
         {...props}
         css={[
           basePromptElementStyles,
           css`
             color: #a8a8ff;
             font-size: inherit;
             font-weight: 500;
             line-height: 1.3;
             font-size: 0.8125rem;
             min-width: 0;
+            cursor: pointer;
+            transition: color 120ms ease-in-out;
+
+            &:hover {
+              color: #c4c4ff;
+            }
+
+            &:focus-visible {
+              outline: 2px solid white;
+              outline-offset: 2px;
+              border-radius: 2px;
+            }
+
+            @media (prefers-reduced-motion: reduce) {
+              transition: none;
+            }
           `,
           cssProp,
         ]}
       >
         {children}
       </a>
     );
   },
 );
packages/shared/src/types/clerk.ts (1)

1449-1476: Align caller unions to avoid unsafe type assertions.

The caller union in __internal_EnableOrganizationsPromptProps (lines 1453-1458) includes 5 values, while __internal_AttemptToEnableEnvironmentSettingParams.caller (lines 1463-1470) includes 7 values—adding 'CreateOrganization' and 'TaskChooseOrganization'. This mismatch forces unsafe casting when passing the caller from __internal_attemptToEnableEnvironmentSetting to __internal_openEnableOrganizationsPrompt.

Consider one of these approaches:

  1. Extend the prompt type to include all callers:
 export type __internal_EnableOrganizationsPromptProps = {
   onSuccess?: () => void;
   onClose?: () => void;
 } & {
   caller:
     | 'OrganizationSwitcher'
     | 'OrganizationProfile'
     | 'OrganizationList'
+    | 'CreateOrganization'
+    | 'TaskChooseOrganization'
     | 'useOrganizationList'
     | 'useOrganization';
 };
  1. Extract a shared union type:
+export type OrganizationFeatureCaller =
+  | 'OrganizationSwitcher'
+  | 'OrganizationProfile'
+  | 'OrganizationList'
+  | 'CreateOrganization'
+  | 'TaskChooseOrganization'
+  | 'useOrganizationList'
+  | 'useOrganization';
+
 export type __internal_EnableOrganizationsPromptProps = {
   onSuccess?: () => void;
   onClose?: () => void;
 } & {
-  caller:
-    | 'OrganizationSwitcher'
-    | 'OrganizationProfile'
-    | 'OrganizationList'
-    | 'useOrganizationList'
-    | 'useOrganization';
+  caller: OrganizationFeatureCaller;
 };

 export type __internal_AttemptToEnableEnvironmentSettingParams = {
   for: 'organizations';
-  caller:
-    | 'OrganizationSwitcher'
-    | 'OrganizationProfile'
-    | 'OrganizationList'
-    | 'CreateOrganization'
-    | 'TaskChooseOrganization'
-    | 'useOrganizationList'
-    | 'useOrganization';
+  caller: OrganizationFeatureCaller;
   onClose?: () => void;
 };

Either approach eliminates the need for type assertions and ensures type safety across all call sites.

packages/clerk-js/src/core/clerk.ts (2)

787-795: Use eventPrebuiltComponentOpened for the enable‑organizations prompt telemetry

__internal_openEnableOrganizationsPrompt opens a modal but records telemetry with eventPrebuiltComponentMounted:

this.telemetry?.record(eventPrebuiltComponentMounted('EnableOrganizationsPrompt', props));

Other modal “open*” APIs (e.g. openSignIn, __internal_openPlanDetails) use eventPrebuiltComponentOpened so analytics reflect “prompt shown” rather than “component mounted”.

For consistency and clearer metrics, switch this to:

this.telemetry?.record(eventPrebuiltComponentOpened('EnableOrganizationsPrompt', props));

As per coding guidelines, keeping telemetry semantics consistent across prebuilt components simplifies downstream analysis.


751-781: Remove as __internal_EnableOrganizationsPromptProps and align types between attempt params and prompt props

__internal_attemptToEnableEnvironmentSetting builds the props for __internal_openEnableOrganizationsPrompt and then forces them to __internal_EnableOrganizationsPromptProps with an as cast:

this.__internal_openEnableOrganizationsPrompt({
  caller,
  onSuccess: () => window.location.reload(),
  onClose: params.onClose,
} as __internal_EnableOrganizationsPromptProps);

This hides type drift between __internal_AttemptToEnableEnvironmentSettingParams['caller'] and __internal_EnableOrganizationsPromptProps['caller'] and weakens exhaustiveness checks inside the prompt.

Prefer to:

  • Expand __internal_EnableOrganizationsPromptProps so that the object constructed here is assignable without a cast, and
  • Drop the as __internal_EnableOrganizationsPromptProps so the compiler enforces compatibility in both directions.

This keeps the internal flow type‑safe and avoids future breakage when new callers are added.

As per coding guidelines, we should avoid masking type mismatches with assertions.

🧹 Nitpick comments (3)
packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx (1)

87-112: Good reuse of basePromptElementStyles; consider further consolidation into themed primitives

Injecting basePromptElementStyles into the main CTA, header button, header text, body copy, and secondary CTA (lines 88, 154, 260, 326, 477) is a solid step toward consistent prompt styling.

As a follow-up, you might want to:

  • Extract small shared components (e.g. PromptHeaderText, PromptBodyText, PromptSecondaryLink) that already bake in basePromptElementStyles.
  • Gradually replace the hard-coded hex colors and ad‑hoc Emotion blocks here with sx + theme tokens, to better match the styled-system guidance and reduce one-off overrides.

Also applies to: 154-159, 260-266, 326-343, 477-501

packages/shared/src/react/hooks/useCheckout.ts (1)

125-126: This bypass pattern is widespread—coordinate an architectural fix across affected files.

The comment accurately describes the issue, but this same workaround appears in 6+ files across the codebase (PricingTable, APIKeys, SubscriptionDetails, PaymentMethods, Plans, and now useCheckout), suggesting this is an intentional architectural decision rather than an isolated workaround.

Since the enable organizations prompt is a real, intentionally-triggered feature in dev instances, consider addressing this at the architectural level rather than accepting the pattern piecemeal:

  1. Make the prompt logic more selective: Extend useOrganization() or the triggering logic to skip prompting for specific flows (checkout, billing components, etc.) that access organizations in expected contexts.

  2. Add a suppression flag: Enable useOrganization({ suppressEnablePrompt: true }) for all affected locations, ensuring consistent behavior.

  3. Document the decision: If this pattern must remain, centralize the comment in a shared constant or doc to avoid duplication across 6+ files.

Coordinate fixes across: useCheckout.ts, PricingTableDefault.tsx, APIKeys.tsx, SubscriptionDetails.tsx, PaymentMethods.tsx, and Plans.tsx.

packages/clerk-js/src/core/clerk.ts (1)

872-885: Confirm intended non‑dev behavior when organizations are disabled

All organization entrypoints now short‑circuit through __internal_attemptToEnableEnvironmentSetting:

  • openOrganizationProfile
  • openCreateOrganization
  • mountOrganizationProfile
  • mountCreateOrganization
  • mountOrganizationSwitcher
  • mountOrganizationList
  • mountTaskChooseOrganization

Each pattern is:

const { isEnabled: isOrganizationsEnabled } = this.__internal_attemptToEnableEnvironmentSetting({ ... });

if (!isOrganizationsEnabled) {
  return;
}

and __internal_attemptToEnableEnvironmentSetting returns { isEnabled: false } whenever disabledOrganizationsFeature(this, this.environment) is true, regardless of instanceType.

This means that in staging/production environments where organizations are disabled, these methods now become silent no‑ops (no UI, no error), whereas previously they may have mounted components or relied on different guards/runtime errors.

Please double‑check that this semantic change for non‑dev instances is intentional; if the goal was “dev‑only prompt, preserve prior behavior elsewhere”, you may want to:

  • Either make __internal_attemptToEnableEnvironmentSetting always return { isEnabled: true } outside development, or
  • Keep non‑dev behavior (e.g. specific ClerkRuntimeError paths) explicitly mirrored here.

As per coding guidelines, it’s worth validating that new central guards don’t inadvertently change production semantics.

Also applies to: 909-922, 1058-1072, 1105-1119, 1143-1157, 1189-1203, 1392-1404

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 04f0eb7 and 2da34a0.

📒 Files selected for processing (28)
  • .changeset/flat-ravens-call.md (1 hunks)
  • packages/clerk-js/bundlewatch.config.json (2 hunks)
  • packages/clerk-js/src/core/__tests__/clerk.test.ts (1 hunks)
  • packages/clerk-js/src/core/clerk.ts (9 hunks)
  • packages/clerk-js/src/core/resources/DevTools.ts (1 hunks)
  • packages/clerk-js/src/ui/Components.tsx (11 hunks)
  • packages/clerk-js/src/ui/components/APIKeys/APIKeys.tsx (2 hunks)
  • packages/clerk-js/src/ui/components/KeylessPrompt/ClerkLogoIcon.tsx (0 hunks)
  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx (1 hunks)
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx (9 hunks)
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/use-revalidate-environment.ts (1 hunks)
  • packages/clerk-js/src/ui/components/devPrompts/shared.tsx (1 hunks)
  • packages/clerk-js/src/ui/customizables/parseAppearance.ts (1 hunks)
  • packages/clerk-js/src/ui/elements/Modal.tsx (2 hunks)
  • packages/clerk-js/src/ui/elements/contexts/index.tsx (1 hunks)
  • packages/clerk-js/src/ui/lazyModules/components.ts (4 hunks)
  • packages/clerk-js/src/ui/lazyModules/providers.tsx (1 hunks)
  • packages/react/src/isomorphicClerk.ts (5 hunks)
  • packages/shared/src/organization.ts (2 hunks)
  • packages/shared/src/react/__tests__/payment-element.test.tsx (0 hunks)
  • packages/shared/src/react/hooks/useCheckout.ts (1 hunks)
  • packages/shared/src/react/hooks/useOrganization.tsx (2 hunks)
  • packages/shared/src/react/hooks/useOrganizationList.tsx (2 hunks)
  • packages/shared/src/types/appearance.ts (2 hunks)
  • packages/shared/src/types/clerk.ts (2 hunks)
  • packages/shared/src/types/devtools.ts (1 hunks)
  • packages/shared/src/types/index.ts (1 hunks)
  • packages/vue/src/composables/useOrganization.ts (2 hunks)
💤 Files with no reviewable changes (2)
  • packages/shared/src/react/tests/payment-element.test.tsx
  • packages/clerk-js/src/ui/components/KeylessPrompt/ClerkLogoIcon.tsx
🚧 Files skipped from review as they are similar to previous changes (10)
  • packages/shared/src/react/hooks/useOrganizationList.tsx
  • packages/clerk-js/src/ui/elements/Modal.tsx
  • packages/clerk-js/src/core/tests/clerk.test.ts
  • packages/clerk-js/src/ui/lazyModules/components.ts
  • packages/shared/src/react/hooks/useOrganization.tsx
  • packages/clerk-js/src/core/resources/DevTools.ts
  • packages/clerk-js/src/ui/components/APIKeys/APIKeys.tsx
  • packages/clerk-js/src/ui/components/devPrompts/shared.tsx
  • packages/clerk-js/src/ui/elements/contexts/index.tsx
  • .changeset/flat-ravens-call.md
🧰 Additional context used
📓 Path-based instructions (12)
packages/clerk-js/src/ui/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)

packages/clerk-js/src/ui/**/*.{ts,tsx}: Element descriptors should be written in camelCase
Use useCardState for card-level state management
Use useFormState for form-level state management
Use useLoadingStatus for managing loading states
Use useFormControl hook for form field state management with validation and localization support
All rendered values must be localized using useLocalizations hook - hard coded values are not allowed
Use localizationKeys for translating UI text with support for parameters and error messages
Use handleError utility for API error handling and provide field states for proper error mapping
Use the styled system sx prop with theme tokens for custom styling instead of inline styles
Use the Card component pattern with Card.Root, Card.Header, Card.Title, Card.Content, and Card.Footer for consistent card layouts
Use FormContainer with headerTitle and headerSubtitle localization keys combined with Form.Root and FormButtons for consistent form layouts
When form submission occurs, manage loading and error states by calling status.setLoading(), card.setLoading(), and card.setError() appropriately

Files:

  • packages/clerk-js/src/ui/customizables/parseAppearance.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/use-revalidate-environment.ts
  • packages/clerk-js/src/ui/Components.tsx
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx
  • packages/clerk-js/src/ui/lazyModules/providers.tsx
  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

All code must pass ESLint checks with the project's configuration

Files:

  • packages/clerk-js/src/ui/customizables/parseAppearance.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/use-revalidate-environment.ts
  • packages/shared/src/types/devtools.ts
  • packages/shared/src/organization.ts
  • packages/clerk-js/src/ui/Components.tsx
  • packages/shared/src/types/index.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx
  • packages/clerk-js/src/ui/lazyModules/providers.tsx
  • packages/shared/src/types/clerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx
  • packages/shared/src/types/appearance.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/vue/src/composables/useOrganization.ts
  • packages/shared/src/react/hooks/useCheckout.ts
**/*.{js,jsx,ts,tsx,json,md,yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/clerk-js/src/ui/customizables/parseAppearance.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/use-revalidate-environment.ts
  • packages/shared/src/types/devtools.ts
  • packages/shared/src/organization.ts
  • packages/clerk-js/src/ui/Components.tsx
  • packages/shared/src/types/index.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx
  • packages/clerk-js/src/ui/lazyModules/providers.tsx
  • packages/clerk-js/bundlewatch.config.json
  • packages/shared/src/types/clerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx
  • packages/shared/src/types/appearance.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/vue/src/composables/useOrganization.ts
  • packages/shared/src/react/hooks/useCheckout.ts
packages/**/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/clerk-js/src/ui/customizables/parseAppearance.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/use-revalidate-environment.ts
  • packages/shared/src/types/devtools.ts
  • packages/shared/src/organization.ts
  • packages/clerk-js/src/ui/Components.tsx
  • packages/shared/src/types/index.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx
  • packages/clerk-js/src/ui/lazyModules/providers.tsx
  • packages/shared/src/types/clerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx
  • packages/shared/src/types/appearance.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/vue/src/composables/useOrganization.ts
  • packages/shared/src/react/hooks/useCheckout.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Follow established naming conventions (PascalCase for components, camelCase for variables)

Prefer importing types from @clerk/shared/types instead of the deprecated @clerk/types alias

Files:

  • packages/clerk-js/src/ui/customizables/parseAppearance.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/use-revalidate-environment.ts
  • packages/shared/src/types/devtools.ts
  • packages/shared/src/organization.ts
  • packages/clerk-js/src/ui/Components.tsx
  • packages/shared/src/types/index.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx
  • packages/clerk-js/src/ui/lazyModules/providers.tsx
  • packages/shared/src/types/clerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx
  • packages/shared/src/types/appearance.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/vue/src/composables/useOrganization.ts
  • packages/shared/src/react/hooks/useCheckout.ts
packages/**/src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

packages/**/src/**/*.{ts,tsx,js,jsx}: Maintain comprehensive JSDoc comments for public APIs
Use tree-shaking friendly exports
Validate all inputs and sanitize outputs
All public APIs must be documented with JSDoc
Use dynamic imports for optional features
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Implement proper logging with different levels

Files:

  • packages/clerk-js/src/ui/customizables/parseAppearance.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/use-revalidate-environment.ts
  • packages/shared/src/types/devtools.ts
  • packages/shared/src/organization.ts
  • packages/clerk-js/src/ui/Components.tsx
  • packages/shared/src/types/index.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx
  • packages/clerk-js/src/ui/lazyModules/providers.tsx
  • packages/shared/src/types/clerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx
  • packages/shared/src/types/appearance.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/vue/src/composables/useOrganization.ts
  • packages/shared/src/react/hooks/useCheckout.ts
**/*.ts?(x)

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

Files:

  • packages/clerk-js/src/ui/customizables/parseAppearance.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/use-revalidate-environment.ts
  • packages/shared/src/types/devtools.ts
  • packages/shared/src/organization.ts
  • packages/clerk-js/src/ui/Components.tsx
  • packages/shared/src/types/index.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx
  • packages/clerk-js/src/ui/lazyModules/providers.tsx
  • packages/shared/src/types/clerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx
  • packages/shared/src/types/appearance.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/vue/src/composables/useOrganization.ts
  • packages/shared/src/react/hooks/useCheckout.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Implement type guards for unknown types using the pattern function isType(value: unknown): value is Type
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details in classes
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Use mixins for shared behavior across unrelated classes in TypeScript
Use generic constraints with bounded type parameters like <T extends { id: string }>
Use utility types like Omit, Partial, and Pick for data transformation instead of manual type construction
Use discriminated unions instead of boolean flags for state management and API responses
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation at the type level
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Document functions with JSDoc comments including @param, @returns, @throws, and @example tags
Create custom error classes that extend Error for specific error types
Use the Result pattern for error handling instead of throwing exceptions
Use optional chaining (?.) and nullish coalescing (??) operators for safe property access
Let TypeScript infer obvious types to reduce verbosity
Use const assertions with as const for literal types
Use satisfies operator for type checking without widening types
Declare readonly arrays and objects for immutable data structures
Use spread operator and array spread for immutable updates instead of mutations
Use lazy loading for large types...

Files:

  • packages/clerk-js/src/ui/customizables/parseAppearance.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/use-revalidate-environment.ts
  • packages/shared/src/types/devtools.ts
  • packages/shared/src/organization.ts
  • packages/clerk-js/src/ui/Components.tsx
  • packages/shared/src/types/index.ts
  • packages/react/src/isomorphicClerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx
  • packages/clerk-js/src/ui/lazyModules/providers.tsx
  • packages/shared/src/types/clerk.ts
  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx
  • packages/shared/src/types/appearance.ts
  • packages/clerk-js/src/core/clerk.ts
  • packages/vue/src/composables/useOrganization.ts
  • packages/shared/src/react/hooks/useCheckout.ts
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.tsx: Use error boundaries in React components
Minimize re-renders in React components

**/*.tsx: Use proper type definitions for props and state in React components
Leverage TypeScript's type inference where possible in React components
Use proper event types for handlers in React components
Implement proper generic types for reusable React components
Use proper type guards for conditional rendering in React components

Files:

  • packages/clerk-js/src/ui/Components.tsx
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx
  • packages/clerk-js/src/ui/lazyModules/providers.tsx
  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx
**/*.{md,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Update documentation for API changes

Files:

  • packages/clerk-js/src/ui/Components.tsx
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx
  • packages/clerk-js/src/ui/lazyModules/providers.tsx
  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components (e.g., UserProfile, NavigationMenu)
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Separate UI components from business logic components
Use useState for simple state management in React components
Use useReducer for complex state logic in React components
Implement proper state initialization in React components
Use proper state updates with callbacks in React components
Implement proper state cleanup in React components
Use Context API for theme/authentication state management
Implement proper state persistence in React applications
Use React.memo for expensive components
Implement proper useCallback for handlers in React components
Use proper useMemo for expensive computations in React components
Implement proper virtualization for lists in React components
Use proper code splitting with React.lazy in React applications
Implement proper cleanup in useEffect hooks
Use proper refs for DOM access in React components
Implement proper event listener cleanup in React components
Use proper abort controllers for fetch in React components
Implement proper subscription cleanup in React components
Use proper HTML elements for semantic HTML in React components
Implement proper ARIA attributes for accessibility in React components
Use proper heading hierarchy in React components
Implement proper form labels in React components
Use proper button types in React components
Implement proper focus management for keyboard navigation in React components
Use proper keyboard shortcuts in React components
Implement proper tab order in React components
Use proper ...

Files:

  • packages/clerk-js/src/ui/Components.tsx
  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx
  • packages/clerk-js/src/ui/lazyModules/providers.tsx
  • packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx
**/index.ts

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

Avoid barrel files (index.ts re-exports) as they can cause circular dependencies

Files:

  • packages/shared/src/types/index.ts
🧬 Code graph analysis (4)
packages/clerk-js/src/ui/Components.tsx (4)
packages/shared/src/types/clerk.ts (2)
  • __internal_EnableOrganizationsPromptProps (1449-1459)
  • UserProfileProps (1565-1603)
packages/clerk-js/src/ui/lazyModules/providers.tsx (1)
  • LazyEnableOrganizationsPromptProvider (212-227)
packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx (1)
  • EnableOrganizationsPrompt (278-284)
packages/clerk-js/src/ui/lazyModules/components.ts (1)
  • EnableOrganizationsPrompt (49-51)
packages/react/src/isomorphicClerk.ts (1)
packages/shared/src/types/clerk.ts (3)
  • __internal_EnableOrganizationsPromptProps (1449-1459)
  • __internal_AttemptToEnableEnvironmentSettingParams (1461-1472)
  • __internal_AttemptToEnableEnvironmentSettingResult (1474-1476)
packages/clerk-js/src/ui/lazyModules/providers.tsx (3)
packages/shared/src/types/appearance.ts (1)
  • Appearance (1057-1131)
packages/clerk-js/src/ui/router/VirtualRouter.tsx (1)
  • VirtualRouter (15-67)
packages/clerk-js/src/ui/customizables/index.ts (1)
  • AppearanceProvider (9-9)
packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx (6)
packages/shared/src/types/clerk.ts (1)
  • __internal_EnableOrganizationsPromptProps (1449-1459)
packages/shared/src/types/devtools.ts (1)
  • EnableEnvironmentSettingParams (3-6)
packages/clerk-js/src/core/resources/DevTools.ts (1)
  • DevTools (8-21)
packages/clerk-js/src/ui/elements/Modal.tsx (1)
  • Modal (26-111)
packages/clerk-js/src/ui/components/devPrompts/shared.tsx (1)
  • PromptContainer (10-28)
packages/clerk-js/src/ui/elements/Switch.tsx (1)
  • Switch (15-108)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Build Packages
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (10)
packages/clerk-js/bundlewatch.config.json (2)

4-6: Bundle size increases are reasonable for the new development modal feature.

The modest increases (+2KB for browser variants, +4KB for the legacy variant) align with adding a new UI component and associated DevTools integration logic.


26-26: New entry follows established patterns.

The new enableOrganizationsPrompt*.js entry is correctly named, placed near related prompt components (keylessPrompt), and sized consistently with similar modular UI components.

packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx (1)

8-17: Imports now correctly rely on shared prompt primitives

Switching to PromptContainer, PromptSuccessIcon, ClerkLogoIcon, handleDashboardUrlParsing, and basePromptElementStyles from ../shared keeps this prompt aligned with the new shared dev-prompt system and avoids duplicating styling/utility logic. No issues spotted with these imports or their usage.

packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/use-revalidate-environment.ts (1)

4-6: Import path and typing adjustments look correct

Switching to explicit Clerk/Environment type imports from core and updating the useEnvironment path are consistent with the existing usage and do not change runtime behavior. No issues here.

packages/shared/src/types/index.ts (1)

15-15: DevTools types export is consistent with existing type barrel

Re-exporting ./devtools here matches the established pattern in this file and correctly surfaces the new DevTools types to consumers of @clerk/shared/types. No issues.

packages/shared/src/types/appearance.ts (1)

1038-1130: New enable-organizations appearance types follow existing pattern; ensure key alignment

Adding EnableOrganizationsTheme = Theme and the enableOrganizations?: T; property on Appearance<T> is consistent with how other component‑specific themes are modeled (e.g. signIn, organizationList, taskChooseOrganization).

Given this, the value passed as appearanceKey for the new prompt should be 'enableOrganizations' so that globalAppearance.enableOrganizations is actually picked up in the appearance cascade. Right now parseAppearance and the lazy provider use 'enableOrganizationsPrompt', which won’t match this property—see the comment in parseAppearance.ts for the suggested alignment.

packages/shared/src/organization.ts (1)

1-4: Internal React hook for attempting organizations enablement looks sound

useAttemptToEnableOrganizations cleanly wraps the internal __internal_attemptToEnableEnvironmentSetting call with a useRef guard and useEffect, ensuring the attempt runs at most once per hook instance and remains compatible with older clerk-js versions via optional chaining. This is a reasonable encapsulation for the React hooks (useOrganization, useOrganizationList) to share.

Also applies to: 22-44

packages/shared/src/types/devtools.ts (1)

1-13: DevTools resource typings look correct; double‑check param naming with backend

EnableEnvironmentSettingParams and DevToolsResource.__internal_enableEnvironmentSetting are modeled consistently with the rest of the shared types and DevTools resource patterns.

One thing to confirm: the optional field is named organization_allow_personal_accounts, whereas the PR description references an allow_personal_accounts field coming from clerk-go. Please verify that this name matches the backend endpoint contract so the PATCH body is accepted as expected.

packages/clerk-js/src/ui/components/devPrompts/EnableOrganizationsPrompt/index.tsx (1)

18-18: Verify dashboard URL with Clerk dashboard or team.

The hardcoded URL uses organizations-settings (plural). While web search indicates Clerk doesn't publish stable patterns for dashboard navigation URLs, the UI terminology uses "Organizations Settings page" (plural), which aligns with the current code. However, the exact path requires manual verification by accessing your Clerk dashboard directly or confirming with the Clerk team, as this pattern is not formally documented as a public stable API.

packages/clerk-js/src/core/clerk.ts (1)

22-29: New internal type imports look consistent

The added __internal_* types are correctly brought in via a type‑only import from @clerk/shared/types and align with the new internal methods introduced in this file. No changes needed here.

Comment on lines 27 to 31
export type AppearanceCascade = {
globalAppearance?: Appearance;
appearance?: Appearance;
appearanceKey: PublicAppearanceTopLevelKey | 'impersonationFab';
appearanceKey: PublicAppearanceTopLevelKey | 'impersonationFab' | 'enableOrganizationsPrompt';
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

appearanceKey for enable-organizations prompt does not match Appearance property

AppearanceCascade.appearanceKey now allows 'enableOrganizationsPrompt', but Appearance defines the component-specific theme as enableOrganizations?: T;. In parseAppearance, we index globalAppearance?.[appearanceKey as PublicAppearanceTopLevelKey], so when appearanceKey === 'enableOrganizationsPrompt' we end up looking for a non‑existent property and ignore any appearance.enableOrganizations overrides.

To make theming for the new prompt work as expected, the appearanceKey used by the provider should match the Appearance property (or vice versa). One minimal option in this file is:

-export type AppearanceCascade = {
-  globalAppearance?: Appearance;
-  appearance?: Appearance;
-  appearanceKey: PublicAppearanceTopLevelKey | 'impersonationFab' | 'enableOrganizationsPrompt';
-};
+export type AppearanceCascade = {
+  globalAppearance?: Appearance;
+  appearance?: Appearance;
+  // 'enableOrganizations' is already part of PublicAppearanceTopLevelKey
+  appearanceKey: PublicAppearanceTopLevelKey | 'impersonationFab';
+};

and then in LazyEnableOrganizationsPromptProvider pass appearanceKey="enableOrganizations" instead of "enableOrganizationsPrompt" so globalAppearance.enableOrganizations is honored. Alternatively, rename the Appearance property to enableOrganizationsPrompt if that’s the intended public name, but the two must be consistent.



---

🏁 Script executed:

```shell
#!/bin/bash
# Examine parseAppearance.ts file
echo "=== parseAppearance.ts ==="
cat packages/clerk-js/src/ui/customizables/parseAppearance.ts

Length of output: 5585


🏁 Script executed:

#!/bin/bash
# Find Appearance type definition
echo "=== Searching for Appearance type definition ==="
rg -n "type Appearance\s*=" --type ts --type tsx -A 20

Length of output: 76


🏁 Script executed:

#!/bin/bash
# Find PublicAppearanceTopLevelKey definition
echo "=== Searching for PublicAppearanceTopLevelKey ==="
rg -n "PublicAppearanceTopLevelKey" --type ts --type tsx -B 2 -A 10

Length of output: 77


🏁 Script executed:

#!/bin/bash
# Search for LazyEnableOrganizationsPromptProvider and its usage
echo "=== Searching for LazyEnableOrganizationsPromptProvider ==="
rg -n "LazyEnableOrganizationsPromptProvider\|enableOrganizationsPrompt" --type ts --type tsx -B 3 -A 3

Length of output: 87


🏁 Script executed:

#!/bin/bash
# Search for where appearanceKey is set to enableOrganizationsPrompt
echo "=== Searching for appearanceKey assignment ==="
rg -n "appearanceKey\s*=" --type ts --type tsx -B 2 -A 2

Length of output: 74



---

🏁 Script executed:

```shell
#!/bin/bash
# Find Appearance type in @clerk/shared
echo "=== Searching for Appearance type definition ==="
rg -n "type Appearance\s*=" -A 20

Length of output: 48


🏁 Script executed:

#!/bin/bash
# Search for LazyEnableOrganizationsPromptProvider
echo "=== Searching for LazyEnableOrganizationsPromptProvider ==="
rg -n "LazyEnableOrganizationsPromptProvider" -B 3 -A 10

Length of output: 3850


🏁 Script executed:

#!/bin/bash
# Search for enableOrganizationsPrompt usage
echo "=== Searching for enableOrganizationsPrompt ==="
rg -n "enableOrganizationsPrompt" -B 2 -A 2

Length of output: 6305


🏁 Script executed:

#!/bin/bash
# Search for enableOrganizations property in Appearance or related code
echo "=== Searching for enableOrganizations ==="
rg -n "enableOrganizations" -B 2 -A 2

Length of output: 7133


🏁 Script executed:

#!/bin/bash
# Check if @clerk/shared is in node_modules or source
fd -t f "appearance" --search-path . | head -20

Length of output: 689



---

🏁 Script executed:

```shell
#!/bin/bash
# Check Appearance type definition
echo "=== Appearance type definition ==="
cat packages/shared/src/types/appearance.ts | grep -A 100 "type Appearance = " | head -150

Length of output: 34


🏁 Script executed:

#!/bin/bash
# Verify what PublicAppearanceTopLevelKey would include
echo "=== Check if enableOrganizations is in Appearance ==="
rg -n "enableOrganizations\s*\?" packages/shared/src/types/appearance.ts -B 2 -A 2

Length of output: 196


appearanceKey for enable-organizations prompt does not match Appearance property

Verified: Appearance defines enableOrganizations?: T; (in packages/shared/src/types/appearance.ts line 1130), while AppearanceCascade (line 30) allows appearanceKey: 'enableOrganizationsPrompt'. In parseAppearance line 65, when indexing globalAppearance?.[appearanceKey as PublicAppearanceTopLevelKey] with 'enableOrganizationsPrompt', the property lookup returns undefined because Appearance has no such property. This means appearance.enableOrganizations theme overrides are never applied to the prompt.

The fix is to align the key with the actual Appearance property:

  1. Remove 'enableOrganizationsPrompt' from AppearanceCascade.appearanceKey union (it's redundant since 'enableOrganizations' is already part of PublicAppearanceTopLevelKey)
  2. In LazyEnableOrganizationsPromptProvider (packages/clerk-js/src/ui/lazyModules/providers.tsx line 220), change appearanceKey={'enableOrganizationsPrompt'} to appearanceKey={'enableOrganizations'}
🤖 Prompt for AI Agents
In packages/clerk-js/src/ui/customizables/parseAppearance.ts around lines 27-31,
the AppearanceCascade.appearanceKey union incorrectly includes
'enableOrganizationsPrompt' which does not match the actual Appearance property
name; remove 'enableOrganizationsPrompt' from the appearanceKey union so only
the real Appearance keys (including 'enableOrganizations') are allowed. Also
update packages/clerk-js/src/ui/lazyModules/providers.tsx around line 220 to
pass appearanceKey={'enableOrganizations'} instead of
appearanceKey={'enableOrganizationsPrompt'} so parseAppearance indexes the
correct Appearance property and theme overrides are applied.

Comment on lines +212 to +227
export const LazyEnableOrganizationsPromptProvider = (
props: React.PropsWithChildren<{ globalAppearance: Appearance | undefined }>,
) => {
return (
<Suspense>
<VirtualRouter startPath=''>
<AppearanceProvider
globalAppearance={props.globalAppearance}
appearanceKey={'enableOrganizationsPrompt'}
>
{props.children}
</AppearanceProvider>
</VirtualRouter>
</Suspense>
);
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Provider wiring is good; align appearanceKey with Appearance.enableOrganizations

The new LazyEnableOrganizationsPromptProvider mirrors the existing impersonation provider and the VirtualRouter usage looks fine. The only issue is the appearanceKey:

<AppearanceProvider
  globalAppearance={props.globalAppearance}
  appearanceKey={'enableOrganizationsPrompt'}
>

Since the Appearance type exposes enableOrganizations?: T; as the theming slot for this surface, this key should be 'enableOrganizations' so that globalAppearance.enableOrganizations is actually picked up by the cascade:

-        <AppearanceProvider
-          globalAppearance={props.globalAppearance}
-          appearanceKey={'enableOrganizationsPrompt'}
-        >
+        <AppearanceProvider
+          globalAppearance={props.globalAppearance}
+          appearanceKey={'enableOrganizations'}
+        >

Combined with the adjusted AppearanceCascade.appearanceKey in parseAppearance.ts, this will make theming for the enable-organizations prompt consistent with the other components.

🤖 Prompt for AI Agents
In packages/clerk-js/src/ui/lazyModules/providers.tsx around lines 212 to 227,
the AppearanceProvider is using appearanceKey 'enableOrganizationsPrompt' which
doesn't match the Appearance type's slot name enableOrganizations; change the
appearanceKey to 'enableOrganizations' so that
globalAppearance.enableOrganizations is cascaded correctly (i.e., replace the
current string key with 'enableOrganizations' in the AppearanceProvider props).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
packages/clerk-js/src/core/clerk.ts (1)

787-799: Inconsistency: telemetry event still uses "Mounted" instead of "Opened".

Line 793 uses eventPrebuiltComponentMounted, but a previous review comment (marked "Addressed in commits 5966383 to 8fbc59c") flagged this exact line and recommended switching to eventPrebuiltComponentOpened for consistency with other modal methods like openSignIn, openCheckout, etc. The code hasn't been updated.

Apply this diff to align with other modal telemetry:

-    this.telemetry?.record(eventPrebuiltComponentMounted('EnableOrganizationsPrompt', props));
+    this.telemetry?.record(eventPrebuiltComponentOpened('EnableOrganizationsPrompt', props));
🧹 Nitpick comments (1)
packages/clerk-js/src/core/clerk.ts (1)

872-885: Verify error-throwing pattern in onClose callbacks is intentional.

All modified organization methods (OrganizationProfile, CreateOrganization, OrganizationSwitcher, OrganizationList, TaskChooseOrganization) follow the same pattern: they call __internal_attemptToEnableEnvironmentSetting with an onClose callback that throws a ClerkRuntimeError when the prompt is dismissed.

This means:

  • If a developer calls e.g. clerk.openOrganizationProfile() in development with organizations disabled, a prompt appears.
  • If the developer closes the prompt without enabling organizations, an error is thrown after the modal closes.

Confirm this is the intended UX. Typically, errors are thrown before opening a modal (to prevent it from opening), not after closing it. If this is intentional, consider adding a code comment explaining why the error is deferred to the onClose callback.

Based on relevant code snippets and past review context.

Also applies to: 909-922, 1058-1071, 1105-1118, 1143-1156, 1189-1202, 1392-1404

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e3da555 and a0c0716.

📒 Files selected for processing (1)
  • packages/clerk-js/src/core/clerk.ts (10 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

All code must pass ESLint checks with the project's configuration

Files:

  • packages/clerk-js/src/core/clerk.ts
**/*.{js,jsx,ts,tsx,json,md,yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/clerk-js/src/core/clerk.ts
packages/**/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/clerk-js/src/core/clerk.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Follow established naming conventions (PascalCase for components, camelCase for variables)

Prefer importing types from @clerk/shared/types instead of the deprecated @clerk/types alias

Files:

  • packages/clerk-js/src/core/clerk.ts
packages/**/src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

packages/**/src/**/*.{ts,tsx,js,jsx}: Maintain comprehensive JSDoc comments for public APIs
Use tree-shaking friendly exports
Validate all inputs and sanitize outputs
All public APIs must be documented with JSDoc
Use dynamic imports for optional features
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Implement proper logging with different levels

Files:

  • packages/clerk-js/src/core/clerk.ts
**/*.ts?(x)

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

Files:

  • packages/clerk-js/src/core/clerk.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Implement type guards for unknown types using the pattern function isType(value: unknown): value is Type
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details in classes
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Use mixins for shared behavior across unrelated classes in TypeScript
Use generic constraints with bounded type parameters like <T extends { id: string }>
Use utility types like Omit, Partial, and Pick for data transformation instead of manual type construction
Use discriminated unions instead of boolean flags for state management and API responses
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation at the type level
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Document functions with JSDoc comments including @param, @returns, @throws, and @example tags
Create custom error classes that extend Error for specific error types
Use the Result pattern for error handling instead of throwing exceptions
Use optional chaining (?.) and nullish coalescing (??) operators for safe property access
Let TypeScript infer obvious types to reduce verbosity
Use const assertions with as const for literal types
Use satisfies operator for type checking without widening types
Declare readonly arrays and objects for immutable data structures
Use spread operator and array spread for immutable updates instead of mutations
Use lazy loading for large types...

Files:

  • packages/clerk-js/src/core/clerk.ts
🧬 Code graph analysis (1)
packages/clerk-js/src/core/clerk.ts (3)
packages/shared/src/types/clerk.ts (2)
  • __internal_AttemptToEnableEnvironmentSettingParams (1461-1472)
  • __internal_AttemptToEnableEnvironmentSettingResult (1474-1476)
packages/clerk-js/src/utils/componentGuards.ts (1)
  • disabledOrganizationsFeature (21-23)
packages/shared/src/telemetry/events/component-mounted.ts (1)
  • eventPrebuiltComponentMounted (69-75)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build Packages
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
packages/clerk-js/src/core/clerk.ts (2)

25-28: LGTM on new type imports.

The new internal type imports for the environment setting enablement flow are correctly added and follow TypeScript naming conventions.


751-785: Add explicit return type and verify type safety of the cast.

Three issues with this method:

  1. Missing explicit return type annotation (Line 751-753): Per coding guidelines, "Always define explicit return types for functions, especially public APIs." Add : __internal_AttemptToEnableEnvironmentSettingResult to the method signature.

  2. Unsafe type assertion (Line 777): The as __internal_EnableOrganizationsPromptProps cast was flagged in a previous review but remains unaddressed. This cast bypasses TypeScript's type checking when caller includes union members like 'CreateOrganization' or 'TaskChooseOrganization' that may not be present in __internal_EnableOrganizationsPromptProps['caller']. If the types don't align, the prompt component could receive unexpected caller values.

  3. Silent failure in non-dev environments (Lines 770-780): When organizations are disabled in production/staging, the method returns { isEnabled: false } without any user-facing feedback. Confirm this is intentional—if developers expect production to guard against disabled organizations, document this behavior or consider adding a warning.

Apply this fix for the return type:

-  public __internal_attemptToEnableEnvironmentSetting = (
-    params: __internal_AttemptToEnableEnvironmentSettingParams,
-  ): __internal_AttemptToEnableEnvironmentSettingResult => {
+  public __internal_attemptToEnableEnvironmentSetting = (
+    params: __internal_AttemptToEnableEnvironmentSettingParams,
+  ): __internal_AttemptToEnableEnvironmentSettingResult => {

For the type cast, verify that __internal_EnableOrganizationsPromptProps['caller'] includes all members from __internal_AttemptToEnableEnvironmentSettingParams['caller'], then remove the as assertion:

-          this.__internal_openEnableOrganizationsPrompt({
-            caller,
-            // Reload current window to all invalidate all resources
-            // related to organizations, eg: roles
-            onSuccess: () => window.location.reload(),
-            onClose: params.onClose,
-          } as __internal_EnableOrganizationsPromptProps);
+          this.__internal_openEnableOrganizationsPrompt({
+            caller,
+            // Reload current window to invalidate all resources
+            // related to organizations, eg: roles
+            onSuccess: () => window.location.reload(),
+            onClose: params.onClose,
+          });

Likely an incorrect or invalid review comment.

@LauraBeatris
Copy link
Member Author

!snapshot

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/clerk-js/src/core/clerk.ts (1)

773-773: Fix typo in comment.

The comment reads "to all invalidate" but should be "to invalidate".

Apply this diff:

-            // Reload current window to all invalidate all resources
+            // Reload current window to invalidate all resources
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a0c0716 and 21d53a9.

📒 Files selected for processing (1)
  • packages/clerk-js/src/core/clerk.ts (9 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

All code must pass ESLint checks with the project's configuration

Files:

  • packages/clerk-js/src/core/clerk.ts
**/*.{js,jsx,ts,tsx,json,md,yml,yaml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/clerk-js/src/core/clerk.ts
packages/**/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/clerk-js/src/core/clerk.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Follow established naming conventions (PascalCase for components, camelCase for variables)

Prefer importing types from @clerk/shared/types instead of the deprecated @clerk/types alias

Files:

  • packages/clerk-js/src/core/clerk.ts
packages/**/src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

packages/**/src/**/*.{ts,tsx,js,jsx}: Maintain comprehensive JSDoc comments for public APIs
Use tree-shaking friendly exports
Validate all inputs and sanitize outputs
All public APIs must be documented with JSDoc
Use dynamic imports for optional features
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Implement proper logging with different levels

Files:

  • packages/clerk-js/src/core/clerk.ts
**/*.ts?(x)

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

Files:

  • packages/clerk-js/src/core/clerk.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Implement type guards for unknown types using the pattern function isType(value: unknown): value is Type
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details in classes
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Use mixins for shared behavior across unrelated classes in TypeScript
Use generic constraints with bounded type parameters like <T extends { id: string }>
Use utility types like Omit, Partial, and Pick for data transformation instead of manual type construction
Use discriminated unions instead of boolean flags for state management and API responses
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation at the type level
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Document functions with JSDoc comments including @param, @returns, @throws, and @example tags
Create custom error classes that extend Error for specific error types
Use the Result pattern for error handling instead of throwing exceptions
Use optional chaining (?.) and nullish coalescing (??) operators for safe property access
Let TypeScript infer obvious types to reduce verbosity
Use const assertions with as const for literal types
Use satisfies operator for type checking without widening types
Declare readonly arrays and objects for immutable data structures
Use spread operator and array spread for immutable updates instead of mutations
Use lazy loading for large types...

Files:

  • packages/clerk-js/src/core/clerk.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build Packages
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (2)
packages/clerk-js/src/core/clerk.ts (2)

766-768: Verify intended production behavior when organizations are disabled.

When organizations are disabled in non-development environments, the method returns { isEnabled: true } and allows components to mount. This means production/staging apps with disabled organizations won't show the prompt and will silently proceed.

Confirm this is intentional: does the system rely on backend guards or other component-level error handling in production when organizations are actually disabled?


751-753: Add explicit return type to the method signature.

The method lacks an explicit return type in its declaration. Per coding guidelines, all functions (especially public/internal APIs) should have explicit return types.

Apply this diff:

-  public __internal_attemptToEnableEnvironmentSetting = (
-    params: __internal_AttemptToEnableEnvironmentSettingParams,
-  ): __internal_AttemptToEnableEnvironmentSettingResult => {
+  public __internal_attemptToEnableEnvironmentSetting(
+    params: __internal_AttemptToEnableEnvironmentSettingParams,
+  ): __internal_AttemptToEnableEnvironmentSettingResult {

Likely an incorrect or invalid review comment.

// related to organizations, eg: roles
onSuccess: () => window.location.reload(),
onClose: params.onClose,
} as __internal_EnableOrganizationsPromptProps);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove type assertion to maintain type safety.

The as __internal_EnableOrganizationsPromptProps cast was flagged in past reviews but remains unaddressed. This assertion bypasses TypeScript's type checking and can hide incompatibilities between __internal_AttemptToEnableEnvironmentSettingParams['caller'] and __internal_EnableOrganizationsPromptProps['caller'].

From the past review context: the caller union in the params includes values like 'CreateOrganization' and 'TaskChooseOrganization', which may not be present in the prompt props type. The cast hides this mismatch.

Based on relevant code snippets and past reviews.

Apply this approach:

  1. Ensure __internal_EnableOrganizationsPromptProps['caller'] accepts all values that __internal_AttemptToEnableEnvironmentSettingParams['caller'] can have
  2. Remove the type assertion so the compiler enforces compatibility:
-          } as __internal_EnableOrganizationsPromptProps);
+          });

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/clerk-js/src/core/clerk.ts around line 777, remove the unsafe "as
__internal_EnableOrganizationsPromptProps" type assertion and make the compiler
enforce compatibility by ensuring the prompt props' caller type includes every
member of __internal_AttemptToEnableEnvironmentSettingParams['caller']; update
__internal_EnableOrganizationsPromptProps to reference or extend the same union
type (or create a shared alias) so the assignment is directly assignable without
a cast, then delete the assertion on that line.

.ensureMounted({ preloadHint: 'EnableOrganizationsPrompt' })
.then(controls => controls.openModal('enableOrganizationsPrompt', props || {}));

this.telemetry?.record(eventPrebuiltComponentMounted('EnableOrganizationsPrompt', props));
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Telemetry event type is inconsistent despite past review being marked as addressed.

A past review identified that this line should use eventPrebuiltComponentOpened instead of eventPrebuiltComponentMounted for consistency with other modal methods like openSignIn, openCheckout, etc. The review was marked as "Addressed in commits 5966383 to 8fbc59c", but the code still shows eventPrebuiltComponentMounted.

This inconsistency means analytics will report "component mounted" rather than "prompt shown", which doesn't match the semantics of opening a modal.

Apply this diff:

-    this.telemetry?.record(eventPrebuiltComponentMounted('EnableOrganizationsPrompt', props));
+    this.telemetry?.record(eventPrebuiltComponentOpened('EnableOrganizationsPrompt', props));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.telemetry?.record(eventPrebuiltComponentMounted('EnableOrganizationsPrompt', props));
this.telemetry?.record(eventPrebuiltComponentOpened('EnableOrganizationsPrompt', props));
🤖 Prompt for AI Agents
In packages/clerk-js/src/core/clerk.ts around line 793, the telemetry call uses
eventPrebuiltComponentMounted but should use eventPrebuiltComponentOpened to
match semantics of showing/opening prompts; update the call to
this.telemetry?.record(eventPrebuiltComponentOpened('EnableOrganizationsPrompt',
props)) keeping the optional chaining and same props argument so analytics
report "prompt opened" consistently with other modal methods.

@clerk-cookie
Copy link
Collaborator

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

Package Version
@clerk/agent-toolkit 0.2.5-snapshot.v20251124170822
@clerk/astro 2.16.3-snapshot.v20251124170822
@clerk/backend 2.24.0-snapshot.v20251124170822
@clerk/chrome-extension 2.8.5-snapshot.v20251124170822
@clerk/clerk-js 5.110.0-snapshot.v20251124170822
@clerk/elements 0.23.86-snapshot.v20251124170822
@clerk/clerk-expo 2.19.5-snapshot.v20251124170822
@clerk/expo-passkeys 0.4.22-snapshot.v20251124170822
@clerk/express 1.7.53-snapshot.v20251124170822
@clerk/fastify 2.6.5-snapshot.v20251124170822
@clerk/localizations 3.28.4-snapshot.v20251124170822
@clerk/nextjs 6.35.5-snapshot.v20251124170822
@clerk/nuxt 1.13.3-snapshot.v20251124170822
@clerk/clerk-react 5.57.0-snapshot.v20251124170822
@clerk/react-router 2.2.5-snapshot.v20251124170822
@clerk/remix 4.13.20-snapshot.v20251124170822
@clerk/shared 3.36.0-snapshot.v20251124170822
@clerk/tanstack-react-start 0.27.5-snapshot.v20251124170822
@clerk/testing 1.13.19-snapshot.v20251124170822
@clerk/themes 2.4.40-snapshot.v20251124170822
@clerk/types 4.101.3-snapshot.v20251124170822
@clerk/vue 1.17.0-snapshot.v20251124170822

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

npm i @clerk/agent-toolkit@0.2.5-snapshot.v20251124170822 --save-exact

@clerk/astro

npm i @clerk/astro@2.16.3-snapshot.v20251124170822 --save-exact

@clerk/backend

npm i @clerk/backend@2.24.0-snapshot.v20251124170822 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@2.8.5-snapshot.v20251124170822 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@5.110.0-snapshot.v20251124170822 --save-exact

@clerk/elements

npm i @clerk/elements@0.23.86-snapshot.v20251124170822 --save-exact

@clerk/clerk-expo

npm i @clerk/clerk-expo@2.19.5-snapshot.v20251124170822 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@0.4.22-snapshot.v20251124170822 --save-exact

@clerk/express

npm i @clerk/express@1.7.53-snapshot.v20251124170822 --save-exact

@clerk/fastify

npm i @clerk/fastify@2.6.5-snapshot.v20251124170822 --save-exact

@clerk/localizations

npm i @clerk/localizations@3.28.4-snapshot.v20251124170822 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@6.35.5-snapshot.v20251124170822 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@1.13.3-snapshot.v20251124170822 --save-exact

@clerk/clerk-react

npm i @clerk/clerk-react@5.57.0-snapshot.v20251124170822 --save-exact

@clerk/react-router

npm i @clerk/react-router@2.2.5-snapshot.v20251124170822 --save-exact

@clerk/remix

npm i @clerk/remix@4.13.20-snapshot.v20251124170822 --save-exact

@clerk/shared

npm i @clerk/shared@3.36.0-snapshot.v20251124170822 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@0.27.5-snapshot.v20251124170822 --save-exact

@clerk/testing

npm i @clerk/testing@1.13.19-snapshot.v20251124170822 --save-exact

@clerk/themes

npm i @clerk/themes@2.4.40-snapshot.v20251124170822 --save-exact

@clerk/types

npm i @clerk/types@4.101.3-snapshot.v20251124170822 --save-exact

@clerk/vue

npm i @clerk/vue@1.17.0-snapshot.v20251124170822 --save-exact

@LauraBeatris LauraBeatris merged commit f85abda into main Nov 24, 2025
46 checks passed
@LauraBeatris LauraBeatris deleted the laura/enable-orgs branch November 24, 2025 17:33
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