-
Notifications
You must be signed in to change notification settings - Fork 386
feat(react-router): Introduce middleware and context #6660
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: d94a79c The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (1)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including You can disable this status message by setting the WalkthroughIntroduces a new server middleware-based auth flow for @clerk/react-router, adds a server subpath export, and updates types/APIs to support middleware contexts. Deprecates SSR import paths, adds deprecation warnings, and removes legacy SSR implementations. Updates integration templates, configs, and tests accordingly, with various dependency version bumps. Changes
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: Invoke middleware chain
MW->>CC: authenticateRequest(patched request, options)
alt Redirect (Location header)
MW-->>RR: 307 Redirect with Clerk headers
RR-->>U: Redirect response
else Handshake without redirect
MW-->>RR: Error (handshake status)
else Auth state available
MW->>RR: Set contexts (requestState, authFn)
MW-->>RR: next()
RR->>LD: Route loader executes
opt getAuth called
LD->>RR: Check authFnContext
alt Context present
RR-->>LD: authFn provides authObject
else Legacy path
LD->>CC: legacyAuthenticateRequest()
CC-->>LD: requestState.toAuth()
end
LD-->>RR: Loader returns data/Response
end
RR-->>U: Response (with propagated Clerk headers)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal). Please share your feedback with us on this Discord post. Comment |
@clerk/agent-toolkit
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/dev-cli
@clerk/elements
@clerk/clerk-expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/clerk-react
@clerk/react-router
@clerk/remix
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/themes
@clerk/types
@clerk/upgrade
@clerk/vue
commit: |
There was a problem hiding this 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 authenticateRequestacceptsToken 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 warningMinor 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 goodAdd 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 versionClarify 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 optionsIf 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 annotateclerkClient
’s return type asClerkClient
.integration/tests/react-router/basic.test.ts (1)
92-102
: Prefer test IDs over text to reduce flakiness; consider unskipping when stableText-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 coverageVerify 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
: Avoidexport *
barrel; prefer explicit, tree-shakable exports to reduce circular-deps riskRe-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 testsUnset 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 signalAlso 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 pathTighten 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()
errorsIf
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 exportAdd 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 cancellationTie 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 takesDataFunctionArgs
; callers likegetAuth
may still be typed withLoaderFunctionArgs
. ExportDataFunctionArgs
from a centraltypes.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 flakinessRunning 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 typesUse 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 typePrefer unknown for RootAuthLoaderCallback generic.
- handler?: RootAuthLoaderCallback<any>, + handler?: RootAuthLoaderCallback<unknown>,
60-64
: Avoid any in LoaderFunctionArgsWithAuth castUse 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.
⛔ 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
Avoidany
type - preferunknown
when type is uncertain, then narrow with type guards
Useinterface
for object shapes that might be extended
Usetype
for unions, primitives, and computed types
Preferreadonly
properties for immutable data structures
Useprivate
for internal implementation details
Useprotected
for inheritance hierarchies
Usepublic
explicitly for clarity in public APIs
Preferreadonly
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
Useconst assertions
for literal types:as const
Usesatisfies
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 ...
Noany
types without justification
Proper error handling with typed errors
Consistent use ofreadonly
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: LGTMintegration/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: LGTMpackages/react-router/src/ssr/index.ts (1)
1-2
: LGTM: explicit named re-exportsExplicit 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 — OKTitle 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 APIunstable_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 templateAre 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 splitThe rootAuthLoader flow correctly prefers middleware, warns once when missing, and handles injection/redirect semantics appropriately.
packages/react-router/src/server/__tests__/rootAuthLoader.test.ts
Outdated
Show resolved
Hide resolved
const requestState = await clerkClient(args).authenticateRequest(patchRequest(request), { | ||
apiUrl, |
There was a problem hiding this comment.
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):
- 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}`,
});
};
- 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.
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.
// Only add Clerk headers if requested (for legacy mode) | ||
if (includeClerkHeaders) { | ||
headers.forEach((value, key) => { | ||
clone.headers.append(key, value); | ||
}); | ||
} |
There was a problem hiding this comment.
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.
// 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.
There was a problem hiding this 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 implementationThis 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 appendAppending 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 examplePublic 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 runsUsing 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-throughprocessRootAuthLoader 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.warnOnceUse 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 authObject.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 onlyThe 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.
📒 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
Avoidany
type - preferunknown
when type is uncertain, then narrow with type guards
Useinterface
for object shapes that might be extended
Usetype
for unions, primitives, and computed types
Preferreadonly
properties for immutable data structures
Useprivate
for internal implementation details
Useprotected
for inheritance hierarchies
Usepublic
explicitly for clarity in public APIs
Preferreadonly
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
Useconst assertions
for literal types:as const
Usesatisfies
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 ...
Noany
types without justification
Proper error handling with typed errors
Consistent use ofreadonly
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 pathLoading options, authenticating, decorating request, and reusing the same processor keeps behavior consistent while guiding migration.
There was a problem hiding this 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.
📒 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
Avoidany
type - preferunknown
when type is uncertain, then narrow with type guards
Useinterface
for object shapes that might be extended
Usetype
for unions, primitives, and computed types
Preferreadonly
properties for immutable data structures
Useprivate
for internal implementation details
Useprotected
for inheritance hierarchies
Usepublic
explicitly for clarity in public APIs
Preferreadonly
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
Useconst assertions
for literal types:as const
Usesatisfies
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 ...
Noany
types without justification
Proper error handling with typed errors
Consistent use ofreadonly
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
Confirmedunstable_middleware: true
inintegration/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.
There was a problem hiding this 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 withfuture.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.
📒 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
Avoidany
type - preferunknown
when type is uncertain, then narrow with type guards
Useinterface
for object shapes that might be extended
Usetype
for unions, primitives, and computed types
Preferreadonly
properties for immutable data structures
Useprivate
for internal implementation details
Useprotected
for inheritance hierarchies
Usepublic
explicitly for clarity in public APIs
Preferreadonly
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
Useconst assertions
for literal types:as const
Usesatisfies
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 ...
Noany
types without justification
Proper error handling with typed errors
Consistent use ofreadonly
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.
There was a problem hiding this 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_KEYCapture 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 assertionsUse 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 fieldmockContext.set is never used in this suite.
- }), - set: vi.fn(), + }),
48-53
: Add an assertion that middleware context was queriedThis 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 argsCovers 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.
📒 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
Avoidany
type - preferunknown
when type is uncertain, then narrow with type guards
Useinterface
for object shapes that might be extended
Usetype
for unions, primitives, and computed types
Preferreadonly
properties for immutable data structures
Useprivate
for internal implementation details
Useprotected
for inheritance hierarchies
Usepublic
explicitly for clarity in public APIs
Preferreadonly
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
Useconst assertions
for literal types:as const
Usesatisfies
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 ...
Noany
types without justification
Proper error handling with typed errors
Consistent use ofreadonly
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 pathsThis test correctly verifies the short-circuit when middleware context is present and asserts the normalized tokenType. Looks solid.
There was a problem hiding this 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 (4)
.changeset/quiet-bats-protect.md (4)
7-8
: Deprecation phrasing conflicts with an immediate major bump — clarify timeline.You’re shipping a major now while saying removal happens “in the next major.” Reword to avoid ambiguity.
Apply this edit:
-Usage of `rootAuthLoader` without the `clerkMiddleware()` installed is now deprecated and will be removed in the next major version. +Usage of `rootAuthLoader` without `clerkMiddleware()` is deprecated in this release and scheduled for removal in a subsequent major version. Migrate to `clerkMiddleware()` + `rootAuthLoader` now.
5-5
: Call out all breaking requirements and deprecations up front.Add bullets for the minimum React Router version and deprecated import paths to align with the PR description.
Apply this insertion after the introductory sentence:
Introduce [React Router middleware](https://reactrouter.com/how-to/middleware) support with `clerkMiddleware()` for improved performance and streaming capabilities. + +Breaking changes and deprecations: +- Requires React Router >= 7.9.0 (relies on the stable Middleware and Context APIs). +- `@clerk/react-router/ssr.server` and `@clerk/react-router/api.server` are deprecated in favor of `@clerk/react-router/server` and will be removed in a future major.
21-28
: Add missing type import in the config snippet.Without importing
Config
, thesatisfies Config
line is incomplete.Apply this tweak:
```ts -// react-router.config.ts +// react-router.config.ts +import type { Config } from '@react-router/dev/config'; export default { future: { v8_middleware: true, }, } satisfies Config;--- `40-54`: **Optional doc polish: mention promise streaming support explicitly.** Add one sentence clarifying that `rootAuthLoader` may return promises when middleware is enabled (RR >=7.9), matching the objective USER-2693. Proposed addition right above the example: ```diff **Streaming Support (with middleware):** +When using React Router >=7.9 with `clerkMiddleware()`, your `rootAuthLoader` can return promises to enable streaming responses.
📜 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.
📒 Files selected for processing (1)
.changeset/quiet-bats-protect.md
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/**
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Automated releases must use Changesets.
Files:
.changeset/quiet-bats-protect.md
⏰ 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 (billing, chrome)
- GitHub Check: Integration Tests (react-router, chrome)
- GitHub Check: Integration Tests (nuxt, chrome)
- GitHub Check: Integration Tests (nextjs, chrome, 14)
- GitHub Check: Integration Tests (nextjs, chrome, 15)
- GitHub Check: Integration Tests (custom, chrome)
- GitHub Check: Integration Tests (machine, chrome)
- GitHub Check: Integration Tests (astro, chrome)
- GitHub Check: Integration Tests (generic, chrome)
- GitHub Check: Integration Tests (tanstack-react-start, chrome)
- GitHub Check: Integration Tests (vue, chrome)
- GitHub Check: Integration Tests (sessions, chrome)
- GitHub Check: Integration Tests (tanstack-react-router, chrome)
- GitHub Check: Integration Tests (localhost, chrome)
- GitHub Check: Integration Tests (elements, chrome)
- GitHub Check: Integration Tests (quickstart, chrome)
- GitHub Check: Integration Tests (expo-web, chrome)
- GitHub Check: Integration Tests (ap-flows, chrome)
- GitHub Check: Integration Tests (express, chrome)
- GitHub Check: Publish with pkg-pr-new
- GitHub Check: Unit Tests (22, **)
- GitHub Check: Static analysis
- GitHub Check: Unit Tests (18, --filter=@clerk/astro --filter=@clerk/backend --filter=@clerk/express --filter=@c...
- 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)
.changeset/quiet-bats-protect.md (1)
1-3
: Frontmatter fixed — good to release.The changeset frontmatter is now valid and marks a major bump for @clerk/react-router.
Before merging, confirm whether any sibling packages (templates/integrations) also require bumps or dependent releases in the same batch so the release notes remain coherent.
2. Use the middleware in your app: | ||
|
||
```tsx | ||
import { clerkMiddleware, rootAuthLoader } from '@clerk/react-router/server' | ||
|
||
export const middleware: Route.MiddlewareFunction[] = [clerkMiddleware()] | ||
|
||
export const loader = (args: Route.LoaderArgs) => rootAuthLoader(args) | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify stable API names: middleware
key, Route.MiddlewareFunction
, and future.v8_middleware
.
These names depend on the exact React Router version. Your PR text says “stable APIs” on >=7.9.0; if consumers are below that, they may still need unstable_middleware
. Keep the snippet as-is if we’re hard-requiring 7.9+, but let’s double-check the flag and type names.
🌐 Web query:
For React Router v7.9.0 and later:
- Is the feature flag name `future.v8_middleware` correct for enabling middleware on the Node adapter?
- Is the route export key `middleware` (not `unstable_middleware`) the correct stable name?
- Is the type `Route.MiddlewareFunction` the correct stable type name?
💡 Result:
Short answers:
- No. The runtime feature flag to enable middleware is future.unstable_middleware (not future.v8_middleware). [1][2]
- No. The stable route export in the docs remains unstable_middleware (the docs show export const unstable_middleware = …). [1]
- No. The documented type is Route.unstable_MiddlewareFunction (not Route.MiddlewareFunction). [1][3]
Sources:
- React Router Middleware docs (shows future.unstable_middleware, export unstable_middleware, and Route.unstable_MiddlewareFunction examples). [turn0search0].
- React Router changelog (v7.9.1 notes about internal Future interface naming fixes). [turn0search1].
- Route Module docs / examples showing unstable_middleware usage. [turn0search2].
Use documented unstable middleware names (fix snippet + PR text)
File: .changeset/quiet-bats-protect.md (lines 30–38)
- Replace future.v8_middleware → future.unstable_middleware (runtime flag).
- Replace export const middleware → export const unstable_middleware (route export).
- Use Route.unstable_MiddlewareFunction (type) instead of Route.MiddlewareFunction.
- Either update the snippet to use these unstable names, or change the PR to require and cite the exact React Router version that actually exposes stable middleware names and verify those names.
🤖 Prompt for AI Agents
In .changeset/quiet-bats-protect.md around lines 30–38, the provided snippet
uses stable middleware names that aren’t available; update the snippet and PR
text to use the unstable names: change the runtime flag future.v8_middleware to
future.unstable_middleware, change the route export from export const middleware
to export const unstable_middleware, and use the
Route.unstable_MiddlewareFunction type instead of Route.MiddlewareFunction;
alternatively, if you want to keep the stable names, update the PR to explicitly
require and cite the exact React Router version that exposes those stable
middleware names and verify the names in the documentation.
!snapshot |
Hey @wobsoriano - the snapshot version command generated the following package versions:
Tip: Use the snippet copy button below to quickly install the required packages. npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact
npm i @clerk/[email protected] --save-exact |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
integration/templates/react-router-node/app/routes/protected.tsx (1)
6-11
: Return typed JSON with no-store, handle missing/deleted users, don’t assume an email exists.Add defensive fetch + primary email selection, avoid caching PII, and provide an explicit return type for the public loader. This mirrors prior feedback.
-export async function loader(args: Route.LoaderArgs) { +/** Loader for the protected route. Returns minimal, non-PII-cached user info. */ +export async function loader(args: Route.LoaderArgs): Promise<Response> { const { userId } = await getAuth(args); if (!userId) { return redirect('/sign-in'); } - const user = await createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY }).users.getUser(userId); - - return { - firstName: user.firstName, - emailAddress: user.emailAddresses[0].emailAddress, - }; + try { + const user = await clerkClient.users.getUser(userId); + 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' } }, + ); + } catch (_err: unknown) { + // User may be deleted or token invalid; force re-auth. + return redirect('/sign-in'); + } }Also applies to: 15-18
🧹 Nitpick comments (2)
integration/templates/react-router-node/app/routes/protected.tsx (2)
21-29
: Null-safe render and explicit component return type.Guard against nulls from the loader and declare the return type.
-export default function Profile({ loaderData }: Route.ComponentProps) { +/** Protected profile page. */ +export default function Profile({ loaderData }: Route.ComponentProps): JSX.Element { return ( <div> <h1>Protected</h1> <UserProfile /> <ul> - <li>First name: {loaderData.firstName}</li> - <li>Email: {loaderData.emailAddress}</li> + <li>First name: {loaderData.firstName ?? '—'}</li> + <li>Email: {loaderData.emailAddress ?? '—'}</li> </ul> </div> ); }
33-33
: Add a route-level ErrorBoundary for better DX.Optional but recommended per guidelines.
+export function ErrorBoundary(): JSX.Element { + // eslint-disable-next-line @typescript-eslint/consistent-type-imports + const { isRouteErrorResponse, useRouteError } = require('react-router') as typeof import('react-router'); + const err = useRouteError(); + if (isRouteErrorResponse(err)) { + return ( + <div role="alert"> + <h1>Something went wrong</h1> + <p> + {err.status} {err.statusText} + </p> + </div> + ); + } + return ( + <div role="alert"> + <h1>Unexpected error</h1> + <pre>{String(err)}</pre> + </div> + ); +}
📜 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.
📒 Files selected for processing (2)
integration/templates/react-router-node/app/root.tsx
(1 hunks)integration/templates/react-router-node/app/routes/protected.tsx
(3 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
**/*.{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
Avoidany
type - preferunknown
when type is uncertain, then narrow with type guards
Useinterface
for object shapes that might be extended
Usetype
for unions, primitives, and computed types
Preferreadonly
properties for immutable data structures
Useprivate
for internal implementation details
Useprotected
for inheritance hierarchies
Usepublic
explicitly for clarity in public APIs
Preferreadonly
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
Useconst assertions
for literal types:as const
Usesatisfies
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 ...
Noany
types without justification
Proper error handling with typed errors
Consistent use ofreadonly
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/**/*
📄 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
**/*.{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). (27)
- GitHub Check: Integration Tests (custom, chrome)
- GitHub Check: Integration Tests (machine, chrome)
- GitHub Check: Integration Tests (nextjs, chrome, 14)
- GitHub Check: Integration Tests (nextjs, chrome, 15)
- GitHub Check: Integration Tests (billing, chrome)
- GitHub Check: Integration Tests (react-router, chrome)
- GitHub Check: Integration Tests (nuxt, chrome)
- GitHub Check: Integration Tests (ap-flows, chrome)
- GitHub Check: Integration Tests (vue, chrome)
- GitHub Check: Integration Tests (tanstack-react-router, chrome)
- GitHub Check: Integration Tests (astro, chrome)
- GitHub Check: Integration Tests (expo-web, chrome)
- GitHub Check: Integration Tests (elements, chrome)
- GitHub Check: Integration Tests (tanstack-react-start, chrome)
- GitHub Check: Integration Tests (quickstart, chrome)
- GitHub Check: Integration Tests (sessions, chrome)
- GitHub Check: Integration Tests (localhost, chrome)
- GitHub Check: Integration Tests (express, chrome)
- GitHub Check: Integration Tests (generic, chrome)
- GitHub Check: Publish with pkg-pr-new
- 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: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (1)
integration/templates/react-router-node/app/routes/protected.tsx (1)
1-4
: Do not migrate to @clerk/react-router/server — the suggested exports are not available.The targeted version does not export both
clerkClient
andgetAuth
from@clerk/react-router/server
, and@clerk/react-router/ssr.server
is not marked deprecated. Keep usinggetAuth
from@clerk/react-router/ssr.server
and your existing server-side client pattern (e.g.,createClerkClient
/api.server
) instead of switching toclerkClient
. Importjson
fromreact-router
if you need typed responses.File: integration/templates/react-router-node/app/routes/protected.tsx (lines 1–4)
Likely an incorrect or invalid review comment.
There was a problem hiding this 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 plaintsc --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.
📒 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
Avoidany
type - preferunknown
when type is uncertain, then narrow with type guards
Useinterface
for object shapes that might be extended
Usetype
for unions, primitives, and computed types
Preferreadonly
properties for immutable data structures
Useprivate
for internal implementation details
Useprotected
for inheritance hierarchies
Usepublic
explicitly for clarity in public APIs
Preferreadonly
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
Useconst assertions
for literal types:as const
Usesatisfies
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 ...
Noany
types without justification
Proper error handling with typed errors
Consistent use ofreadonly
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.
There was a problem hiding this 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.
📒 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
Avoidany
type - preferunknown
when type is uncertain, then narrow with type guards
Useinterface
for object shapes that might be extended
Usetype
for unions, primitives, and computed types
Preferreadonly
properties for immutable data structures
Useprivate
for internal implementation details
Useprotected
for inheritance hierarchies
Usepublic
explicitly for clarity in public APIs
Preferreadonly
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
Useconst assertions
for literal types:as const
Usesatisfies
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 ...
Noany
types without justification
Proper error handling with typed errors
Consistent use ofreadonly
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.
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
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:
After:
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.Type of change
Summary by CodeRabbit