clerk-react-patterns — Claude Code skill: what it does & setup
Provides authentication patterns for React single-page apps using @clerk/react in Vite and CRA. It helps implement route guards, session hooks, and custom forms.
npx skills add clerk/skills --skill clerk-react-patterns -a claude-codeWhat clerk-react-patterns does
The skill provides patterns for integrating @clerk/react into client-side single-page applications. It details wrapping the root component in ClerkProvider, configuring VITE_CLERK_PUBLISHABLE_KEY, and fetching session JWTs via getToken() for backend calls.
Inside, you get reference implementations for useAuth, useUser, and useClerk, along with custom login flows and route protection using React Router v6 or v7. The library runs strictly in the browser, meaning there is no server-side auth() helper available.
Because auth state resolves asynchronously, code must verify isLoaded before reading isSignedIn to avoid undefined checks. If your app relies on Next.js or TanStack Start, this skill is the wrong choice — Clerk maintains separate skill packages for those frameworks.
What it helps with
- protect routes in React Router v6 and v7
- configure ClerkProvider in Vite and Create React App
- retrieve JWT bearer tokens for API requests using useAuth
- build custom sign-in and sign-up flows with Clerk hooks
Example prompts for the agent
- Set up ClerkProvider for my Vite app and protect the /dashboard route
- Show how to safely check auth state with useAuth before calling an API
- Create a custom sign-in form using the useSignIn hook
How to install clerk-react-patterns
1Skills CLI (Vercel)
npx skills add clerk/skills --skill clerk-react-patterns -a claude-code2Manually: put the files in place
~/.claude/skills/clerk-react-patterns/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/clerk-react-patterns/
1Skills CLI (Vercel)
npx skills add clerk/skills --skill clerk-react-patterns -a codex2Manually: put the files in place
.agents/skills/clerk-react-patterns/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add clerk/skills --skill clerk-react-patterns -a cursor2Manually: put the files in place
.cursor/skills/clerk-react-patterns/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install clerk/skills clerk-react-patterns2Manually: put the files in place
.github/skills/clerk-react-patterns/SKILL.md1Skills CLI (Vercel)
npx skills add clerk/skills --skill clerk-react-patterns -a gemini-cli2Platform CLI
gemini skills install https://github.com/clerk/skills --path skills/clerk-react-patternsManually: put the files in place
.devin/skills/clerk-react-patterns/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add clerk/skills --skill clerk-react-patterns -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about clerk-react-patterns
How to install clerk-react-patterns in Claude Code?
Run npx skills add clerk/skills --skill clerk-react-patterns -a claude-code in your terminal.
What does clerk-react-patterns do?
It teaches AI assistants how to structure client-side authentication with @clerk/react. It includes patterns for provider setup, React Router guards, and token retrieval.
Can I use this skill with Next.js?
No, this skill is specifically designed for client-only SPAs. For Next.js projects, use clerk-nextjs-patterns instead.
Source text
SKILL.md · MIT
---
name: clerk-react-patterns
description: 'React SPA auth patterns with @clerk/react for Vite/CRA - ClerkProvider
setup, useAuth/useUser/useClerk hooks, React Router protected routes, custom sign-in
flows. Triggers on: Vite Clerk setup, React Router auth, useAuth hook, protected
route, custom sign-in form React.'
license: MIT
allowed-tools: WebFetch
metadata:
author: clerk
version: 1.0.0
---
# React SPA Patterns
> This skill covers `@clerk/react` for Vite/CRA SPAs. For Next.js use `clerk-nextjs-patterns`. For TanStack Start use `clerk-tanstack-patterns`.
## What Do You Need?
| Task | Reference |
|------|-----------|
| useAuth / useUser / useClerk hooks | references/hooks.md |
| Protected routes with React Router | references/protected-routes.md |
| Custom sign-in / sign-up forms | references/custom-flows.md |
| React Router v6/v7 integration | references/router-integration.md |
## References
| Reference | Description |
|-----------|-------------|
| `references/hooks.md` | useAuth, isLoaded guard |
| `references/protected-routes.md` | ProtectedRoute pattern |
| `references/custom-flows.md` | useSignIn, useSignUp flows |
| `references/router-integration.md` | React Router v6/v7 setup |
## Setup
```
npm install @clerk/react
```
`.env`:
```
VITE_CLERK_PUBLISHABLE_KEY=pk_...
```
`src/main.tsx`:
```tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { ClerkProvider } from '@clerk/react'
import App from './App.tsx'
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
createRoot(document.getElementById('root')!).render(
<StrictMode>
<ClerkProvider publishableKey={PUBLISHABLE_KEY}>
<App />
</ClerkProvider>
</StrictMode>,
)
```
## Mental Model
`@clerk/react` is client-only — there is no server-side `auth()`. All auth state comes from hooks.
- `isLoaded` must be `true` before trusting `isSignedIn` — always guard on `isLoaded`
- `useClerk()` gives access to `signOut`, `openSignIn`, `openUserProfile` and other methods
- `getToken()` from `useAuth()` fetches the session JWT for API calls
## Minimal Pattern
```tsx
import { useAuth } from '@clerk/react'
export function Dashboard() {
const { isLoaded, isSignedIn, userId } = useAuth()
if (!isLoaded) return <div>Loading...</div>
if (!isSignedIn) return <div>Please sign in</div>
return <div>Hello {userId}</div>
}
```
## Protected Route (React Router v6/v7)
```tsx
import { Navigate, Outlet } from 'react-router-dom'
import { useAuth } from '@clerk/react'
export function ProtectedRoute() {
const { isLoaded, isSignedIn } = useAuth()
if (!isLoaded) return <div>Loading...</div>
if (!isSignedIn) return <Navigate to="/sign-in" replace />
return <Outlet />
}
```
```tsx
<Routes>
<Route element={<ProtectedRoute />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Route>
<Route path="/sign-in" element={<SignIn />} />
</Routes>
```
## Token for API Calls
```tsx
import { useAuth } from '@clerk/react'
export function DataFetcher() {
const { getToken } = useAuth()
async function fetchData() {
const token = await getToken()
if (!token) return
const res = await fetch('/api/data', {
headers: { Authorization: `Bearer ${token}` },
})
return res.json()
}
return <button onClick={fetchData}>Load</button>
}
```
## Common Pitfalls
| Symptom | Cause | Fix |
|---------|-------|-----|
| `isSignedIn` is `undefined` | `isLoaded` is still `false` | Always check `isLoaded` first |
| `ClerkProvider` missing | Provider not at root | Wrap `<App>` in `main.tsx` |
| Env var undefined | Wrong Vite prefix | Use `VITE_CLERK_PUBLISHABLE_KEY`, access via `import.meta.env` |
| Token is `null` | User not signed in | Null-check `getToken()` result |
| Sign-in component shows blank | No `publishableKey` on provider | Pass `publishableKey` explicitly |
## See Also
- `clerk-setup` - Initial Clerk install
- `clerk-custom-ui` - Custom flows & appearance
- `clerk-orgs` - B2B organizations
## Docs
[React SDK](https://clerk.com/docs/react/getting-started/quickstart)
© clerk · MIT · clerk/skills