{"id":14586,"plugin_id":"plugin_asdk_app_6a9a3c1cd0108191807da33c4cd319ed","kind":"skill","collection_source":null,"comparison_source":null,"observed_at":"2026-09-30T23:09:49.512Z","digest":"d5dcb8c066b5c03a5de12aca0a15370a4753ad157c3344bb214779eebcbb8f90","against":null,"payload":{"description":"TanStack React Start auth patterns with @clerk/tanstack-react-start - createServerFn, beforeLoad guards, loaders, Vinxi server. Triggers on: TanStack auth, createServerFn clerk, beforeLoad protection, TanStack Start middleware.","included_files":[{"relative_path":"evals/evals.json","size_in_bytes":4553},{"relative_path":"references/loaders.md","size_in_bytes":1793},{"relative_path":"references/router-guards.md","size_in_bytes":2057},{"relative_path":"references/server-functions.md","size_in_bytes":2152},{"relative_path":"references/vinxi-server.md","size_in_bytes":1955},{"relative_path":"templates/tanstack-basic-auth/package.json","size_in_bytes":513},{"relative_path":"templates/tanstack-basic-auth/src/router.tsx","size_in_bytes":488},{"relative_path":"templates/tanstack-basic-auth/src/routes/__root.tsx","size_in_bytes":808},{"relative_path":"templates/tanstack-basic-auth/src/routes/index.tsx","size_in_bytes":496},{"relative_path":"templates/tanstack-basic-auth/src/start.ts","size_in_bytes":237},{"relative_path":"templates/tanstack-basic-auth/tsconfig.json","size_in_bytes":531},{"relative_path":"templates/tanstack-basic-auth/vite.config.ts","size_in_bytes":383}],"name":"clerk-tanstack-patterns","skill_md_contents":"---\nname: clerk-tanstack-patterns\ndescription: 'TanStack React Start auth patterns with @clerk/tanstack-react-start\n  - createServerFn, beforeLoad guards, loaders, Vinxi server. Triggers on: TanStack\n  auth, createServerFn clerk, beforeLoad protection, TanStack Start middleware.'\nlicense: MIT\nallowed-tools: WebFetch\nmetadata:\n  author: clerk\n  version: 1.0.0\n---\n\n# TanStack React Start Patterns\n\n## What Do You Need?\n\n| Task | Reference |\n|------|-----------|\n| Protect routes with beforeLoad | references/router-guards.md |\n| Auth in createServerFn | references/server-functions.md |\n| Pass auth to loaders | references/loaders.md |\n| Configure Vinxi + clerkMiddleware | references/vinxi-server.md |\n\n## References\n\n| Reference | Description |\n|-----------|-------------|\n| `references/router-guards.md` | beforeLoad auth redirect |\n| `references/server-functions.md` | createServerFn with auth() |\n| `references/loaders.md` | Auth context in loaders |\n| `references/vinxi-server.md` | clerkMiddleware() setup |\n\n## Setup\n\n```\nnpm install @clerk/tanstack-react-start\n```\n\n`.env`:\n```\nCLERK_PUBLISHABLE_KEY=pk_...\nCLERK_SECRET_KEY=sk_...\n```\n\n`src/start.ts` (Vinxi entry):\n```typescript\nimport { clerkMiddleware } from '@clerk/tanstack-react-start/server'\nimport { createStart } from '@tanstack/react-start'\n\nexport const startInstance = createStart(() => {\n  return {\n    requestMiddleware: [clerkMiddleware()],\n  }\n})\n```\n\n`src/routes/__root.tsx` — wrap with `<ClerkProvider>`:\n```tsx\nimport { ClerkProvider } from '@clerk/tanstack-react-start'\n\nfunction RootDocument({ children }: { children: React.ReactNode }) {\n  return (\n    <html lang=\"en\">\n      <body>\n        <ClerkProvider>\n          {children}\n        </ClerkProvider>\n      </body>\n    </html>\n  )\n}\n```\n\n## Mental Model\n\nTanStack Start runs on Vinxi. Auth flows through two layers:\n\n1. **Server layer** — `createServerFn` + `auth()` from `@clerk/tanstack-react-start/server`\n2. **Router layer** — `beforeLoad` on route definitions, throws `redirect` for unauthenticated\n\nBoth layers are server-executed. Client hooks (`useAuth`, `useUser`) are React hooks for the browser side.\n\n## Minimal Pattern\n\n```typescript\nimport { createFileRoute, redirect } from '@tanstack/react-router'\nimport { createServerFn } from '@tanstack/react-start'\nimport { auth } from '@clerk/tanstack-react-start/server'\n\nconst authStateFn = createServerFn().handler(async () => {\n  const { isAuthenticated, userId } = await auth()\n  if (!isAuthenticated) {\n    throw redirect({ to: '/sign-in' })\n  }\n  return { userId }\n})\n\nexport const Route = createFileRoute('/dashboard')({\n  beforeLoad: async () => await authStateFn(),\n})\n```\n\n## Common Pitfalls\n\n| Symptom | Cause | Fix |\n|---------|-------|-----|\n| `auth()` returns empty | Missing `clerkMiddleware` in start.ts | Add to `requestMiddleware` array |\n| `redirect` not thrown | Using `return` instead of `throw` | `throw redirect(...)` in TanStack |\n| Wrong import for `auth` | Mixing client/server imports | Server: `@clerk/tanstack-react-start/server` |\n| Loader context missing userId | Not passing from beforeLoad | Return from beforeLoad, access via `context` |\n| `ClerkProvider` missing | Forgot root wrapping | Add to `__root.tsx` shell component |\n\n## See Also\n\n- `clerk-setup` - Initial Clerk install\n- `clerk-custom-ui` - Custom flows & appearance\n- `clerk-orgs` - B2B organizations\n\n## Docs\n\n[TanStack React Start SDK](https://clerk.com/docs/tanstack-react-start/getting-started/quickstart)\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}