← Files WorkOSARCHIVED FILE
references/workos-authkit-tanstack-start.md
9 KB · Oct 2, 2026 · 00:06 UTC
# 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://raw.githubusercontent.com/workos/authkit-tanstack-start/main/README.md`
From README, extract:
1. Package name: `@workos/authkit-tanstack-react-start`
2. Use that exact name for all imports
**README overrides this skill if conflict.**
## Pre-Flight Checklist
- [ ] README fetched and package name extracted
- [ ] `@tanstack/start` or `@tanstack/react-start` in package.json
- [ ] Identify directory structure: `src/` (modern) or `app/` (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:**
```bash
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.**
**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`.**
### If `start.ts` already exists
Read the existing file first. Add `authkitMiddleware` to the existing `requestMiddleware` array (or create the array if missing). Preserve the existing export style. Do not rewrite the file from scratch.
### If `start.ts` does not exist
Create `src/start.ts` (or `app/start.ts` for legacy) using `createStart`:
```typescript
import { createStart } from '@tanstack/react-start';
import { authkitMiddleware } from '@workos/authkit-tanstack-react-start';
export const startInstance = createStart(() => ({
requestMiddleware: [authkitMiddleware()],
}));
```
**Two things matter here:**
1. **Named export `startInstance`** — the build plugin generates `import type { startInstance }` from this file. A `default` export will cause a build error.
2. **`createStart` takes a function** returning the options object, not the options directly. `createStart({ ... })` will fail.
**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`.**
## 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`
```typescript
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:
```typescript
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
```typescript
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:**
```typescript
// src/routes/__root.tsx
import { AuthKitProvider } from '@workos/authkit-tanstack-react-start/client';
function RootComponent() {
return (
<AuthKitProvider>
<Outlet />
</AuthKitProvider>
);
}
```
**2. Use hooks in components:**
```typescript
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.
## Finalize (REQUIRED before declaring success)
After creating/editing all files, run these steps in order. Skipping them is the most common cause of build failures.
### 1. Regenerate the route tree
Adding new route files (callback, signout, etc.) makes the existing `routeTree.gen.ts` stale. The build will fail with type errors about missing routes until it is regenerated.
```bash
pnpm build 2>/dev/null || npx tsr generate
```
The build itself triggers route tree regeneration. If it fails for other reasons, use `tsr generate` directly.
### 2. Ensure Vite type declarations exist
TanStack Start projects import CSS with `import styles from './styles.css?url'`. Without Vite's type declarations, TypeScript will error on these imports. Check if `src/vite-env.d.ts` (or `app/vite-env.d.ts`) exists — if not, create it now (before attempting the build):
```typescript
/// <reference types="vite/client" />
```
### 3. Verify the build
```bash
pnpm build
```
Do not skip this step. If the build fails, fix the errors before finishing. Common causes:
- Stale route tree → re-run step 1
- Missing Vite types → re-run step 2
- Wrong import paths → check package name is `@workos/authkit-tanstack-react-start`
## Verification Checklist (ALL MUST PASS)
Run these commands to confirm integration. **Do not mark complete until all pass:**
```bash
# 1. Check authkitMiddleware is configured
grep -r "authkitMiddleware" src/ app/ 2>/dev/null || echo "FAIL: Middleware not configured"
# 2. Check callback route exists
find src/routes app/routes -name "*callback*" 2>/dev/null
# 3. Check environment variables
grep -c "WORKOS_" .env 2>/dev/null || echo "FAIL: No env vars found"
# 4. Build succeeds
pnpm build
```
**If check #1 fails:** authkitMiddleware must be in src/start.ts (or app/start.ts for legacy) requestMiddleware array. Auth will fail silently without it.
## 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` → file `src/routes/api.auth.callback.tsx` (flat) or `app/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 middleware
- `handleCallbackRoute()` - OAuth callback handler
- `getAuth()` - Get current session
- `signOut()` - Sign out user
- `getSignInUrl()` / `getSignUpUrl()` - Auth URLs
- `switchToOrganization()` - Change org context
**Client (`/client` subpath):**
- `AuthKitProvider` - Context provider
- `useAuth()` - Auth state hook
- `useAccessToken()` - Token management
SHA-256: eaaf651927bb67f29ebcc0233ce49f4316353f7493ac29cca9ac300f73af141d