From 13727db2364266968266072f3da0f4b4611e3b1e Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Thu, 29 Jan 2026 15:37:39 -0600 Subject: [PATCH] feat(nextjs): Update middleware references to proxy for Next.js 16 compatibility Align terminology with Next.js 16 which renamed Middleware to Proxy. This includes renaming middleware.ts files to proxy.ts and updating all internal references and error messages. The clerkMiddleware() function name remains unchanged. Co-Authored-By: Claude Haiku 4.5 --- ...cement.test.ts => proxy-placement.test.ts} | 37 +++++++++---------- packages/nextjs/src/app-router/server/auth.ts | 4 +- packages/nextjs/src/server/createGetAuth.ts | 8 ++-- packages/nextjs/src/server/errors.ts | 6 +-- ...ddleware-location.ts => proxy-location.ts} | 16 ++++---- 5 files changed, 33 insertions(+), 38 deletions(-) rename integration/tests/{middleware-placement.test.ts => proxy-placement.test.ts} (68%) rename packages/nextjs/src/server/fs/{middleware-location.ts => proxy-location.ts} (64%) diff --git a/integration/tests/middleware-placement.test.ts b/integration/tests/proxy-placement.test.ts similarity index 68% rename from integration/tests/middleware-placement.test.ts rename to integration/tests/proxy-placement.test.ts index 42bc1b7227f..a7c7c7f520c 100644 --- a/integration/tests/middleware-placement.test.ts +++ b/integration/tests/proxy-placement.test.ts @@ -42,7 +42,7 @@ async function detectNext(app: Application): Promise<{ version: string | undefin return { version: installedVersion }; } -const middlewareFileContents = ` +const proxyFileContents = ` import { clerkMiddleware } from '@clerk/nextjs/server'; export default clerkMiddleware(); @@ -51,9 +51,9 @@ export const config = { }; `; -const commonSetup = appConfigs.next.appRouterQuickstart.clone().removeFile('src/middleware.ts'); +const commonSetup = appConfigs.next.appRouterQuickstart.clone().removeFile('src/proxy.ts'); -test.describe('next start - missing middleware @quickstart', () => { +test.describe('next start - missing proxy @quickstart', () => { test.describe.configure({ mode: 'parallel' }); let app: Application; @@ -70,21 +70,21 @@ test.describe('next start - missing middleware @quickstart', () => { await app.teardown(); }); - test('Display error for missing middleware', async ({ page, context }) => { + test('Display error for missing proxy', async ({ page, context }) => { const u = createTestUtils({ app, page, context }); await u.page.goToAppHome(); - expect(app.serveOutput).toContain('Your Middleware exists at ./src/middleware.(ts|js)'); + expect(app.serveOutput).toContain('Your Proxy exists at ./src/proxy.(ts|js)'); }); }); -test.describe('next start - invalid middleware at root on src/ @quickstart', () => { +test.describe('next start - invalid proxy at root on src/ @quickstart', () => { test.describe.configure({ mode: 'parallel' }); let app: Application; test.beforeAll(async () => { test.setTimeout(90_000); - app = await commonSetup.addFile('middleware.ts', () => middlewareFileContents).commit(); + app = await commonSetup.addFile('proxy.ts', () => proxyFileContents).commit(); await app.setup(); await app.withEnv(appConfigs.envs.withEmailCodesQuickstart); await app.build(); @@ -95,23 +95,20 @@ test.describe('next start - invalid middleware at root on src/ @quickstart', () await app.teardown(); }); - test('Display suggestion for moving middleware to from `./middleware.ts` to `./src/middleware.ts`', async ({ - page, - context, - }) => { + test('Display suggestion for moving proxy from `./proxy.ts` to `./src/proxy.ts`', async ({ page, context }) => { const { version } = await detectNext(app); const major = parseSemverMajor(version) ?? 0; - test.skip(major >= 16, 'Middleware detection is smarter in Next 16+.'); + test.skip(major >= 16, 'Proxy detection is smarter in Next 16+.'); const u = createTestUtils({ app, page, context }); await u.page.goToAppHome(); - expect(app.serveOutput).not.toContain('Your Middleware exists at ./src/middleware.(ts|js)'); + expect(app.serveOutput).not.toContain('Your Proxy exists at ./src/proxy.(ts|js)'); expect(app.serveOutput).toContain( - 'Clerk: clerkMiddleware() was not run, your middleware file might be misplaced. Move your middleware file to ./src/middleware.ts. Currently located at ./middleware.ts', + 'Clerk: clerkMiddleware() was not run, your proxy file might be misplaced. Move your proxy file to ./src/proxy.ts. Currently located at ./proxy.ts', ); }); - test('Does not display misplaced middleware error on Next 16+', async ({ page, context }) => { + test('Does not display misplaced proxy error on Next 16+', async ({ page, context }) => { const { version } = await detectNext(app); const major = parseSemverMajor(version) ?? 0; test.skip(major < 16, 'Only applicable on Next 16+'); @@ -121,13 +118,13 @@ test.describe('next start - invalid middleware at root on src/ @quickstart', () }); }); -test.describe('next start - invalid middleware inside app on src/ @quickstart', () => { +test.describe('next start - invalid proxy inside app on src/ @quickstart', () => { test.describe.configure({ mode: 'parallel' }); let app: Application; test.beforeAll(async () => { test.setTimeout(90_000); - app = await commonSetup.addFile('src/app/middleware.ts', () => middlewareFileContents).commit(); + app = await commonSetup.addFile('src/app/proxy.ts', () => proxyFileContents).commit(); await app.setup(); await app.withEnv(appConfigs.envs.withEmailCodesQuickstart); await app.build(); @@ -138,15 +135,15 @@ test.describe('next start - invalid middleware inside app on src/ @quickstart', await app.teardown(); }); - test('Display suggestion for moving middleware to from `./src/app/middleware.ts` to `./src/middleware.ts`', async ({ + test('Display suggestion for moving proxy from `./src/app/proxy.ts` to `./src/proxy.ts`', async ({ page, context, }) => { const u = createTestUtils({ app, page, context }); await u.page.goToAppHome(); - expect(app.serveOutput).not.toContain('Your Middleware exists at ./src/middleware.(ts|js)'); + expect(app.serveOutput).not.toContain('Your Proxy exists at ./src/proxy.(ts|js)'); expect(app.serveOutput).toContain( - 'Clerk: clerkMiddleware() was not run, your middleware file might be misplaced. Move your middleware file to ./src/middleware.ts. Currently located at ./src/app/middleware.ts', + 'Clerk: clerkMiddleware() was not run, your proxy file might be misplaced. Move your proxy file to ./src/proxy.ts. Currently located at ./src/app/proxy.ts', ); }); }); diff --git a/packages/nextjs/src/app-router/server/auth.ts b/packages/nextjs/src/app-router/server/auth.ts index f5ce9a3190d..3f77c7085dc 100644 --- a/packages/nextjs/src/app-router/server/auth.ts +++ b/packages/nextjs/src/app-router/server/auth.ts @@ -75,8 +75,8 @@ export const auth: AuthFn = (async (options?: AuthOptions) => { const stepsBasedOnSrcDirectory = async () => { try { - const isSrcAppDir = await import('../../server/fs/middleware-location.js').then(m => m.hasSrcAppDir()); - return [`Your Middleware exists at ./${isSrcAppDir ? 'src/' : ''}middleware.(ts|js)`]; + const isSrcAppDir = await import('../../server/fs/proxy-location.js').then(m => m.hasSrcAppDir()); + return [`Your Proxy exists at ./${isSrcAppDir ? 'src/' : ''}proxy.(ts|js)`]; } catch { return []; } diff --git a/packages/nextjs/src/server/createGetAuth.ts b/packages/nextjs/src/server/createGetAuth.ts index 0b29d105b27..b238f611885 100644 --- a/packages/nextjs/src/server/createGetAuth.ts +++ b/packages/nextjs/src/server/createGetAuth.ts @@ -36,12 +36,12 @@ export const createAsyncGetAuth = ({ } if (!detectClerkMiddleware(req)) { - const missConfiguredMiddlewareLocation = await import('./fs/middleware-location.js') - .then(m => m.suggestMiddlewareLocation()) + const misconfiguredProxyLocation = await import('./fs/proxy-location.js') + .then(m => m.suggestProxyLocation()) .catch(() => undefined); - if (missConfiguredMiddlewareLocation) { - throw new Error(missConfiguredMiddlewareLocation); + if (misconfiguredProxyLocation) { + throw new Error(misconfiguredProxyLocation); } // still throw there is no suggested move location diff --git a/packages/nextjs/src/server/errors.ts b/packages/nextjs/src/server/errors.ts index bb0fc99ba4a..f9de3630a8f 100644 --- a/packages/nextjs/src/server/errors.ts +++ b/packages/nextjs/src/server/errors.ts @@ -22,9 +22,9 @@ export const getAuthAuthHeaderMissing = () => authAuthHeaderMissing('getAuth'); export const authAuthHeaderMissing = (helperName = 'auth', prefixSteps?: string[]) => `Clerk: ${helperName}() was called but Clerk can't detect usage of clerkMiddleware(). Please ensure the following: -- ${prefixSteps ? [...prefixSteps, ''].join('\n- ') : ' '}clerkMiddleware() is used in your Next.js Middleware. -- Your Middleware matcher is configured to match this route or page. -- If you are using the src directory, make sure the Middleware file is inside of it. +- ${prefixSteps ? [...prefixSteps, ''].join('\n- ') : ' '}clerkMiddleware() is used in your Next.js Proxy. +- Your Proxy matcher is configured to match this route or page. +- If you are using the src directory, make sure the Proxy file is inside of it. For more details, see https://clerk.com/err/auth-middleware `; diff --git a/packages/nextjs/src/server/fs/middleware-location.ts b/packages/nextjs/src/server/fs/proxy-location.ts similarity index 64% rename from packages/nextjs/src/server/fs/middleware-location.ts rename to packages/nextjs/src/server/fs/proxy-location.ts index 3586d4a1ae2..94bac76b040 100644 --- a/packages/nextjs/src/server/fs/middleware-location.ts +++ b/packages/nextjs/src/server/fs/proxy-location.ts @@ -10,14 +10,14 @@ function hasSrcAppDir() { return !!existsSync(projectWithAppSrc); } -function suggestMiddlewareLocation() { +function suggestProxyLocation() { const fileExtensions = ['ts', 'js'] as const; const suggestionMessage = ( extension: (typeof fileExtensions)[number], to: 'src/' | '', from: 'src/app/' | 'app/' | '', ) => - `Clerk: clerkMiddleware() was not run, your middleware file might be misplaced. Move your middleware file to ./${to}middleware.${extension}. Currently located at ./${from}middleware.${extension}`; + `Clerk: clerkMiddleware() was not run, your proxy file might be misplaced. Move your proxy file to ./${to}proxy.${extension}. Currently located at ./${from}proxy.${extension}`; const { existsSync } = nodeFsOrThrow(); const path = nodePathOrThrow(); @@ -26,13 +26,13 @@ function suggestMiddlewareLocation() { const projectWithAppSrcPath = path.join(cwd(), 'src', 'app'); const projectWithAppPath = path.join(cwd(), 'app'); - const checkMiddlewareLocation = ( + const checkProxyLocation = ( basePath: string, to: 'src/' | '', from: 'src/app/' | 'app/' | '', ): string | undefined => { for (const fileExtension of fileExtensions) { - if (existsSync(path.join(basePath, `middleware.${fileExtension}`))) { + if (existsSync(path.join(basePath, `proxy.${fileExtension}`))) { return suggestionMessage(fileExtension, to, from); } } @@ -40,16 +40,14 @@ function suggestMiddlewareLocation() { }; if (existsSync(projectWithAppSrcPath)) { - return ( - checkMiddlewareLocation(projectWithAppSrcPath, 'src/', 'src/app/') || checkMiddlewareLocation(cwd(), 'src/', '') - ); + return checkProxyLocation(projectWithAppSrcPath, 'src/', 'src/app/') || checkProxyLocation(cwd(), 'src/', ''); } if (existsSync(projectWithAppPath)) { - return checkMiddlewareLocation(projectWithAppPath, '', 'app/'); + return checkProxyLocation(projectWithAppPath, '', 'app/'); } return undefined; } -export { suggestMiddlewareLocation, hasSrcAppDir }; +export { suggestProxyLocation, hasSrcAppDir };