workos-authkit-tanstack-start
WorkOS AuthKit for TanStack Start
Decision Tree
1. Fetch README (BLOCKING)
├── Extract package name from install command
└── README is source of truth for ALL code patterns
2. Detect directory structure
├── src/ (TanStack Start v1.132+, default)
└── app/ (legacy vinxi-based projects)
3. Follow README install/setup exactly
└── Do not invent commands or patterns
Fetch SDK Documentation (BLOCKING)
STOP - Do not proceed until complete.
WebFetch: https://github.com/workos/authkit-tanstack-start/blob/main/README.md
From README, extract:
- Package name:
@workos/authkit-tanstack-react-start - Use that exact name for all imports
README overrides this skill if conflict.
Pre-Flight Checklist
- README fetched and package name extracted
-
@tanstack/startor@tanstack/react-startin package.json - Identify directory structure:
src/(modern) orapp/(legacy) - Environment variables set (see below)
Directory Structure Detection
Modern TanStack Start (v1.132+) uses src/:
src/
├── start.ts # Middleware config (CRITICAL)
├── router.tsx # Router setup
├── routes/
│ ├── __root.tsx # Root layout
│ ├── api.auth.callback.tsx # OAuth callback (flat route)
│ └── ...
Legacy (vinxi-based) uses app/:
app/
├── start.ts or router.tsx
├── routes/
│ └── api/auth/callback.tsx # OAuth callback (nested route)
Detection:
ls src/routes 2>/dev/null && echo "Modern (src/)" || echo "Legacy (app/)"
Environment Variables
| Variable | Format | Required |
|---|---|---|
WORKOS_API_KEY |
sk_... |
Yes |
WORKOS_CLIENT_ID |
client_... |
Yes |
WORKOS_REDIRECT_URI |
Full URL | Yes |
WORKOS_COOKIE_PASSWORD |
32+ chars | Yes |
Generate password if missing: openssl rand -base64 32
Default redirect URI: http://localhost:3000/api/auth/callback
Middleware Configuration (CRITICAL)
authkitMiddleware MUST be configured or auth will fail silently.
Create or update src/start.ts (or app/start.ts for legacy):
import { authkitMiddleware } from '@workos/authkit-tanstack-react-start';
export default {
requestMiddleware: [authkitMiddleware()],
};
Alternative pattern with createStart:
import { createStart } from '@tanstack/react-start';
import { authkitMiddleware } from '@workos/authkit-tanstack-react-start';
export default createStart({
requestMiddleware: [authkitMiddleware()],
});
Verification Checklist
-
authkitMiddlewareimported from@workos/authkit-tanstack-react-start - Middleware in
requestMiddlewarearray - File exports the config (default export or named
startInstance)
Verify: grep -r "authkitMiddleware" src/ app/ 2>/dev/null
Callback Route (CRITICAL)
Path must match WORKOS_REDIRECT_URI. For /api/auth/callback:
Modern (flat routes): src/routes/api.auth.callback.tsx
Legacy (nested routes): app/routes/api/auth/callback.tsx
import { createFileRoute } from '@tanstack/react-router';
import { handleCallbackRoute } from '@workos/authkit-tanstack-react-start';
export const Route = createFileRoute('/api/auth/callback')({
server: {
handlers: {
GET: handleCallbackRoute(),
},
},
});
Key points:
- Use
handleCallbackRoute()- do not write custom OAuth logic - Route path string must match the URI path exactly
- This is a server-only route (no component needed)
Protected Routes
Use getAuth() in route loaders to check authentication:
import { createFileRoute, redirect } from '@tanstack/react-router';
import { getAuth, getSignInUrl } from '@workos/authkit-tanstack-react-start';
export const Route = createFileRoute('/dashboard')({
loader: async () => {
const { user } = await getAuth();
if (!user) {
const signInUrl = await getSignInUrl();
throw redirect({ href: signInUrl });
}
return { user };
},
component: Dashboard,
});
Sign Out Route
import { createFileRoute, redirect } from '@tanstack/react-router';
import { signOut } from '@workos/authkit-tanstack-react-start';
export const Route = createFileRoute('/signout')({
loader: async () => {
await signOut();
throw redirect({ href: '/' });
},
});
Client-Side Hooks (Optional)
Only needed if you want reactive auth state in components.
1. Add AuthKitProvider to root:
// src/routes/__root.tsx
import { AuthKitProvider } from '@workos/authkit-tanstack-react-start/client';
function RootComponent() {
return (
<AuthKitProvider>
<Outlet />
</AuthKitProvider>
);
}
2. Use hooks in components:
import { useAuth } from '@workos/authkit-tanstack-react-start/client';
function Profile() {
const { user, isLoading } = useAuth();
// ...
}
Note: Server-side getAuth() is preferred for most use cases.
Error Recovery
"AuthKit middleware is not configured"
Cause: authkitMiddleware() not in start.ts
Fix: Create/update src/start.ts with middleware config
Verify: grep -r "authkitMiddleware" src/
"Module not found" for SDK
Cause: Wrong package name or not installed
Fix: pnpm add @workos/authkit-tanstack-react-start
Verify: ls node_modules/@workos/authkit-tanstack-react-start
Callback 404
Cause: Route file path doesn't match WORKOS_REDIRECT_URI Fix:
- URI
/api/auth/callback→ filesrc/routes/api.auth.callback.tsx(flat) orapp/routes/api/auth/callback.tsx(nested) - Route path string in
createFileRoute()must match exactly
getAuth returns undefined user
Cause: Middleware not configured or not running
Fix: Ensure authkitMiddleware() is in start.ts requestMiddleware array
"Cookie password too short"
Cause: WORKOS_COOKIE_PASSWORD < 32 chars
Fix: openssl rand -base64 32, update .env
Build fails with route type errors
Cause: Route tree not regenerated after adding routes
Fix: pnpm dev to regenerate routeTree.gen.ts
SDK Exports Reference
Server (main export):
authkitMiddleware()- Request middlewarehandleCallbackRoute()- OAuth callback handlergetAuth()- Get current sessionsignOut()- Sign out usergetSignInUrl()/getSignUpUrl()- Auth URLsswitchToOrganization()- Change org context
Client (/client subpath):
AuthKitProvider- Context provideruseAuth()- Auth state hookuseAccessToken()- Token management