From 7f3bbbf99afd277c1983b21ada633cb0df0c0524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=B6glund?= Date: Thu, 25 Jun 2026 10:41:47 +0200 Subject: [PATCH 1/2] Deprecate createRouteMatcher in nextjs --- .changeset/nextjs-deprecate-route-matcher.md | 22 ++++++++++++++++ .../src/server/__tests__/routeMatcher.test.ts | 26 +++++++++++++++++++ packages/nextjs/src/server/routeMatcher.ts | 13 ++++++++++ 3 files changed, 61 insertions(+) create mode 100644 .changeset/nextjs-deprecate-route-matcher.md create mode 100644 packages/nextjs/src/server/__tests__/routeMatcher.test.ts diff --git a/.changeset/nextjs-deprecate-route-matcher.md b/.changeset/nextjs-deprecate-route-matcher.md new file mode 100644 index 00000000000..b1979d744ef --- /dev/null +++ b/.changeset/nextjs-deprecate-route-matcher.md @@ -0,0 +1,22 @@ +--- +'@clerk/nextjs': patch +--- + +Deprecate `createRouteMatcher()` in favor of resource-based auth checks. + +Middleware-based auth checks rely on path matching, which can diverge from how Next.js routes requests and leave protected resources reachable. + +For a migration guide, see: + https://clerk.com/docs/guides/development/upgrading/upgrade-guides/migrating-from-create-route-matcher + +Instead of protecting routes from middleware, move auth checks into each protected page, layout, API route, or Server Function, for example: + +```ts +import { auth } from '@clerk/nextjs/server' + +export default async function Page() { + await auth.protect() + + return

Dashboard

+} +``` diff --git a/packages/nextjs/src/server/__tests__/routeMatcher.test.ts b/packages/nextjs/src/server/__tests__/routeMatcher.test.ts new file mode 100644 index 00000000000..d4871c93d5e --- /dev/null +++ b/packages/nextjs/src/server/__tests__/routeMatcher.test.ts @@ -0,0 +1,26 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { createRouteMatcher } from '../routeMatcher'; + +const { mockDeprecated } = vi.hoisted(() => ({ + mockDeprecated: vi.fn(), +})); + +vi.mock('@clerk/shared/deprecated', () => ({ + deprecated: mockDeprecated, +})); + +describe('createRouteMatcher', () => { + beforeEach(() => { + mockDeprecated.mockClear(); + }); + + it('should emit a deprecation warning when called', () => { + createRouteMatcher(['/foo(.*)']); + + expect(mockDeprecated).toHaveBeenCalledWith( + 'createRouteMatcher', + 'Use resource-based auth checks instead. Move auth checks into each page, layout, API route, or Server Function that accesses protected data. Middleware-based auth checks rely on path matching, which can diverge from how Next.js routes requests and leave protected resources reachable. For a migration guide, see: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/migrating-from-create-route-matcher', + ); + }); +}); diff --git a/packages/nextjs/src/server/routeMatcher.ts b/packages/nextjs/src/server/routeMatcher.ts index 428fc3e9dec..b8fd30705b1 100644 --- a/packages/nextjs/src/server/routeMatcher.ts +++ b/packages/nextjs/src/server/routeMatcher.ts @@ -1,3 +1,4 @@ +import { deprecated } from '@clerk/shared/deprecated'; import { createPathMatcher, type WithPathPatternWildcard } from '@clerk/shared/pathMatcher'; import type { Autocomplete } from '@clerk/shared/types'; import type Link from 'next/link'; @@ -19,8 +20,20 @@ export type RouteMatcherParam = * You can use glob patterns to match multiple routes or a function to match against the request object. * Path patterns and regular expressions are supported, for example: `['/foo', '/bar(.*)'] or `[/^\/foo\/.*$/]` * For more information, see: https://clerk.com/docs + * + * @deprecated This function will be removed in the next major version. Use resource-based auth checks instead. + * Move auth checks into each page, layout, API route, or Server Function that accesses protected data. + * Middleware-based auth checks rely on path matching, which can diverge from how Next.js routes requests and + * leave protected resources reachable. + * + * For a migration guide, see: + * https://clerk.com/docs/guides/development/upgrading/upgrade-guides/migrating-from-create-route-matcher */ export const createRouteMatcher = (routes: RouteMatcherParam) => { + deprecated( + 'createRouteMatcher', + 'Use resource-based auth checks instead. Move auth checks into each page, layout, API route, or Server Function that accesses protected data. Middleware-based auth checks rely on path matching, which can diverge from how Next.js routes requests and leave protected resources reachable. For a migration guide, see: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/migrating-from-create-route-matcher', + ); if (typeof routes === 'function') { return (req: NextRequest) => routes(req); } From 938f7a5e63a7eb012c67603c3814db68c3fca5c5 Mon Sep 17 00:00:00 2001 From: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> Date: Wed, 1 Jul 2026 16:02:21 -0700 Subject: [PATCH 2/2] Update links to migration guide Co-authored-by: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> --- .changeset/nextjs-deprecate-route-matcher.md | 2 +- packages/nextjs/src/server/__tests__/routeMatcher.test.ts | 2 +- packages/nextjs/src/server/routeMatcher.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.changeset/nextjs-deprecate-route-matcher.md b/.changeset/nextjs-deprecate-route-matcher.md index b1979d744ef..b1110fc1c1f 100644 --- a/.changeset/nextjs-deprecate-route-matcher.md +++ b/.changeset/nextjs-deprecate-route-matcher.md @@ -7,7 +7,7 @@ Deprecate `createRouteMatcher()` in favor of resource-based auth checks. Middleware-based auth checks rely on path matching, which can diverge from how Next.js routes requests and leave protected resources reachable. For a migration guide, see: - https://clerk.com/docs/guides/development/upgrading/upgrade-guides/migrating-from-create-route-matcher + https://clerk.com/docs/guides/development/upgrading/upgrade-guides/migrate-from-create-route-matcher Instead of protecting routes from middleware, move auth checks into each protected page, layout, API route, or Server Function, for example: diff --git a/packages/nextjs/src/server/__tests__/routeMatcher.test.ts b/packages/nextjs/src/server/__tests__/routeMatcher.test.ts index d4871c93d5e..ad893c445da 100644 --- a/packages/nextjs/src/server/__tests__/routeMatcher.test.ts +++ b/packages/nextjs/src/server/__tests__/routeMatcher.test.ts @@ -20,7 +20,7 @@ describe('createRouteMatcher', () => { expect(mockDeprecated).toHaveBeenCalledWith( 'createRouteMatcher', - 'Use resource-based auth checks instead. Move auth checks into each page, layout, API route, or Server Function that accesses protected data. Middleware-based auth checks rely on path matching, which can diverge from how Next.js routes requests and leave protected resources reachable. For a migration guide, see: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/migrating-from-create-route-matcher', + 'Use resource-based auth checks instead. Move auth checks into each page, layout, API route, or Server Function that accesses protected data. Middleware-based auth checks rely on path matching, which can diverge from how Next.js routes requests and leave protected resources reachable. For a migration guide, see: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/migrate-from-create-route-matcher', ); }); }); diff --git a/packages/nextjs/src/server/routeMatcher.ts b/packages/nextjs/src/server/routeMatcher.ts index b8fd30705b1..24d3505da89 100644 --- a/packages/nextjs/src/server/routeMatcher.ts +++ b/packages/nextjs/src/server/routeMatcher.ts @@ -27,12 +27,12 @@ export type RouteMatcherParam = * leave protected resources reachable. * * For a migration guide, see: - * https://clerk.com/docs/guides/development/upgrading/upgrade-guides/migrating-from-create-route-matcher + * https://clerk.com/docs/guides/development/upgrading/upgrade-guides/migrate-from-create-route-matcher */ export const createRouteMatcher = (routes: RouteMatcherParam) => { deprecated( 'createRouteMatcher', - 'Use resource-based auth checks instead. Move auth checks into each page, layout, API route, or Server Function that accesses protected data. Middleware-based auth checks rely on path matching, which can diverge from how Next.js routes requests and leave protected resources reachable. For a migration guide, see: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/migrating-from-create-route-matcher', + 'Use resource-based auth checks instead. Move auth checks into each page, layout, API route, or Server Function that accesses protected data. Middleware-based auth checks rely on path matching, which can diverge from how Next.js routes requests and leave protected resources reachable. For a migration guide, see: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/migrate-from-create-route-matcher', ); if (typeof routes === 'function') { return (req: NextRequest) => routes(req);