Skip to main content
skill CX Codex

clerk-tanstack-patterns — Claude Code skill: Clerk auth in TanStack

Walks your agent through Clerk auth in TanStack React Start: route guards, createServerFn, loaders and request middleware.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add clerk/skills --skill clerk-tanstack-patterns -a claude-code
Open on GitHub

What clerk-tanstack-patterns does

The skill splits Clerk auth in TanStack React Start across four reference files. references/router-guards.md covers beforeLoad, references/server-functions.md covers createServerFn with auth(), references/loaders.md covers auth context in loaders, and references/server-setup.md covers the Vite plugin and request middleware. The agent pulls the file that matches the task at hand.

Auth runs in two layers, both server-executed. On the server side, createServerFn calls auth() from @clerk/tanstack-react-start/server. On the router side, beforeLoad sits in the route definition and throws redirect for unauthenticated visitors. Browser-side hooks like useAuth and useUser stay separate from both.

You need the @clerk/tanstack-react-start package plus VITE_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY in .env. In src/start.ts, clerkMiddleware() goes into requestMiddleware after the CSRF middleware — register it first and auth() fails with a middleware configuration error. The root shell also needs <ClerkProvider>. One more trap: return redirect(...) does nothing in TanStack, only throw redirect(...) works.

What it helps with

  • block unauthenticated access to /dashboard with beforeLoad
  • read userId inside a createServerFn handler
  • pass auth state from beforeLoad into a loader
  • wire clerkMiddleware next to CSRF in src/start.ts
  • debug the auth() middleware configuration error

Example prompts for the agent

  • Protect the /dashboard route with beforeLoad and Clerk, redirect unauthenticated users to /sign-in
  • Add an auth() check inside this createServerFn and return the userId
  • How do I pass userId from beforeLoad into a TanStack Start loader?

How to install clerk-tanstack-patterns

1Skills CLI (Vercel)

npx skills add clerk/skills --skill clerk-tanstack-patterns -a claude-code

2Manually: put the files in place

~/.claude/skills/clerk-tanstack-patterns/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/clerk-tanstack-patterns/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about clerk-tanstack-patterns

How do I install clerk-tanstack-patterns in Claude?

Run npx skills add clerk/skills --skill clerk-tanstack-patterns -a claude-code. The skill lands at ~/.claude/skills/clerk-tanstack-patterns/SKILL.md.

What does clerk-tanstack-patterns do?

It hands your agent working Clerk auth patterns for TanStack React Start: route protection, createServerFn, loaders, and Vite plus request middleware setup.

What do I need before using the skill?

The @clerk/tanstack-react-start package and VITE_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY in .env. Without clerkMiddleware in src/start.ts, auth() throws.

Source text

SKILL.md · MIT
---
name: clerk-tanstack-patterns
description: 'TanStack React Start auth patterns with @clerk/tanstack-react-start
  - createServerFn, beforeLoad guards, loaders, Vite plugin, server middleware. Triggers on: TanStack
  auth, createServerFn clerk, beforeLoad protection, TanStack Start middleware.'
license: MIT
allowed-tools: WebFetch
metadata:
  author: clerk
  version: 1.0.0
---

# TanStack React Start Patterns

## What Do You Need?

| Task | Reference |
|------|-----------|
| Protect routes with beforeLoad | references/router-guards.md |
| Auth in createServerFn | references/server-functions.md |
| Pass auth to loaders | references/loaders.md |
| Configure Vite + Clerk middleware | references/server-setup.md |

## References

| Reference | Description |
|-----------|-------------|
| `references/router-guards.md` | beforeLoad auth redirect |
| `references/server-functions.md` | createServerFn with auth() |
| `references/loaders.md` | Auth context in loaders |
| `references/server-setup.md` | Vite and request middleware setup |

## Setup

```
npm install @clerk/tanstack-react-start
```

`.env`:
```
VITE_CLERK_PUBLISHABLE_KEY=pk_...
CLERK_SECRET_KEY=sk_...
```

`src/start.ts` (request middleware):
```typescript
import { clerkMiddleware } from '@clerk/tanstack-react-start/server'
import { createCsrfMiddleware, createStart } from '@tanstack/react-start'

const csrfMiddleware = createCsrfMiddleware({
  filter: (ctx) => ctx.handlerType === 'serverFn',
})

export const startInstance = createStart(() => {
  return {
    requestMiddleware: [csrfMiddleware, clerkMiddleware()],
  }
})
```

`src/routes/__root.tsx` — wrap with `<ClerkProvider>`:
```tsx
import { ClerkProvider } from '@clerk/tanstack-react-start'

function RootDocument({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <ClerkProvider>
          {children}
        </ClerkProvider>
      </body>
    </html>
  )
}
```

## Mental Model

TanStack Start uses the `tanstackStart()` Vite plugin. Register CSRF protection before Clerk request middleware in `src/start.ts`; auth then flows through two layers:

1. **Server layer** — `createServerFn` + `auth()` from `@clerk/tanstack-react-start/server`
2. **Router layer** — `beforeLoad` on route definitions, throws `redirect` for unauthenticated

Both layers are server-executed. Client hooks (`useAuth`, `useUser`) are React hooks for the browser side.

## Minimal Pattern

```typescript
import { createFileRoute, redirect } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/react-start'
import { auth } from '@clerk/tanstack-react-start/server'

const authStateFn = createServerFn().handler(async () => {
  const { isAuthenticated, userId } = await auth()
  if (!isAuthenticated) {
    throw redirect({ to: '/sign-in' })
  }
  return { userId }
})

export const Route = createFileRoute('/dashboard')({
  beforeLoad: async () => await authStateFn(),
})
```

## Common Pitfalls

| Symptom | Cause | Fix |
|---------|-------|-----|
| `auth()` throws "without configuring the middleware" | Missing `clerkMiddleware` in start.ts | Add it after CSRF middleware in `requestMiddleware` |
| `redirect` not thrown | Using `return` instead of `throw` | `throw redirect(...)` in TanStack |
| Wrong import for `auth` | Mixing client/server imports | Server: `@clerk/tanstack-react-start/server` |
| Loader context missing userId | Not passing from beforeLoad | Return from beforeLoad, access via `context` |
| `ClerkProvider` missing | Forgot root wrapping | Add to `__root.tsx` shell component |

## See Also

- `clerk-setup` - Initial Clerk install
- `clerk-custom-ui` - Custom flows & appearance
- `clerk-orgs` - B2B organizations

## Docs

[TanStack React Start SDK](https://clerk.com/docs/tanstack-react-start/getting-started/quickstart)

© clerk · MIT · clerk/skills

Similar skills

Everything for Frontend and UI →

From the same set19

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor