Skip to main content
skill CX Codex

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.

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

What 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-code

2Manually: put the files in place

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

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

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

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