From 9ef59f8f260e5c3a970d552940d7aa81535bfb84 Mon Sep 17 00:00:00 2001 From: Nick Nisi Date: Wed, 4 Mar 2026 09:45:57 -0600 Subject: [PATCH 1/2] fix: clarify TanStack Start middleware setup to prevent createRouter confusion The installer agent could confuse TanStack Router's createRouter() with TanStack Start's server middleware config, instructing users to add authkitMiddleware to router.tsx instead of start.ts. Added explicit warning in SKILL.md and improved doctor check remediation with the correct code pattern. --- skills/workos-authkit-tanstack-start/SKILL.md | 2 ++ src/doctor/checks/auth-patterns.spec.ts | 5 +++-- src/doctor/checks/auth-patterns.ts | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/skills/workos-authkit-tanstack-start/SKILL.md b/skills/workos-authkit-tanstack-start/SKILL.md index c83ed2d..36356de 100644 --- a/skills/workos-authkit-tanstack-start/SKILL.md +++ b/skills/workos-authkit-tanstack-start/SKILL.md @@ -86,6 +86,8 @@ Default redirect URI: `http://localhost:3000/api/auth/callback` **authkitMiddleware MUST be configured or auth will fail silently.** +**WARNING: Do NOT add middleware to `createRouter()` in `router.tsx` or `app.tsx`. That is TanStack Router (client-side only). Server middleware belongs in `start.ts` using `requestMiddleware`.** + Create or update `src/start.ts` (or `app/start.ts` for legacy): ```typescript diff --git a/src/doctor/checks/auth-patterns.spec.ts b/src/doctor/checks/auth-patterns.spec.ts index 0226bda..f330457 100644 --- a/src/doctor/checks/auth-patterns.spec.ts +++ b/src/doctor/checks/auth-patterns.spec.ts @@ -514,7 +514,7 @@ describe('checkAuthPatterns', () => { describe('MISSING_AUTHKIT_MIDDLEWARE (TanStack Start)', () => { it('warning when start.ts lacks authkitMiddleware', async () => { - writeFixtureFile(testDir, 'src/start.ts', 'export default defineStart({})'); + writeFixtureFile(testDir, 'src/start.ts', 'export default createStart({})'); const result = await checkAuthPatterns( makeOptions(testDir), makeFramework({ name: 'TanStack Start', expectedCallbackPath: '/auth/callback' }), @@ -529,8 +529,9 @@ describe('checkAuthPatterns', () => { testDir, 'src/start.ts', ` + import { createStart } from "@tanstack/react-start"; import { authkitMiddleware } from "@workos-inc/authkit-tanstack-start"; - export default defineStart({ middleware: [authkitMiddleware()] }); + export default createStart({ requestMiddleware: [authkitMiddleware()] }); `, ); const result = await checkAuthPatterns( diff --git a/src/doctor/checks/auth-patterns.ts b/src/doctor/checks/auth-patterns.ts index 15af4a0..479dec9 100644 --- a/src/doctor/checks/auth-patterns.ts +++ b/src/doctor/checks/auth-patterns.ts @@ -423,7 +423,10 @@ function checkMissingAuthkitMiddleware(ctx: CheckContext): AuthPatternFinding[] severity: 'warning', message: 'start.ts does not reference authkitMiddleware — AuthKit session handling requires it', filePath: relative(ctx.installDir, startFile), - remediation: 'Add authkitMiddleware to your start.ts server middleware configuration.', + remediation: + 'Add authkitMiddleware to requestMiddleware in src/start.ts:\n' + + ' import { authkitMiddleware } from "@workos/authkit-tanstack-react-start";\n' + + ' export default createStart({ requestMiddleware: [authkitMiddleware()] });', }, ]; } From 70eb432a83d0899e955db6cab9d12786372cf401 Mon Sep 17 00:00:00 2001 From: Nick Nisi Date: Wed, 4 Mar 2026 09:48:58 -0600 Subject: [PATCH 2/2] fix: doctor callback route check now searches both flat and nested routes in src/ and app/ Previously only checked flat routes in src/ and nested routes in app/, causing false CALLBACK_ROUTE_MISSING errors for TanStack Start projects using nested routes in src/ (e.g. src/routes/api/auth/callback.tsx). --- src/doctor/checks/auth-patterns.spec.ts | 32 ++++++++++++++++++++++++- src/doctor/checks/auth-patterns.ts | 11 +++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/doctor/checks/auth-patterns.spec.ts b/src/doctor/checks/auth-patterns.spec.ts index f330457..0617360 100644 --- a/src/doctor/checks/auth-patterns.spec.ts +++ b/src/doctor/checks/auth-patterns.spec.ts @@ -368,7 +368,7 @@ describe('checkAuthPatterns', () => { expect(result.findings.find((f) => f.code === 'CALLBACK_ROUTE_MISSING')).toBeUndefined(); }); - it('no finding when callback route exists (TanStack Start flat)', async () => { + it('no finding when callback route exists (TanStack Start flat in src/)', async () => { writeFixtureFile( testDir, 'src/routes/auth.callback.tsx', @@ -382,6 +382,36 @@ describe('checkAuthPatterns', () => { ); expect(result.findings.find((f) => f.code === 'CALLBACK_ROUTE_MISSING')).toBeUndefined(); }); + + it('no finding when callback route exists (TanStack Start nested in src/)', async () => { + writeFixtureFile( + testDir, + 'src/routes/api/auth/callback.tsx', + 'export const Route = createFileRoute("/api/auth/callback")', + ); + const result = await checkAuthPatterns( + makeOptions(testDir), + makeFramework({ name: 'TanStack Start', version: '1.0.0', expectedCallbackPath: '/api/auth/callback' }), + makeEnv(), + makeSdk({ name: '@workos-inc/authkit-tanstack-start' }), + ); + expect(result.findings.find((f) => f.code === 'CALLBACK_ROUTE_MISSING')).toBeUndefined(); + }); + + it('no finding when callback route exists (TanStack Start flat in app/)', async () => { + writeFixtureFile( + testDir, + 'app/routes/api.auth.callback.tsx', + 'export const Route = createFileRoute("/api/auth/callback")', + ); + const result = await checkAuthPatterns( + makeOptions(testDir), + makeFramework({ name: 'TanStack Start', version: '1.0.0', expectedCallbackPath: '/api/auth/callback' }), + makeEnv(), + makeSdk({ name: '@workos-inc/authkit-tanstack-start' }), + ); + expect(result.findings.find((f) => f.code === 'CALLBACK_ROUTE_MISSING')).toBeUndefined(); + }); }); describe('API_KEY_LEAKED_TO_CLIENT', () => { diff --git a/src/doctor/checks/auth-patterns.ts b/src/doctor/checks/auth-patterns.ts index 479dec9..fbfd8f2 100644 --- a/src/doctor/checks/auth-patterns.ts +++ b/src/doctor/checks/auth-patterns.ts @@ -299,13 +299,16 @@ function checkCallbackRouteMissing(ctx: CheckContext): AuthPatternFinding[] { possiblePaths.push(join(ctx.installDir, 'app', 'routes', nested + `.${ext}`)); } } else if (ctx.framework.name === 'TanStack Start') { - // Modern flat: src/routes/api.auth.callback.tsx Legacy nested: app/routes/api/auth/callback.tsx + // Flat: routes/api.auth.callback.tsx Nested: routes/api/auth/callback.tsx + // Both conventions work in both src/ and app/ directories const segments = callbackPath.replace(/^\//, '').split('/'); const flat = segments.join('.'); const nested = segments.join('/'); - for (const ext of ['tsx', 'jsx', 'ts', 'js']) { - possiblePaths.push(join(ctx.installDir, 'src', 'routes', `${flat}.${ext}`)); - possiblePaths.push(join(ctx.installDir, 'app', 'routes', nested + `.${ext}`)); + for (const prefix of ['src', 'app']) { + for (const ext of ['tsx', 'jsx', 'ts', 'js']) { + possiblePaths.push(join(ctx.installDir, prefix, 'routes', `${flat}.${ext}`)); + possiblePaths.push(join(ctx.installDir, prefix, 'routes', nested + `.${ext}`)); + } } }