Skip to content

Conversation

wobsoriano
Copy link
Member

@wobsoriano wobsoriano commented Aug 28, 2025

Description

This PR introduces clerkMiddleware(), which is based on the new React Router middleware. It authenticates once per request and enables streaming in the root loader.

DX guide for more info

Deprecation

  • Using rootAuthLoader without middleware will be removed in the next major.
  • /api.server and /ssr.server module exports is deprecated in favor of @clerk/react-router/server and will be removed in the next major.

Migration

Migration is easy; they'll just need to export a middleware in their root route alongside the rootAuthLoader:

Before:

import { clerkMiddleware, rootAuthLoader } from '@clerk/react-router/server'

export const loader = (args: Route.LoaderArgs) => rootAuthLoader(args)

After:

import { clerkMiddleware, rootAuthLoader } from '@clerk/react-router/server'

export const middleware: Route.MiddlewareFunction[] = [clerkMiddleware()]

export const loader = (args: Route.LoaderArgs) => rootAuthLoader(args)

Even though this change is backwards compatible, we want a major bump since we bumped the minimum required React Router versions to ^7.9.0 for stable Middleware and Context APIs.

Tests

Added unit and integration tests that covers both legacy (rootAuthLoader only) and with middleware flows.

Resolves USER-3317, USER-3141 and USER-2693

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
    • Adds React Router middleware support plus a new server API surface to enable better performance and streaming.
  • Deprecations
    • Emits migration warnings and guidance for legacy SSR/API imports; using the old root loader without middleware is deprecated.
  • Templates
    • Upgrades React and React Router (Node template → React 19), enables v8_middleware by default, and simplifies protected-route loader data shape.
  • Tests
    • Adds unit and end-to-end tests covering middleware and pre-middleware scenarios.
  • Chores
    • Dependency upgrades, removal of older integration dependency from some templates, and integration test script switched to pnpm.

Copy link

changeset-bot bot commented Aug 28, 2025

🦋 Changeset detected

Latest commit: dcf85d4

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

This PR includes changesets to release 1 package
Name Type
@clerk/react-router Major

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

Copy link

vercel bot commented Aug 28, 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 Sep 26, 2025 10:08pm

Copy link
Contributor

coderabbitai bot commented Aug 28, 2025

Walkthrough

Introduces server-side middleware and context-based auth for @clerk/react-router, adds a server subpath export, moves client/getAuth to server, removes legacy SSR rootAuthLoader/getAuth, updates types/utilities for middleware opt-in, adjusts integration templates/configs, adds tests and migration docs.

Changes

Cohort / File(s) Summary
Changeset & Docs
.changeset/quiet-bats-protect.md
New changeset documenting major release: introduces clerkMiddleware(), deprecates rootAuthLoader SSR import path, provides migration and streaming examples.
Public exports & package manifest
packages/react-router/package.json, packages/react-router/src/server/index.ts
Adds ./server export path and types mapping; re-exports backend/server utilities from server index.
Server middleware & auth core
packages/react-router/src/server/clerkMiddleware.ts, packages/react-router/src/server/getAuth.ts, packages/react-router/src/server/clerkClient.ts, packages/react-router/src/server/legacyAuthenticateRequest.ts, packages/react-router/src/server/loadOptions.ts, packages/react-router/src/server/types.ts, packages/react-router/src/server/utils.ts
Adds clerkMiddleware and contexts (authFnContext, requestStateContext); introduces clerkClient factory; implements getAuth that prefers middleware context and falls back to legacy auth; renames internal authenticateRequest → legacyAuthenticateRequest; updates loadOptions/types to middleware DataFunctionArgs, adds ClerkMiddlewareOptions/AuthLoaderOptions, adds IsOptIntoMiddleware and conditional header injection.
SSR surface & deprecation
packages/react-router/src/ssr/index.ts, packages/react-router/src/ssr/getAuth.ts (removed), packages/react-router/src/ssr/rootAuthLoader.ts (removed), packages/react-router/src/utils/errors.ts, packages/react-router/src/api/index.ts
Removes old SSR implementations (rootAuthLoader, SSR getAuth); SSR entry now re-exports server modules and logs one-time deprecation warnings; updates error messages and adds middleware migration examples; adds runtime deprecation warning for api.server.
Tests
packages/react-router/src/server/__tests__/getAuth.test.ts, packages/react-router/src/server/__tests__/clerkMiddleware.test.ts, packages/react-router/src/__tests__/exports.test.ts, integration/tests/react-router/basic.test.ts, integration/tests/react-router/pre-middleware.test.ts
Adds unit tests for middleware and getAuth behavior; updates exports tests to assert server exports and SSR deprecation; adds E2E pre-middleware integration test and adjusts test labels.
Integration templates & sample app
integration/templates/react-router-node/package.json, integration/templates/react-router-library/package.json, integration/templates/react-router-node/react-router.config.ts, integration/templates/react-router-node/app/root.tsx, integration/templates/react-router-node/app/routes/protected.tsx
Removes @clerk/react-router from template deps, upgrades React/React Router and toolchain, enables future.v8_middleware in config, adds commented middleware placeholder in template root, updates protected route loader return shape and UI usage.
Tooling & scripts / minor refactor
package.json, integration/presets/utils.ts
Changes integration test invocation to use pnpm and minor formatting-only refactor in preset util.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant RR as React Router
  participant MW as clerkMiddleware
  participant CC as ClerkClient
  participant LD as Loader / getAuth

  U->>RR: HTTP Request
  RR->>MW: run middleware chain
  MW->>CC: authenticateRequest(patched request, options)
  alt Clerk returns Location (redirect)
    MW-->>RR: 307 Redirect + Clerk headers
    RR-->>U: Redirect response
  else Handshake without redirect
    MW-->>RR: throw error (handshake)
  else Auth available
    MW->>RR: set requestStateContext & authFnContext
    MW-->>RR: next()
    RR->>LD: loader/getAuth executes
    LD->>RR: check authFnContext
    alt Context present
      LD-->>RR: call authFn → AuthObject (no new authenticateRequest)
    else Context missing
      LD->>CC: legacyAuthenticateRequest()
      CC-->>LD: requestState.toAuth()
    end
    RR-->>U: Response (propagate Clerk headers if present)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

In burrows of bytes I hop and mull,
A middleware stitch that keeps calls small.
Context shares one truth across the lane,
Old loaders bow; new streams remain.
Hop on — auth's now shared, not doubled. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The PR includes unrelated modifications such as changing the loader return shape and UI in the sample route integration/templates/react-router-node/app/routes/protected.tsx, updating the CI script in package.json to use pnpm, and a formatting tweak in integration/presets/utils.ts that fall outside the middleware and context objectives. Separate the sample app data-shape change, CI script update, and formatting edits into their own PR or justify their necessity in this context so that this pull request remains focused on the middleware and context implementation.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly and concisely describes the primary feature added by this pull request, which is the introduction of middleware and context support in the React Router integration. It accurately reflects the main change without extra noise.
Linked Issues Check ✅ Passed This change fully implements the middleware authentication feature with clerkMiddleware and React Router contexts to avoid duplicate authenticateRequest calls (USER-3317), reuses the middleware’s auth object in getAuth to reduce machine verification (USER-3141), and retains an async root loader that supports promise returns for streaming scenarios (USER-2693). All coding objectives from the linked issues are met with appropriate implementation and accompanying tests.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch rob/user-3317-bu

📜 Recent 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 dd59d14 and 4ebbc93.

📒 Files selected for processing (1)
  • package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
⏰ 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). (7)
  • GitHub Check: Unit Tests (18, --filter=@clerk/astro --filter=@clerk/backend --filter=@clerk/express --filter=@c...
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan

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

@wobsoriano wobsoriano changed the title feat(react-router): Introduce middleware feat(react-router): [WIP] Introduce middleware Aug 28, 2025
Copy link

pkg-pr-new bot commented Aug 28, 2025

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@6660

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@6660

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@6660

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@6660

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@6660

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@6660

@clerk/elements

npm i https://pkg.pr.new/@clerk/elements@6660

@clerk/clerk-expo

npm i https://pkg.pr.new/@clerk/clerk-expo@6660

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@6660

@clerk/express

npm i https://pkg.pr.new/@clerk/express@6660

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@6660

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@6660

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@6660

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@6660

@clerk/clerk-react

npm i https://pkg.pr.new/@clerk/clerk-react@6660

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@6660

@clerk/remix

npm i https://pkg.pr.new/@clerk/remix@6660

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@6660

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@6660

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@6660

@clerk/themes

npm i https://pkg.pr.new/@clerk/themes@6660

@clerk/types

npm i https://pkg.pr.new/@clerk/types@6660

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@6660

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@6660

commit: dcf85d4

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: 13

Caution

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

⚠️ Outside diff range comments (2)
packages/react-router/src/server/types.ts (1)

15-40: Avoid defaulting generics to any in public types (outside selected range included below)

Current defaults elsewhere use “= any”, which weakens consumer DX. Prefer a concrete default or unknown and narrow.

Outside this hunk, update generic defaults:

- export type LoaderFunctionArgsWithAuth<Options extends RootAuthLoaderOptions = any> = LoaderFunctionArgs & {
+ export type LoaderFunctionArgsWithAuth<Options extends RootAuthLoaderOptions = RootAuthLoaderOptions> = LoaderFunctionArgs & {
   request: RequestWithAuth<Options>;
 };
 
- export type RequestWithAuth<Options extends RootAuthLoaderOptions = any> = LoaderFunctionArgs['request'] & {
+ export type RequestWithAuth<Options extends RootAuthLoaderOptions = RootAuthLoaderOptions> = LoaderFunctionArgs['request'] & {
   auth: Omit<SignedInAuthObject | SignedOutAuthObject, 'session' | 'user' | 'organization'>;
 } & (Options extends { loadSession: true } ? { session: Session | null } : object) &
   (Options extends { loadUser: true } ? { user: User | null } : object) &
   (Options extends { loadOrganization: true } ? { organization: Organization | null } : object);
packages/react-router/src/server/legacyAuthenticateRequest.ts (1)

16-34: Bug: acceptsToken is dropped; pass it through to authenticateRequest

acceptsToken from opts isn’t forwarded, changing auth source semantics. Include it in the options passed to authenticateRequest.

Apply this diff:

-  const { audience, authorizedParties } = opts;
+  const { audience, authorizedParties, acceptsToken } = opts;
@@
-  const requestState = await clerkClient(args).authenticateRequest(patchRequest(request), {
+  const requestState = await clerkClient(args).authenticateRequest(patchRequest(request), {
@@
-    afterSignUpUrl,
+    afterSignUpUrl,
+    acceptsToken,
   });
🧹 Nitpick comments (19)
packages/react-router/src/utils/errors.ts (1)

120-124: Tighten wording/quotes in warning

Minor polish: drop the leading single quote before "clerkMiddleware()".

Apply:

-export const middlewareMigrationWarning = createErrorMessage(`
-'"clerkMiddleware()" not detected.
+export const middlewareMigrationWarning = createErrorMessage(`
+"clerkMiddleware()" not detected.
packages/react-router/src/server/types.ts (2)

15-40: Document signInUrl/signUpUrl and generalize env-var notes; options shape looks good

Add JSDoc for signInUrl/signUpUrl and avoid Vite-specific wording so docs match Node/Workers too.

 export type ClerkMiddlewareOptions = {
   /**
-   * Used to override the default VITE_CLERK_PUBLISHABLE_KEY env variable if needed.
+   * Overrides the default publishable key resolved from env/context
+   * (e.g. CLERK_PUBLISHABLE_KEY, VITE_CLERK_PUBLISHABLE_KEY, NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY).
    */
   publishableKey?: string;
   /**
-   * Used to override the CLERK_JWT_KEY env variable if needed.
+   * Overrides the JWT key resolved from env/context (CLERK_JWT_KEY).
    */
   jwtKey?: string;
   /**
-   * Used to override the CLERK_SECRET_KEY env variable if needed.
+   * Overrides the secret key resolved from env/context (CLERK_SECRET_KEY).
    */
   secretKey?: string;
   /**
-   * Used to override the CLERK_MACHINE_SECRET_KEY env variable if needed.
+   * Overrides the machine secret key resolved from env/context (CLERK_MACHINE_SECRET_KEY).
    */
   machineSecretKey?: string;
+  /**
+   * Absolute URL to your Sign In route. If omitted, resolved from env/context.
+   */
   signInUrl?: string;
+  /**
+   * Absolute URL to your Sign Up route. If omitted, resolved from env/context.
+   */
   signUpUrl?: string;
 } & Pick<VerifyTokenOptions, 'audience' | 'authorizedParties'> &
   MultiDomainAndOrProxy &
   SignInForceRedirectUrl &
   SignInFallbackRedirectUrl &
   SignUpForceRedirectUrl &
   SignUpFallbackRedirectUrl &
   LegacyRedirectProps;

Additionally, consider tightening the public docs for audience/authorizedParties by linking to VerifyTokenOptions.


42-55: Deprecation guidance is good; add “since” and planned removal version

Clarify migration timing for loadUser/loadSession/loadOrganization to set expectations.

 export type RootAuthLoaderOptions = ClerkMiddlewareOptions & {
   /**
-   * @deprecated Use [session token claims](https://clerk.com/docs/backend-requests/making/custom-session-token) instead.
+   * @deprecated Since vX.Y. Use custom session token claims instead.
+   * Will be removed in vZ.0.
    */
   loadUser?: boolean;
   /**
-   * @deprecated Use [session token claims](https://clerk.com/docs/backend-requests/making/custom-session-token) instead.
+   * @deprecated Since vX.Y. Use custom session token claims instead.
+   * Will be removed in vZ.0.
    */
   loadSession?: boolean;
   /**
-   * @deprecated Use [session token claims](https://clerk.com/docs/backend-requests/making/custom-session-token) instead.
+   * @deprecated Since vX.Y. Use custom session token claims instead.
+   * Will be removed in vZ.0.
    */
   loadOrganization?: boolean;
 };

If you have the timeline, replace X.Y/Z.0 accordingly.

packages/react-router/src/server/clerkClient.ts (2)

5-21: Consider memoizing the client per resolved options

If loadOptions resolves to the same values across requests, caching avoids re-instantiation. Key by a stable JSON of options that affect the client (apiUrl, secretKey, jwtKey, proxyUrl, isSatellite, domain, publishableKey, machineSecretKey).


5-21: Add explicit return type for clerkClient

  • Import ClerkClient from @clerk/backend and annotate clerkClient’s return type as ClerkClient.
integration/tests/react-router/basic.test.ts (1)

92-102: Prefer test IDs over text to reduce flakiness; consider unskipping when stable

Text-based assertions on “Loading...” and content can be brittle. Use data-testid hooks and extend timeout if CI is slow. Unskip when streaming is supported on all targets.

-test.skip('streaming with Suspense works with rootAuthLoader', async ({ page, context }) => {
+test.skip('streaming with Suspense works with rootAuthLoader', async ({ page, context }) => {
@@
-  await expect(u.page.getByText('Loading...')).toBeVisible();
+  await expect(u.page.getByTestId('non-critical-loading')).toBeVisible();
@@
-  await expect(u.page.getByText('Non critical value: non-critical')).toBeVisible({ timeout: 3000 });
-  await expect(u.page.getByText('Loading...')).toBeHidden();
+  await expect(u.page.getByTestId('non-critical-value')).toHaveText('Non critical value: non-critical', { timeout: 5000 });
+  await expect(u.page.getByTestId('non-critical-loading')).toBeHidden();

Add the corresponding data-testid attributes in the app under test.

packages/react-router/src/server/__tests__/rootAuthLoader.test.ts (1)

47-66: Add expectations on returned value shape to increase coverage

Verify that the handler is invoked and the data path returns expected structure, and that headers are preserved when legacy path returns a redirect-less signed-in state.

-  await rootAuthLoader(args, () => ({ data: 'test' }));
+  const res = (await rootAuthLoader(args, () => ({ data: 'test' }))) as any;
+  expect(res).toMatchObject({ data: 'test' });

For the legacy path case, also assert the mocked headers/status propagate if applicable.

packages/react-router/src/server/index.ts (1)

1-4: Avoid export * barrel; prefer explicit, tree-shakable exports to reduce circular-deps risk

Re-exporting the entire backend surface from an index barrel can hinder tree-shaking and increase the chance of cycles. Prefer explicit named re-exports and separate type-only re-exports.

Please confirm no circular import graph is introduced by this star export (common with index barrels). If needed, I can generate a script to map the import graph.

packages/react-router/src/server/__tests__/getAuth.test.ts (3)

18-21: Clean up env after tests

Unset CLERK_SECRET_KEY post-test to avoid cross-test leakage.

Apply:

-import { beforeEach, describe, expect, it, vi } from 'vitest';
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

 beforeEach(() => {
   vi.clearAllMocks();
   process.env.CLERK_SECRET_KEY = 'sk_test_...';
 });

+afterEach(() => {
+  delete process.env.CLERK_SECRET_KEY;
+});

36-39: Assert return value for stronger signal

Also verify the returned auth object.

-    await getAuth(args);
-
-    expect(legacyAuthenticateRequest).not.toHaveBeenCalled();
+    const res = await getAuth(args);
+    expect(res.userId).toBe('user_xxx');
+    expect(legacyAuthenticateRequest).not.toHaveBeenCalled();

51-54: Assert return value in legacy path

Tighten the expectation to ensure getAuth returns the expected shape.

-    await getAuth(args);
-
-    expect(legacyAuthenticateRequest).toHaveBeenCalled();
+    const res = await getAuth(args);
+    expect(res.userId).toBe('user_xxx');
+    expect(legacyAuthenticateRequest).toHaveBeenCalled();
packages/react-router/src/server/utils.ts (1)

47-47: Guard redirects/non-JSON responses to prevent .json() errors

If response is a redirect or not JSON, await clone.json() will throw. Early-return redirects and consider tolerant parse.

Outside selected lines, suggested pattern:

if (isRedirect(response)) {
  return response;
}

let data: unknown = {};
try {
  data = await clone.json();
} catch {
  // keep empty object if body is not JSON
}
integration/templates/react-router-node/app/root.tsx (2)

7-8: Document middleware export

Add a brief JSDoc so users know where to customize Clerk middleware options.

/** Configure Clerk middleware for this route */
export const unstable_middleware: Route.unstable_MiddlewareFunction[] = [clerkMiddleware()];

10-14: Make deferred promise abortable to respect navigation cancellation

Tie the promise to args.request.signal to avoid leaked timers and spurious work.

-  const nonCriticalData = new Promise(res => setTimeout(() => res('non-critical'), 1000));
+  const nonCriticalData = new Promise<string>((res, rej) => {
+    const id = setTimeout(() => res('non-critical'), 1000);
+    const onAbort = () => {
+      clearTimeout(id);
+      rej(new DOMException('Aborted', 'AbortError'));
+    };
+    args.request.signal.addEventListener('abort', onAbort, { once: true });
+  });
packages/react-router/src/server/loadOptions.ts (1)

14-17: Unify arg types across server APIs

loadOptions now takes DataFunctionArgs; callers like getAuth may still be typed with LoaderFunctionArgs. Export DataFunctionArgs from a central types.ts and use it consistently to avoid drift.

integration/tests/react-router/pre-middleware.test.ts (1)

8-12: Parallel mode with shared app/user — confirm no flakiness

Running tests in parallel while sharing a single app instance and user can cause intermittent failures if routes mutate shared state. If you’ve seen flakes, switch this suite to serial or provision per-test users.

packages/react-router/src/server/clerkMiddleware.ts (1)

15-15: Avoid any in public types

Use unknown instead of any for RequestState generic.

-export const requestStateContext = unstable_createContext<RequestState<any> | null>(null);
+export const requestStateContext = unstable_createContext<RequestState<unknown> | null>(null);
packages/react-router/src/server/rootAuthLoader.ts (2)

46-49: Avoid any in callback type

Prefer unknown for RootAuthLoaderCallback generic.

-  handler?: RootAuthLoaderCallback<any>,
+  handler?: RootAuthLoaderCallback<unknown>,

60-64: Avoid any in LoaderFunctionArgsWithAuth cast

Use unknown to prevent unsafe widening.

-  } as LoaderFunctionArgsWithAuth<any>;
+  } as LoaderFunctionArgsWithAuth<unknown>;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • 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 2a82737 and 55d3572.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (23)
  • .changeset/quiet-bats-protect.md (1 hunks)
  • integration/templates/react-router-library/package.json (1 hunks)
  • integration/templates/react-router-node/app/root.tsx (2 hunks)
  • integration/templates/react-router-node/package.json (1 hunks)
  • integration/templates/react-router-node/react-router.config.ts (1 hunks)
  • integration/tests/react-router/basic.test.ts (2 hunks)
  • integration/tests/react-router/pre-middleware.test.ts (1 hunks)
  • packages/react-router/package.json (3 hunks)
  • packages/react-router/src/server/__tests__/getAuth.test.ts (1 hunks)
  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts (1 hunks)
  • packages/react-router/src/server/clerkClient.ts (1 hunks)
  • packages/react-router/src/server/clerkMiddleware.ts (1 hunks)
  • packages/react-router/src/server/getAuth.ts (1 hunks)
  • packages/react-router/src/server/index.ts (1 hunks)
  • packages/react-router/src/server/legacyAuthenticateRequest.ts (2 hunks)
  • packages/react-router/src/server/loadOptions.ts (1 hunks)
  • packages/react-router/src/server/rootAuthLoader.ts (1 hunks)
  • packages/react-router/src/server/types.ts (3 hunks)
  • packages/react-router/src/server/utils.ts (2 hunks)
  • packages/react-router/src/ssr/getAuth.ts (0 hunks)
  • packages/react-router/src/ssr/index.ts (1 hunks)
  • packages/react-router/src/ssr/rootAuthLoader.ts (0 hunks)
  • packages/react-router/src/utils/errors.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • packages/react-router/src/ssr/getAuth.ts
  • packages/react-router/src/ssr/rootAuthLoader.ts
🧰 Additional context used
📓 Path-based instructions (17)
**/*.{js,jsx,ts,tsx}

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

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
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
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/react-router/src/server/index.ts
  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/ssr/index.ts
  • packages/react-router/src/server/__tests__/getAuth.test.ts
  • packages/react-router/src/server/clerkMiddleware.ts
  • packages/react-router/src/server/clerkClient.ts
  • integration/templates/react-router-node/react-router.config.ts
  • packages/react-router/src/server/loadOptions.ts
  • integration/tests/react-router/basic.test.ts
  • packages/react-router/src/server/rootAuthLoader.ts
  • packages/react-router/src/utils/errors.ts
  • packages/react-router/src/server/getAuth.ts
  • integration/tests/react-router/pre-middleware.test.ts
  • packages/react-router/src/server/utils.ts
  • packages/react-router/src/server/types.ts
  • integration/templates/react-router-node/app/root.tsx
  • packages/react-router/src/server/legacyAuthenticateRequest.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

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

Use Prettier for consistent code formatting

Files:

  • packages/react-router/src/server/index.ts
  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/ssr/index.ts
  • packages/react-router/src/server/__tests__/getAuth.test.ts
  • packages/react-router/src/server/clerkMiddleware.ts
  • packages/react-router/package.json
  • packages/react-router/src/server/clerkClient.ts
  • integration/templates/react-router-node/react-router.config.ts
  • packages/react-router/src/server/loadOptions.ts
  • integration/tests/react-router/basic.test.ts
  • packages/react-router/src/server/rootAuthLoader.ts
  • packages/react-router/src/utils/errors.ts
  • packages/react-router/src/server/getAuth.ts
  • integration/templates/react-router-node/package.json
  • integration/templates/react-router-library/package.json
  • integration/tests/react-router/pre-middleware.test.ts
  • packages/react-router/src/server/utils.ts
  • packages/react-router/src/server/types.ts
  • integration/templates/react-router-node/app/root.tsx
  • packages/react-router/src/server/legacyAuthenticateRequest.ts
packages/**/*.{ts,tsx}

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

TypeScript is required for all packages

Files:

  • packages/react-router/src/server/index.ts
  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/ssr/index.ts
  • packages/react-router/src/server/__tests__/getAuth.test.ts
  • packages/react-router/src/server/clerkMiddleware.ts
  • packages/react-router/src/server/clerkClient.ts
  • packages/react-router/src/server/loadOptions.ts
  • packages/react-router/src/server/rootAuthLoader.ts
  • packages/react-router/src/utils/errors.ts
  • packages/react-router/src/server/getAuth.ts
  • packages/react-router/src/server/utils.ts
  • packages/react-router/src/server/types.ts
  • packages/react-router/src/server/legacyAuthenticateRequest.ts
packages/**/*.{ts,tsx,d.ts}

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

Packages should export TypeScript types alongside runtime code

Files:

  • packages/react-router/src/server/index.ts
  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/ssr/index.ts
  • packages/react-router/src/server/__tests__/getAuth.test.ts
  • packages/react-router/src/server/clerkMiddleware.ts
  • packages/react-router/src/server/clerkClient.ts
  • packages/react-router/src/server/loadOptions.ts
  • packages/react-router/src/server/rootAuthLoader.ts
  • packages/react-router/src/utils/errors.ts
  • packages/react-router/src/server/getAuth.ts
  • packages/react-router/src/server/utils.ts
  • packages/react-router/src/server/types.ts
  • packages/react-router/src/server/legacyAuthenticateRequest.ts
packages/**/index.{js,ts}

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

Use tree-shaking friendly exports

Files:

  • packages/react-router/src/server/index.ts
  • packages/react-router/src/ssr/index.ts
**/*.{ts,tsx}

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

Use proper TypeScript error types

**/*.{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
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
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/react-router/src/server/index.ts
  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/ssr/index.ts
  • packages/react-router/src/server/__tests__/getAuth.test.ts
  • packages/react-router/src/server/clerkMiddleware.ts
  • packages/react-router/src/server/clerkClient.ts
  • integration/templates/react-router-node/react-router.config.ts
  • packages/react-router/src/server/loadOptions.ts
  • integration/tests/react-router/basic.test.ts
  • packages/react-router/src/server/rootAuthLoader.ts
  • packages/react-router/src/utils/errors.ts
  • packages/react-router/src/server/getAuth.ts
  • integration/tests/react-router/pre-middleware.test.ts
  • packages/react-router/src/server/utils.ts
  • packages/react-router/src/server/types.ts
  • integration/templates/react-router-node/app/root.tsx
  • packages/react-router/src/server/legacyAuthenticateRequest.ts
**/*.{js,ts,tsx,jsx}

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

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/react-router/src/server/index.ts
  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/ssr/index.ts
  • packages/react-router/src/server/__tests__/getAuth.test.ts
  • packages/react-router/src/server/clerkMiddleware.ts
  • packages/react-router/src/server/clerkClient.ts
  • integration/templates/react-router-node/react-router.config.ts
  • packages/react-router/src/server/loadOptions.ts
  • integration/tests/react-router/basic.test.ts
  • packages/react-router/src/server/rootAuthLoader.ts
  • packages/react-router/src/utils/errors.ts
  • packages/react-router/src/server/getAuth.ts
  • integration/tests/react-router/pre-middleware.test.ts
  • packages/react-router/src/server/utils.ts
  • packages/react-router/src/server/types.ts
  • integration/templates/react-router-node/app/root.tsx
  • packages/react-router/src/server/legacyAuthenticateRequest.ts
**/index.ts

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

Use index.ts files for clean imports but avoid deep barrel exports

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

Files:

  • packages/react-router/src/server/index.ts
  • packages/react-router/src/ssr/index.ts
.changeset/**

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

Automated releases must use Changesets.

Files:

  • .changeset/quiet-bats-protect.md
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

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

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/server/__tests__/getAuth.test.ts
**/__tests__/**/*.{ts,tsx}

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

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/server/__tests__/getAuth.test.ts
packages/*/package.json

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

All publishable packages should be placed under the packages/ directory

packages/*/package.json: All publishable packages must be located in the 'packages/' directory.
All packages must be published under the @clerk namespace on npm.
Semantic versioning must be used across all packages.

Files:

  • packages/react-router/package.json
integration/**

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

Framework integration templates and E2E tests should be placed under the integration/ directory

Files:

  • integration/templates/react-router-node/react-router.config.ts
  • integration/tests/react-router/basic.test.ts
  • integration/templates/react-router-node/package.json
  • integration/templates/react-router-library/package.json
  • integration/tests/react-router/pre-middleware.test.ts
  • integration/templates/react-router-node/app/root.tsx
integration/**/*

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

End-to-end tests and integration templates must be located in the 'integration/' directory.

Files:

  • integration/templates/react-router-node/react-router.config.ts
  • integration/tests/react-router/basic.test.ts
  • integration/templates/react-router-node/package.json
  • integration/templates/react-router-library/package.json
  • integration/tests/react-router/pre-middleware.test.ts
  • integration/templates/react-router-node/app/root.tsx
integration/**/*.{test,spec}.{js,ts}

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

Integration tests should use Playwright.

Files:

  • integration/tests/react-router/basic.test.ts
  • integration/tests/react-router/pre-middleware.test.ts
**/*.{jsx,tsx}

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

**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components: 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
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...

Files:

  • integration/templates/react-router-node/app/root.tsx
**/*.tsx

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

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

Files:

  • integration/templates/react-router-node/app/root.tsx
🧬 Code graph analysis (12)
packages/react-router/src/server/__tests__/rootAuthLoader.test.ts (4)
packages/remix/src/ssr/types.ts (1)
  • LoaderFunctionArgs (68-68)
packages/react-router/src/server/rootAuthLoader.ts (1)
  • rootAuthLoader (116-136)
packages/react-router/src/server/legacyAuthenticateRequest.ts (1)
  • legacyAuthenticateRequest (9-53)
packages/react-router/src/utils/errors.ts (1)
  • middlewareMigrationWarning (120-124)
packages/react-router/src/server/__tests__/getAuth.test.ts (3)
packages/remix/src/ssr/types.ts (1)
  • LoaderFunctionArgs (68-68)
packages/react-router/src/server/getAuth.ts (1)
  • getAuth (16-45)
packages/react-router/src/server/legacyAuthenticateRequest.ts (1)
  • legacyAuthenticateRequest (9-53)
packages/react-router/src/server/clerkMiddleware.ts (6)
packages/types/src/session.ts (1)
  • PendingSessionOptions (34-40)
packages/react-router/src/server/types.ts (1)
  • ClerkMiddlewareOptions (15-40)
packages/react-router/src/server/utils.ts (1)
  • patchRequest (118-133)
packages/react-router/src/server/loadOptions.ts (1)
  • loadOptions (16-90)
packages/react-router/src/server/clerkClient.ts (1)
  • clerkClient (5-21)
packages/shared/src/netlifyCacheHandler.ts (1)
  • handleNetlifyCacheInDevInstance (43-65)
packages/react-router/src/server/clerkClient.ts (1)
packages/react-router/src/server/loadOptions.ts (2)
  • DataFunctionArgs (14-14)
  • loadOptions (16-90)
packages/react-router/src/server/loadOptions.ts (1)
packages/react-router/src/server/types.ts (1)
  • ClerkMiddlewareOptions (15-40)
integration/tests/react-router/basic.test.ts (1)
integration/testUtils/index.ts (1)
  • createTestUtils (24-86)
packages/react-router/src/server/rootAuthLoader.ts (6)
packages/react-router/src/server/types.ts (4)
  • RootAuthLoaderOptions (42-55)
  • RootAuthLoaderCallback (64-66)
  • LoaderFunctionReturn (83-83)
  • LoaderFunctionArgsWithAuth (85-87)
packages/react-router/src/server/clerkMiddleware.ts (2)
  • authFnContext (14-14)
  • requestStateContext (15-15)
packages/react-router/src/server/utils.ts (5)
  • getResponseClerkState (72-99)
  • isResponse (8-16)
  • isRedirect (29-31)
  • injectRequestStateIntoResponse (43-65)
  • isDataWithResponseInit (18-27)
packages/react-router/src/utils/errors.ts (2)
  • invalidRootLoaderCallbackReturn (51-73)
  • middlewareMigrationWarning (120-124)
packages/react-router/src/server/loadOptions.ts (1)
  • loadOptions (16-90)
packages/react-router/src/server/legacyAuthenticateRequest.ts (1)
  • legacyAuthenticateRequest (9-53)
packages/react-router/src/server/getAuth.ts (7)
packages/nextjs/src/server/createGetAuth.ts (1)
  • GetAuthOptions (18-20)
packages/types/src/session.ts (1)
  • PendingSessionOptions (34-40)
packages/remix/src/ssr/types.ts (1)
  • LoaderFunctionArgs (68-68)
packages/react-router/src/utils/errors.ts (1)
  • noLoaderArgsPassedInGetAuth (40-49)
packages/react-router/src/server/clerkMiddleware.ts (1)
  • authFnContext (14-14)
packages/react-router/src/server/loadOptions.ts (1)
  • loadOptions (16-90)
packages/react-router/src/server/legacyAuthenticateRequest.ts (1)
  • legacyAuthenticateRequest (9-53)
integration/tests/react-router/pre-middleware.test.ts (3)
integration/models/application.ts (1)
  • Application (7-7)
integration/presets/index.ts (1)
  • appConfigs (14-30)
integration/testUtils/index.ts (1)
  • createTestUtils (24-86)
packages/react-router/src/server/types.ts (2)
packages/types/src/multiDomain.ts (1)
  • MultiDomainAndOrProxy (11-35)
packages/types/src/redirects.ts (5)
  • SignInForceRedirectUrl (128-133)
  • SignInFallbackRedirectUrl (120-126)
  • SignUpForceRedirectUrl (105-110)
  • SignUpFallbackRedirectUrl (112-118)
  • LegacyRedirectProps (21-34)
integration/templates/react-router-node/app/root.tsx (3)
packages/react-router/src/server/clerkMiddleware.ts (1)
  • clerkMiddleware (17-61)
playground/react-router/app/root.tsx (1)
  • loader (15-17)
packages/react-router/src/server/rootAuthLoader.ts (1)
  • rootAuthLoader (116-136)
packages/react-router/src/server/legacyAuthenticateRequest.ts (2)
packages/react-router/src/server/clerkClient.ts (1)
  • clerkClient (5-21)
packages/react-router/src/server/utils.ts (1)
  • patchRequest (118-133)
🪛 LanguageTool
.changeset/quiet-bats-protect.md

[grammar] ~1-~1: Hier könnte ein Fehler sein.
Context: --- ---

(QB_NEW_DE)

⏰ 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). (6)
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Build Packages
  • GitHub Check: semgrep/ci
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (13)
.changeset/quiet-bats-protect.md (1)

1-2: Verify affected packages and bump levels before merging. Automatic detection failed due to a missing merge base; please manually ensure every publishable package touched by this PR that exposes new middleware APIs is bumped (minor for new APIs, major for breaking changes).

integration/templates/react-router-node/react-router.config.ts (1)

7-9: unstable_middleware export verified
The export const unstable_middleware is defined in integration/templates/react-router-node/app/root.tsx, matching the future.unstable_middleware flag requirement.

packages/react-router/package.json (4)

33-36: Server subpath export: LGTM


62-64: typesVersions for server: LGTM


102-102: Dev dependency bump to 7.8.2: LGTM


107-107: Peer dependency bump to ^7.8.2: LGTM

integration/templates/react-router-node/package.json (2)

12-13: RR tooling aligned to ^7.8.2: LGTM


20-20: Dev tooling aligned to ^7.8.2: LGTM

packages/react-router/src/ssr/index.ts (1)

1-2: LGTM: explicit named re-exports

Explicit server re-exports improve tree-shaking and clarity. Ensure docs reflect the new import paths.

integration/tests/react-router/basic.test.ts (1)

8-8: Test title updated — OK

Title reflects middleware path; no action needed.

packages/react-router/src/server/loadOptions.ts (1)

7-7: Confirm react-router peerDependency covers unstable_MiddlewareFunction
Hard-couples to the unstable API unstable_MiddlewareFunction. Verify your package.json peerDependency range includes a React Router version that exports this type and update any project templates to pin a compatible version.

integration/tests/react-router/pre-middleware.test.ts (1)

19-24: Verify Meta/Links imports are valid for this template

Are Meta, Links, Scripts, ScrollRestoration exported from 'react-router' in the react-router-node template? If not, adjust imports (e.g., the framework-specific entry) to avoid build errors.

packages/react-router/src/server/rootAuthLoader.ts (1)

116-136: LGTM: Middleware vs legacy routing is cleanly split

The rootAuthLoader flow correctly prefers middleware, warns once when missing, and handles injection/redirect semantics appropriately.

Comment on lines +19 to 20
const requestState = await clerkClient(args).authenticateRequest(patchRequest(request), {
apiUrl,
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Align client config with overrides to avoid mismatched secrets/domains

clerkClient(args) internally calls loadOptions(args) without overrides, which can diverge from opts (e.g., overridden secretKey/domain). Prefer passing overrides into the client factory.

Proposed changes (outside this file for completeness):

  1. packages/react-router/src/server/clerkClient.ts
-export const clerkClient = (args: DataFunctionArgs) => {
-  const options = loadOptions(args);
+export const clerkClient = (args: DataFunctionArgs, overrides?: ClerkMiddlewareOptions) => {
+  const options = loadOptions(args, overrides);
@@
   return createClerkClient({
     apiUrl,
     secretKey,
     jwtKey,
     proxyUrl,
     isSatellite,
     domain,
     publishableKey,
     machineSecretKey,
     userAgent: `${PACKAGE_NAME}@${PACKAGE_VERSION}`,
   });
 };
  1. packages/react-router/src/server/legacyAuthenticateRequest.ts
-  const requestState = await clerkClient(args).authenticateRequest(patchRequest(request), {
+  const requestState = await clerkClient(args, opts).authenticateRequest(patchRequest(request), {
📝 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
const requestState = await clerkClient(args).authenticateRequest(patchRequest(request), {
apiUrl,
const requestState = await clerkClient(args, opts).authenticateRequest(
patchRequest(request),
{
apiUrl,
// …other opts…
}
);
🤖 Prompt for AI Agents
In packages/react-router/src/server/legacyAuthenticateRequest.ts around lines
19-20, the call clerkClient(args) creates a client that ignores the current
overrides (opts) causing mismatched secrets/domains; update the call to pass the
same overrides into the client factory (e.g., clerkClient(args, opts) or
clerkClient({ ...args, ...opts }) depending on the factory signature) so the
client is constructed with the same overridden config before calling
authenticateRequest.

Comment on lines +57 to +62
// Only add Clerk headers if requested (for legacy mode)
if (includeClerkHeaders) {
headers.forEach((value, key) => {
clone.headers.append(key, value);
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use set instead of append to avoid duplicate Clerk headers

Appending can create duplicated observability headers across multiple injections. Overwrite instead.

-  if (includeClerkHeaders) {
-    headers.forEach((value, key) => {
-      clone.headers.append(key, value);
-    });
-  }
+  if (includeClerkHeaders) {
+    headers.forEach((value, key) => {
+      clone.headers.set(key, value);
+    });
+  }
📝 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
// Only add Clerk headers if requested (for legacy mode)
if (includeClerkHeaders) {
headers.forEach((value, key) => {
clone.headers.append(key, value);
});
}
// Only add Clerk headers if requested (for legacy mode)
if (includeClerkHeaders) {
headers.forEach((value, key) => {
clone.headers.set(key, value);
});
}
🤖 Prompt for AI Agents
In packages/react-router/src/server/utils.ts around lines 57 to 62, the code
appends Clerk headers which can produce duplicate observability headers on
multiple injections; replace clone.headers.append(key, value) with
clone.headers.set(key, value) so headers are overwritten instead of duplicated,
ensuring each header key is unique and preventing repeated values.

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: 1

♻️ Duplicate comments (3)
packages/react-router/src/server/__tests__/rootAuthLoader.test.ts (1)

39-48: Good: spying on logger.warnOnce (not console.warn) matches implementation

This addresses the prior review and decouples tests from logger internals.

packages/react-router/src/server/clerkMiddleware.ts (2)

61-65: Avoid duplicating non-Set-Cookie headers: set vs append

Appending all headers can create duplicates. Append Set-Cookie; set others.

-    if (requestState.headers) {
-      requestState.headers.forEach((value, key) => {
-        response.headers.append(key, value);
-      });
-    }
+    if (requestState.headers) {
+      for (const [key, value] of requestState.headers.entries()) {
+        if (key.toLowerCase() === 'set-cookie') {
+          response.headers.append(key, value);
+        } else {
+          response.headers.set(key, value);
+        }
+      }
+    }

17-24: Expand/correct JSDoc and usage example

Public API needs comprehensive JSDoc. The example is syntactically incorrect; it should assign an array.

 /**
- * Middleware that integrates Clerk authentication into your React Router application.
- * It checks the request's cookies and headers for a session JWT and, if found,
- * attaches the Auth object to a context.
- *
- * @example
- * export const middleware: Route.MiddlewareFunction[clerkMiddleware()]
+ * Integrates Clerk authentication into a React Router app.
+ * Authenticates the incoming request (cookies/headers), stores the RequestState
+ * and an auth() function in contexts for downstream loaders/actions, and
+ * propagates Clerk headers on the way out.
+ *
+ * @param options - Clerk middleware options (keys, domain/proxy, redirect URLs, audience/authorizedParties).
+ * @returns A React Router middleware function.
+ *
+ * @example
+ * export const middleware: Route.MiddlewareFunction[] = [clerkMiddleware()];
  */
🧹 Nitpick comments (7)
packages/react-router/src/server/__tests__/rootAuthLoader.test.ts (3)

82-85: Remove long timers in tests to prevent slow/flaky runs

Using setTimeout(5000) needlessly slows tests. A resolved promise is enough to verify serialization to {}.

-      const nonCriticalData = new Promise(res => setTimeout(() => res('non-critical'), 5000));
+      const nonCriticalData = Promise.resolve('non-critical');

Apply the same change in the legacy-path test.

Also applies to: 159-161


71-79: Add a test for redirect pass-through

processRootAuthLoader returns unmodified redirect Responses. Add a case where the handler returns new Response(null, { status: 302, headers: { Location: '/login' } }) and assert it’s returned as-is and not decorated.

I can draft the test if you want.


111-119: Tighten spy typing for logger.warnOnce

Use SpyInstance for accurate typing of arguments and return type.

-import type { MockInstance } from 'vitest';
+import type { SpyInstance } from 'vitest';
@@
-    let warnOnceSpy: MockInstance<(msg: string) => void>;
+    let warnOnceSpy: SpyInstance<[string], void>;
packages/react-router/src/server/clerkMiddleware.ts (1)

31-39: Consider making acceptsToken configurable (default to 'any')

Expose acceptsToken in ClerkMiddlewareOptions for advanced deployments that want to restrict token sources.

I can propose the types and a backwards-compatible default if you want this.

packages/react-router/src/server/rootAuthLoader.ts (3)

59-66: Don’t mutate the original Request when adding auth

Object.assign mutates args.request. Prefer a shallow wrapper to avoid side effects on other code that uses the same Request.

-  const argsWithAuth = {
-    ...args,
-    request: Object.assign(args.request, { auth: requestState.toAuth() }),
-  } as LoaderFunctionArgsWithAuth<any>;
+  const requestWithAuth = Object.create(args.request, {
+    auth: { value: requestState.toAuth(), enumerable: false, configurable: true },
+  });
+  const argsWithAuth = { ...args, request: requestWithAuth } as LoaderFunctionArgsWithAuth<any>;

67-79: Robustness: narrow catch blocks to JSON parsing only

The catch will also swallow unrelated errors. Limit the try/catch to the JSON injection path.

-  if (isResponse(handlerResult)) {
-    try {
-      if (isRedirect(handlerResult)) {
-        return handlerResult;
-      }
-      return injectRequestStateIntoResponse(handlerResult, requestState, args.context, includeClerkHeaders);
-    } catch {
-      throw new Error(invalidRootLoaderCallbackReturn);
-    }
-  }
+  if (isResponse(handlerResult)) {
+    if (isRedirect(handlerResult)) {
+      return handlerResult;
+    }
+    try {
+      return injectRequestStateIntoResponse(handlerResult, requestState, args.context, includeClerkHeaders);
+    } catch {
+      throw new Error(invalidRootLoaderCallbackReturn);
+    }
+  }

96-105: Confirm intentional return shape for “no handler” (middleware path)

Returning a plain object with clerkState (not a Response) enables streaming, which is good. Ensure docs explicitly call out the differing return types between middleware and legacy paths to set developer expectations.

I can add a short note to the reference docs and examples.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • 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 55d3572 and 7e07dca.

📒 Files selected for processing (3)
  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts (1 hunks)
  • packages/react-router/src/server/clerkMiddleware.ts (1 hunks)
  • packages/react-router/src/server/rootAuthLoader.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,jsx,ts,tsx}

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

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
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
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/server/rootAuthLoader.ts
  • packages/react-router/src/server/clerkMiddleware.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

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

Use Prettier for consistent code formatting

Files:

  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/server/rootAuthLoader.ts
  • packages/react-router/src/server/clerkMiddleware.ts
packages/**/*.{ts,tsx}

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

TypeScript is required for all packages

Files:

  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/server/rootAuthLoader.ts
  • packages/react-router/src/server/clerkMiddleware.ts
packages/**/*.{ts,tsx,d.ts}

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

Packages should export TypeScript types alongside runtime code

Files:

  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/server/rootAuthLoader.ts
  • packages/react-router/src/server/clerkMiddleware.ts
**/*.{ts,tsx}

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

Use proper TypeScript error types

**/*.{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
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
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/server/rootAuthLoader.ts
  • packages/react-router/src/server/clerkMiddleware.ts
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

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

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
**/*.{js,ts,tsx,jsx}

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

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
  • packages/react-router/src/server/rootAuthLoader.ts
  • packages/react-router/src/server/clerkMiddleware.ts
**/__tests__/**/*.{ts,tsx}

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

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: wobsoriano
PR: clerk/javascript#6653
File: integration/tests/react-router/pre-middleware.test.ts:20-20
Timestamp: 2025-08-28T14:52:55.884Z
Learning: In the clerk/react-router package migration, the legacy `clerk/react-router/ssr.server` entrypoint is being maintained for backward compatibility while users are guided to migrate to `clerk/react-router/server` through deprecation notices.
🧬 Code graph analysis (3)
packages/react-router/src/server/__tests__/rootAuthLoader.test.ts (4)
packages/remix/src/ssr/types.ts (1)
  • LoaderFunctionArgs (68-68)
packages/react-router/src/server/rootAuthLoader.ts (1)
  • rootAuthLoader (117-137)
packages/react-router/src/server/legacyAuthenticateRequest.ts (1)
  • legacyAuthenticateRequest (9-53)
packages/react-router/src/utils/errors.ts (1)
  • middlewareMigrationWarning (120-124)
packages/react-router/src/server/rootAuthLoader.ts (6)
packages/react-router/src/server/types.ts (4)
  • RootAuthLoaderOptions (42-55)
  • RootAuthLoaderCallback (64-66)
  • LoaderFunctionReturn (83-83)
  • LoaderFunctionArgsWithAuth (85-87)
packages/react-router/src/server/clerkMiddleware.ts (2)
  • authFnContext (14-14)
  • requestStateContext (15-15)
packages/react-router/src/server/utils.ts (5)
  • getResponseClerkState (72-99)
  • isResponse (8-16)
  • isRedirect (29-31)
  • injectRequestStateIntoResponse (43-65)
  • isDataWithResponseInit (18-27)
packages/react-router/src/utils/errors.ts (2)
  • invalidRootLoaderCallbackReturn (51-73)
  • middlewareMigrationWarning (120-124)
packages/react-router/src/server/loadOptions.ts (1)
  • loadOptions (16-90)
packages/react-router/src/server/legacyAuthenticateRequest.ts (1)
  • legacyAuthenticateRequest (9-53)
packages/react-router/src/server/clerkMiddleware.ts (6)
packages/types/src/session.ts (1)
  • PendingSessionOptions (34-40)
packages/react-router/src/server/types.ts (1)
  • ClerkMiddlewareOptions (15-40)
packages/react-router/src/server/utils.ts (1)
  • patchRequest (118-133)
packages/react-router/src/server/loadOptions.ts (1)
  • loadOptions (16-90)
packages/react-router/src/server/clerkClient.ts (1)
  • clerkClient (5-21)
packages/shared/src/netlifyCacheHandler.ts (1)
  • handleNetlifyCacheInDevInstance (43-65)
⏰ 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: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (1)
packages/react-router/src/server/rootAuthLoader.ts (1)

155-169: Good backward compatibility in legacy path

Loading options, authenticating, decorating request, and reusing the same processor keeps behavior consistent while guiding migration.

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: 1

🧹 Nitpick comments (5)
integration/tests/react-router/basic.test.ts (1)

92-102: Harden the streaming test against CI flakiness.
Increase timeout headroom and wait for app URL before assertions to avoid races on slow bots.

Apply this diff:

     test('streaming with Suspense works with rootAuthLoader', async ({ page, context }) => {
       const u = createTestUtils({ app, page, context });

-      await u.page.goToRelative('/');
+      await u.page.goToRelative('/');
+      await u.page.waitForAppUrl('/');

       await expect(u.page.getByText('Loading...')).toBeVisible();

       // Wait for the streaming content to resolve (5 second delay + buffer)
-      await expect(u.page.getByText('Non critical value: non-critical')).toBeVisible({ timeout: 8000 });
+      await expect(u.page.getByText('Non critical value: non-critical')).toBeVisible({ timeout: 15000 });
       await expect(u.page.getByText('Loading...')).toBeHidden();
     });
integration/templates/react-router-node/app/root.tsx (4)

7-7: Document the middleware export and intent.
Since this is a template entrypoint, add a brief JSDoc so integrators know where to customize.

Apply this diff:

+/**
+ * Route middleware chain. Customize by adding your own handlers before/after Clerk.
+ * Requires React Router `future.unstable_middleware` to be enabled in the router config.
+ */
 export const unstable_middleware: Route.unstable_MiddlewareFunction[] = [clerkMiddleware()];

9-15: Abort-aware delayed promise to avoid leaking timers on navigation.
Tie the timeout to the request’s abort signal so timers are cleared when the loader is canceled.

Apply this diff:

 export async function loader(args: Route.LoaderArgs) {
-  const nonCriticalData = new Promise(res => setTimeout(() => res('non-critical'), 5000));
+  const controller = new AbortController();
+  const nonCriticalData: Promise<string> = new Promise(res => {
+    const id = setTimeout(() => res('non-critical'), 5000);
+    const cleanup = () => clearTimeout(id);
+    args.request.signal.addEventListener('abort', cleanup, { once: true });
+    controller.signal.addEventListener('abort', cleanup, { once: true });
+  });
 
   return rootAuthLoader(args, () => ({
     nonCriticalData,
   }));
 }

12-14: Add minimal type clarity for loader data.
Make the awaited value explicit for downstream inference without over-specifying the loader’s return type.

Apply this diff:

-  return rootAuthLoader(args, () => ({
-    nonCriticalData,
-  }));
+  return rootAuthLoader(args, () => ({
+    nonCriticalData: nonCriticalData as Promise<string>,
+  }));

43-45: Type the Await render arg and improve a11y of the fallback.
Explicit type avoids unknown, and role/aria-live improves SR experience.

Apply this diff:

-        <React.Suspense fallback={<div>Loading...</div>}>
-          <Await resolve={loaderData.nonCriticalData}>{value => <h3>Non critical value: {value}</h3>}</Await>
+        <React.Suspense fallback={<div role="status" aria-live="polite">Loading...</div>}>
+          <Await resolve={loaderData.nonCriticalData}>
+            {(value: string) => <h3>Non critical value: {value}</h3>}
+          </Await>
         </React.Suspense>
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • 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 7e07dca and b8f9998.

📒 Files selected for processing (2)
  • integration/templates/react-router-node/app/root.tsx (2 hunks)
  • integration/tests/react-router/basic.test.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{js,jsx,ts,tsx}

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

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
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
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • integration/tests/react-router/basic.test.ts
  • integration/templates/react-router-node/app/root.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

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

Use Prettier for consistent code formatting

Files:

  • integration/tests/react-router/basic.test.ts
  • integration/templates/react-router-node/app/root.tsx
**/*.{ts,tsx}

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

Use proper TypeScript error types

**/*.{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
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
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • integration/tests/react-router/basic.test.ts
  • integration/templates/react-router-node/app/root.tsx
integration/**

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

Framework integration templates and E2E tests should be placed under the integration/ directory

Files:

  • integration/tests/react-router/basic.test.ts
  • integration/templates/react-router-node/app/root.tsx
integration/**/*

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

End-to-end tests and integration templates must be located in the 'integration/' directory.

Files:

  • integration/tests/react-router/basic.test.ts
  • integration/templates/react-router-node/app/root.tsx
integration/**/*.{test,spec}.{js,ts}

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

Integration tests should use Playwright.

Files:

  • integration/tests/react-router/basic.test.ts
**/*.{js,ts,tsx,jsx}

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

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • integration/tests/react-router/basic.test.ts
  • integration/templates/react-router-node/app/root.tsx
**/*.{jsx,tsx}

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

**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components: 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
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...

Files:

  • integration/templates/react-router-node/app/root.tsx
**/*.tsx

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

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

Files:

  • integration/templates/react-router-node/app/root.tsx
🧬 Code graph analysis (1)
integration/tests/react-router/basic.test.ts (1)
integration/testUtils/index.ts (1)
  • createTestUtils (24-86)
⏰ 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). (26)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (tanstack-react-router, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (expo-web, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 14)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (elements, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome)
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Static analysis
  • GitHub Check: Unit Tests (22, **)
  • GitHub Check: Unit Tests (18, --filter=@clerk/astro --filter=@clerk/backend --filter=@clerk/express --filter=@c...
  • GitHub Check: semgrep/ci
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
integration/tests/react-router/basic.test.ts (2)

8-8: Suite title change is clear and scoped.
Accurately reflects middleware focus. No action needed.


92-102: No changes needed: unstable_middleware is already enabled
Confirmed unstable_middleware: true in integration/templates/react-router-node/react-router.config.ts.

integration/templates/react-router-node/app/root.tsx (1)

1-3: Imports are correct for react-router v7.1.2
Await, Links, Meta, Scripts, ScrollRestoration and isRouteErrorResponse are all exported by the core react-router package in the v7 release line—no change needed.

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: 4

♻️ Duplicate comments (1)
integration/templates/react-router-node/app/root.tsx (1)

7-8: Ensure router feature flag is enabled.

Exporting unstable_middleware isn’t enough; the router must opt-in with future.unstable_middleware: true. Please confirm it’s set in this template’s router config.

#!/bin/bash
# Verify the feature flag is enabled somewhere under the template
rg -nP -C3 'future\s*:\s*\{[^}]*unstable_middleware\s*:\s*true' integration/templates/react-router-node -g '!**/dist/**'
🧹 Nitpick comments (5)
.changeset/quiet-bats-protect.md (1)

32-48: Keep streaming timings consistent with the template/tests.

The example uses a 5s delay while the template currently uses 10s and the test waits less by default. Standardize to 5s here and in the template to avoid flaky tests and long waits.

If you prefer 10s in the template, update the test’s expectation timeouts accordingly (see my test comment).

integration/templates/react-router-node/app/root.tsx (4)

17-36: Add explicit return types for public components.

Keep TS surfaces explicit.

-export function Layout({ children }: { children: React.ReactNode }) {
+export function Layout({ children }: { children: React.ReactNode }): JSX.Element {

38-49: Add explicit return type for App.

-export default function App({ loaderData }: Route.ComponentProps) {
+export default function App({ loaderData }: Route.ComponentProps): JSX.Element {

51-76: Add explicit return type for ErrorBoundary.

-export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
+export function ErrorBoundary({ error }: Route.ErrorBoundaryProps): JSX.Element {

43-46: Optional: Provide an error fallback for Await.

Helps surface loader promise errors in dev.

-        <React.Suspense fallback={<div>Loading...</div>}>
-          <Await resolve={loaderData.nonCriticalData}>{value => <h3>Non critical value: {value}</h3>}</Await>
-        </React.Suspense>
+        <React.Suspense fallback={<div>Loading...</div>}>
+          <Await
+            resolve={loaderData.nonCriticalData}
+            errorElement={<div>Failed to load non-critical data.</div>}
+          >
+            {value => <h3>Non critical value: {value}</h3>}
+          </Await>
+        </React.Suspense>
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • 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 b8f9998 and be2d0b0.

📒 Files selected for processing (3)
  • .changeset/quiet-bats-protect.md (1 hunks)
  • integration/templates/react-router-node/app/root.tsx (2 hunks)
  • integration/tests/react-router/basic.test.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
.changeset/**

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

Automated releases must use Changesets.

Files:

  • .changeset/quiet-bats-protect.md
**/*.{js,jsx,ts,tsx}

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

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
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
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • integration/templates/react-router-node/app/root.tsx
  • integration/tests/react-router/basic.test.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

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

Use Prettier for consistent code formatting

Files:

  • integration/templates/react-router-node/app/root.tsx
  • integration/tests/react-router/basic.test.ts
**/*.{ts,tsx}

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

Use proper TypeScript error types

**/*.{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
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
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • integration/templates/react-router-node/app/root.tsx
  • integration/tests/react-router/basic.test.ts
**/*.{jsx,tsx}

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

**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components: 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
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...

Files:

  • integration/templates/react-router-node/app/root.tsx
integration/**

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

Framework integration templates and E2E tests should be placed under the integration/ directory

Files:

  • integration/templates/react-router-node/app/root.tsx
  • integration/tests/react-router/basic.test.ts
integration/**/*

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

End-to-end tests and integration templates must be located in the 'integration/' directory.

Files:

  • integration/templates/react-router-node/app/root.tsx
  • integration/tests/react-router/basic.test.ts
**/*.{js,ts,tsx,jsx}

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

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • integration/templates/react-router-node/app/root.tsx
  • integration/tests/react-router/basic.test.ts
**/*.tsx

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

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

Files:

  • integration/templates/react-router-node/app/root.tsx
integration/**/*.{test,spec}.{js,ts}

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

Integration tests should use Playwright.

Files:

  • integration/tests/react-router/basic.test.ts
🧬 Code graph analysis (2)
integration/templates/react-router-node/app/root.tsx (1)
packages/react-router/src/server/clerkMiddleware.ts (1)
  • clerkMiddleware (25-69)
integration/tests/react-router/basic.test.ts (1)
integration/testUtils/index.ts (1)
  • createTestUtils (24-86)
⏰ 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). (21)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 14)
  • GitHub Check: Integration Tests (tanstack-react-router, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (quickstart, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (expo-web, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Integration Tests (elements, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (2)
.changeset/quiet-bats-protect.md (1)

1-3: Frontmatter looks correct for a breaking release.

The package key and bump type are valid for Changesets.

integration/templates/react-router-node/app/root.tsx (1)

1-3: Imports and server entrypoints look good.

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

🧹 Nitpick comments (6)
packages/react-router/src/server/__tests__/getAuth.test.ts (6)

23-26: Prevent env leakage across test suite by restoring CLERK_SECRET_KEY

Capture the previous value and restore it after the suite to avoid cross-test contamination.

-import { beforeEach, describe, expect, it, vi } from 'vitest';
+import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest';

 describe('getAuth', () => {
   beforeEach(() => {
     vi.clearAllMocks();
-    process.env.CLERK_SECRET_KEY = 'sk_test_...';
+    prevSecretKey = process.env.CLERK_SECRET_KEY;
+    process.env.CLERK_SECRET_KEY = 'sk_test_...';
   });
+
+  let prevSecretKey: string | undefined;
+  afterAll(() => {
+    if (prevSecretKey === undefined) {
+      delete process.env.CLERK_SECRET_KEY;
+    } else {
+      process.env.CLERK_SECRET_KEY = prevSecretKey;
+    }
+  });

Also applies to: 3-3


43-47: Tighten type-safety of args and avoid broad type assertions

Use the satisfies operator and include params to conform to LoaderFunctionArgs without an unsafe cast.

-    const args = {
-      context: mockContext,
-      request: new Request('http://clerk.com'),
-    } as LoaderFunctionArgs;
+    const args = {
+      context: mockContext,
+      request: new Request('http://clerk.com'),
+      params: {} as any,
+    } satisfies LoaderFunctionArgs;
-    const args = {
-      context: mockContext,
-      request: new Request('http://clerk.com'),
-    } as LoaderFunctionArgs;
+    const args = {
+      context: mockContext,
+      request: new Request('http://clerk.com'),
+      params: {} as any,
+    } satisfies LoaderFunctionArgs;

Also applies to: 60-63


29-41: Remove unused mock field

mockContext.set is never used in this suite.

-      }),
-      set: vi.fn(),
+      }),

48-53: Add an assertion that middleware context was queried

This makes the control-flow intent explicit.

     const auth = await getAuth(args);

+    expect(mockContext.get).toHaveBeenCalledWith(authFnContext);
     expect(legacyAuthenticateRequest).not.toHaveBeenCalled();

65-69: Assert legacyAuthenticateRequest is called with acceptsToken: 'any'

Verifies the fallback path sets the expected option.

     const auth = await getAuth(args);

-    expect(legacyAuthenticateRequest).toHaveBeenCalled();
+    expect(legacyAuthenticateRequest).toHaveBeenCalledWith(
+      args,
+      expect.objectContaining({ acceptsToken: 'any' }),
+    );
     expect(auth.userId).toBe('user_xxx');
     expect(auth.tokenType).toBe('session_token');

71-71: Add a negative test for missing args

Covers the explicit error branch in getAuth for better safety.

   it('should call legacyAuthenticateRequest when middleware context is missing', async () => {
     const mockContext = {
       get: vi.fn().mockReturnValue(null),
     };

     const args = {
       context: mockContext,
       request: new Request('http://clerk.com'),
     } as LoaderFunctionArgs;

     const auth = await getAuth(args);

     expect(legacyAuthenticateRequest).toHaveBeenCalled();
     expect(auth.userId).toBe('user_xxx');
     expect(auth.tokenType).toBe('session_token');
   });
+
+  it('throws when called without args', async () => {
+    // @ts-expect-error - validating runtime guard
+    await expect(getAuth()).rejects.toThrowError();
+  });
 });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • 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 be2d0b0 and 6ed6edd.

📒 Files selected for processing (5)
  • .changeset/quiet-bats-protect.md (1 hunks)
  • integration/templates/react-router-node/app/root.tsx (1 hunks)
  • integration/tests/react-router/basic.test.ts (1 hunks)
  • packages/react-router/src/server/__tests__/getAuth.test.ts (1 hunks)
  • packages/react-router/src/server/__tests__/rootAuthLoader.test.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • integration/tests/react-router/basic.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • integration/templates/react-router-node/app/root.tsx
  • .changeset/quiet-bats-protect.md
  • packages/react-router/src/server/tests/rootAuthLoader.test.ts
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,jsx,ts,tsx}

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

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
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
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/react-router/src/server/__tests__/getAuth.test.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

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

Use Prettier for consistent code formatting

Files:

  • packages/react-router/src/server/__tests__/getAuth.test.ts
packages/**/*.{ts,tsx}

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

TypeScript is required for all packages

Files:

  • packages/react-router/src/server/__tests__/getAuth.test.ts
packages/**/*.{ts,tsx,d.ts}

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

Packages should export TypeScript types alongside runtime code

Files:

  • packages/react-router/src/server/__tests__/getAuth.test.ts
**/*.{ts,tsx}

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

Use proper TypeScript error types

**/*.{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
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
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/react-router/src/server/__tests__/getAuth.test.ts
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

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

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/react-router/src/server/__tests__/getAuth.test.ts
**/*.{js,ts,tsx,jsx}

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

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/react-router/src/server/__tests__/getAuth.test.ts
**/__tests__/**/*.{ts,tsx}

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

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/react-router/src/server/__tests__/getAuth.test.ts
🧬 Code graph analysis (1)
packages/react-router/src/server/__tests__/getAuth.test.ts (4)
packages/react-router/src/server/clerkMiddleware.ts (1)
  • authFnContext (14-14)
packages/remix/src/ssr/types.ts (1)
  • LoaderFunctionArgs (68-68)
packages/react-router/src/server/getAuth.ts (1)
  • getAuth (16-45)
packages/react-router/src/server/legacyAuthenticateRequest.ts (1)
  • legacyAuthenticateRequest (9-53)
⏰ 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). (4)
  • GitHub Check: Build Packages
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
packages/react-router/src/server/__tests__/getAuth.test.ts (1)

28-53: Good coverage of both middleware and legacy paths

This test correctly verifies the short-circuit when middleware context is present and asserts the normalized tokenType. Looks solid.

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: 1

♻️ Duplicate comments (2)
integration/templates/react-router-node/app/root.tsx (1)

6-6: Ensure the router opts into middleware; export alone won’t activate it.

Double‑check the router config enables the middleware feature flag, otherwise rootAuthLoader will fall back to legacy behavior and warn.

#!/bin/bash
# Search template for a middleware opt‑in flag in router config
rg -nP -C3 '(future\s*:\s*\{[^}]*\b(unstable_)?middleware\s*:\s*true)' integration/templates/react-router-node -g '!**/dist/**'

# Also scan common router config files
fd -H 'react-router*.{js,ts}' integration/templates/react-router-node | xargs -I{} rg -n 'middleware' {}
integration/templates/react-router-node/package.json (1)

9-9: Switch typecheck to plain tsc --noEmit; --build requires composite projects.

This template doesn’t declare "composite": true; tsc --build commonly fails.

-    "typecheck": "react-router typegen && tsc --build --noEmit"
+    "typecheck": "react-router typegen && tsc --noEmit"
🧹 Nitpick comments (1)
integration/templates/react-router-node/app/root.tsx (1)

8-8: Add an explicit return type for the public loader.

Keep API surfaces explicit per guidelines.

-export const loader = (args: Route.LoaderArgs) => rootAuthLoader(args);
+export const loader: Route.LoaderFunction = (args) => rootAuthLoader(args);
📜 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 7d1c5bc and 74f4f36.

📒 Files selected for processing (3)
  • integration/templates/react-router-node/app/root.tsx (1 hunks)
  • integration/templates/react-router-node/app/routes/protected.tsx (3 hunks)
  • integration/templates/react-router-node/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • integration/templates/react-router-node/app/routes/protected.tsx
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

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

Use Prettier for consistent code formatting

Files:

  • integration/templates/react-router-node/package.json
  • integration/templates/react-router-node/app/root.tsx
integration/**

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

Framework integration templates and E2E tests should be placed under the integration/ directory

Files:

  • integration/templates/react-router-node/package.json
  • integration/templates/react-router-node/app/root.tsx
integration/**/*

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

End-to-end tests and integration templates must be located in the 'integration/' directory.

Files:

  • integration/templates/react-router-node/package.json
  • integration/templates/react-router-node/app/root.tsx
**/*.{js,jsx,ts,tsx}

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

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
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
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • integration/templates/react-router-node/app/root.tsx
**/*.{ts,tsx}

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

Use proper TypeScript error types

**/*.{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
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
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • integration/templates/react-router-node/app/root.tsx
**/*.{jsx,tsx}

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

**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components: 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
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...

Files:

  • integration/templates/react-router-node/app/root.tsx
**/*.{js,ts,tsx,jsx}

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

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • integration/templates/react-router-node/app/root.tsx
**/*.tsx

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

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

Files:

  • integration/templates/react-router-node/app/root.tsx
🧬 Code graph analysis (1)
integration/templates/react-router-node/app/root.tsx (2)
packages/react-router/src/server/clerkMiddleware.ts (1)
  • clerkMiddleware (33-77)
packages/react-router/src/server/rootAuthLoader.ts (1)
  • rootAuthLoader (118-139)
⏰ 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). (25)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (custom, chrome)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (tanstack-react-router, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 14)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Integration Tests (expo-web, chrome)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome)
  • GitHub Check: Integration Tests (elements, chrome)
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Unit Tests (22, **)
  • GitHub Check: Unit Tests (18, --filter=@clerk/astro --filter=@clerk/backend --filter=@clerk/express --filter=@c...
  • GitHub Check: Static analysis
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (1)
integration/templates/react-router-node/package.json (1)

12-19: Deps bump aligns with the new middleware/context requirements.

@clerk/react-router snapshot and React Router 7.9.x look consistent here.

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

Caution

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

⚠️ Outside diff range comments (1)
integration/templates/react-router-node/app/routes/protected.tsx (1)

3-4: Use new server entrypoint and preconfigured client; avoid deprecated imports and manual secret wiring.

Replace deprecated /ssr.server and /api.server imports with @clerk/react-router/server and use the preconfigured clerkClient instead of constructing one with the secret key.

-import { getAuth } from '@clerk/react-router/ssr.server';
-import { createClerkClient } from '@clerk/react-router/api.server';
+import { getAuth, clerkClient } from '@clerk/react-router/server';
-  const user = await createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY }).users.getUser(userId);
+  const user = await clerkClient.users.getUser(userId);

Location: integration/templates/react-router-node/app/routes/protected.tsx — preconfigured clerkClient available at packages/react-router/src/server/clerkClient.ts.

♻️ Duplicate comments (4)
integration/templates/react-router-node/package.json (2)

9-9: Switch typecheck off “--build”; duplicate of prior feedback.
tsc --build needs "composite": true; this template typically isn’t composite.

-    "typecheck": "react-router typegen && tsc --build --noEmit"
+    "typecheck": "react-router typegen && tsc --noEmit"

11-18: Missing required dependency: @clerk/react-router.
This is a Clerk quickstart; installs will fail without it.

Apply (use one of the versions per your release workflow):

   "dependencies": {
+    "@clerk/react-router": "workspace:*",
     "@react-router/node": "^7.9.1",
     "@react-router/serve": "^7.9.1",
     "isbot": "^5.1.17",
     "react": "^19.1.0",
     "react-dom": "^19.1.0",
     "react-router": "^7.9.1"
   },

If publishing outside the monorepo, prefer:

-    "@clerk/react-router": "workspace:*",
+    "@clerk/react-router": "^2.0.0"
integration/templates/react-router-node/app/routes/protected.tsx (2)

5-5: Types path mismatch for generated Route types.

Use the protected types file to match this route’s filename.

-import type { Route } from './+types/profile';
+import type { Route } from './+types/protected';

16-19: Return typed JSON, set no-store for PII, and null‑safe email selection.

Avoid caching personalized data and don’t assume an email exists; prefer the primary email with a safe fallback.

-  return {
-    firstName: user.firstName,
-    emailAddress: user.emailAddresses[0].emailAddress,
-  };
+  const primaryEmail =
+    user.emailAddresses?.find(e => e.id === user.primaryEmailAddressId) ??
+    user.emailAddresses?.[0];
+  return json<{ firstName: string | null; emailAddress: string | null }>(
+    {
+      firstName: user.firstName ?? null,
+      emailAddress: primaryEmail?.emailAddress ?? null,
+    },
+    { headers: { 'Cache-Control': 'private, no-store' } },
+  );

Add the missing import:

import { json, redirect } from 'react-router';

(Optional) Wrap the fetch in a try/catch to handle deleted users/invalid tokens by redirecting to sign-in.

🧹 Nitpick comments (2)
integration/templates/react-router-node/package.json (1)

25-26: Vite 7 requires modern Node — add an engines guard.
Prevent CI/user mismatches by declaring Node range.

Apply:

 {
   "name": "clerk-react-router-quickstart",
   "private": true,
   "type": "module",
+  "engines": {
+    "node": ">=18.0.0"
+  },
   "scripts": {
integration/templates/react-router-node/app/routes/protected.tsx (1)

28-29: Render fallbacks for possibly null loaderData fields.

Prevents “cannot read” UI glitches when values are absent.

-        <li>First name: {loaderData.firstName}</li>
-        <li>Email: {loaderData.emailAddress}</li>
+        <li>First name: {loaderData.firstName ?? '—'}</li>
+        <li>Email: {loaderData.emailAddress ?? '—'}</li>
📜 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 74f4f36 and d718198.

📒 Files selected for processing (3)
  • integration/templates/react-router-node/app/root.tsx (1 hunks)
  • integration/templates/react-router-node/app/routes/protected.tsx (2 hunks)
  • integration/templates/react-router-node/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • integration/templates/react-router-node/app/root.tsx
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{js,jsx,ts,tsx}

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

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
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
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • integration/templates/react-router-node/app/routes/protected.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

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

Use Prettier for consistent code formatting

Files:

  • integration/templates/react-router-node/app/routes/protected.tsx
  • integration/templates/react-router-node/package.json
**/*.{ts,tsx}

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

Use proper TypeScript error types

**/*.{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
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
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • integration/templates/react-router-node/app/routes/protected.tsx
**/*.{jsx,tsx}

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

**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components: 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
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...

Files:

  • integration/templates/react-router-node/app/routes/protected.tsx
integration/**

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

Framework integration templates and E2E tests should be placed under the integration/ directory

Files:

  • integration/templates/react-router-node/app/routes/protected.tsx
  • integration/templates/react-router-node/package.json
integration/**/*

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

End-to-end tests and integration templates must be located in the 'integration/' directory.

Files:

  • integration/templates/react-router-node/app/routes/protected.tsx
  • integration/templates/react-router-node/package.json
**/*.{js,ts,tsx,jsx}

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

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • integration/templates/react-router-node/app/routes/protected.tsx
**/*.tsx

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

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

Files:

  • integration/templates/react-router-node/app/routes/protected.tsx
⏰ 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). (28)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (custom, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 14)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (tanstack-react-router, chrome)
  • GitHub Check: Integration Tests (expo-web, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (elements, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Unit Tests (18, --filter=@clerk/astro --filter=@clerk/backend --filter=@clerk/express --filter=@c...
  • GitHub Check: Unit Tests (22, **)
  • GitHub Check: Static analysis
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (3)
integration/templates/react-router-node/package.json (3)

12-13: Router core/server bumped to ^7.9.1 — aligned with new minimum.
Looks good and matches the middleware/context requirement.


15-17: React 19 upgrade acknowledged.
Deps are consistent (react/react-dom 19, router 7.9).


20-23: Dev/tooling versions aligned to 7.9 + React 19 types.
No issues spotted.

"test:integration:nuxt": "E2E_APP_ID=nuxt.node npm run test:integration:base -- --grep @nuxt",
"test:integration:quickstart": "E2E_APP_ID=quickstart.* pnpm test:integration:base --grep @quickstart",
"test:integration:react-router": "E2E_APP_ID=react-router.* npm run test:integration:base -- --grep @react-router",
"test:integration:react-router": "E2E_APP_ID=react-router.* pnpm test:integration:base --grep @react-router",
Copy link
Member

Choose a reason for hiding this comment

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

👍🏻

Copy link
Member

@panteliselef panteliselef left a comment

Choose a reason for hiding this comment

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

🚢 🚢

@wobsoriano wobsoriano merged commit 8743290 into main Sep 26, 2025
41 checks passed
@wobsoriano wobsoriano deleted the rob/user-3317-bu branch September 26, 2025 22:18
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.

3 participants