Generated banner for Clerk React Patterns
Generated logo for Clerk React Patterns

Clerk React Patterns

ClerkOfficialCreated by clerk

  • Skill
  • Tool integration
  • Software development
  • MIT
  • Low risk
  • Has scripts

From the author

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.
— the description by clerk

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a comprehensive guide and set of patterns for integrating @clerk/react into React applications built with Vite or Create React App. It focuses on client-side authentication, covering the essential setup of the ClerkProvider, the use of authentication hooks (useAuth, useUser, useClerk), and the implementation of protected routes using React Router. It also includes guidance on building custom sign-in and sign-up flows and handling JWT tokens for secure API communication.

What it does

  • Provides setup instructions for ClerkProvider in React SPAs.
  • Demonstrates how to use authentication hooks to manage user state and sessions.
  • Offers patterns for creating protected routes with React Router v6/v7.
  • Explains how to implement custom sign-in and sign-up forms.
  • Shows how to retrieve session JWTs for authenticated API requests.
  • Outlines common pitfalls and troubleshooting steps for Clerk integration.

When to use it

  • When adding authentication to a new React SPA using Vite or CRA.
  • When you need to protect specific routes in a React application.
  • When building custom authentication UI components instead of using pre-built Clerk components.
  • When you need to authenticate API requests from a React frontend to a backend service.

Advantages

  • Provides clear, standardized patterns for common authentication tasks.
  • Includes essential safety checks like the isLoaded guard to prevent state errors.
  • Offers modular examples for hooks, routing, and custom flows.
  • Addresses specific integration challenges like environment variable configuration.

Usage examples

“How do I protect a route in my React Router application using Clerk?”
The skill provides a ProtectedRoute component pattern that uses the useAuth hook to check authentication status and redirect unauthenticated users to the sign-in page.
“How can I fetch a token to use in an API call header?”
The skill demonstrates using the getToken method from the useAuth hook to retrieve a session JWT for inclusion in the Authorization header of fetch requests.
“What is the correct way to build a custom sign-in form?”
The skill provides a code example using the useSignIn hook, showing how to handle form submission, session creation, and error management.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/clerk/clerk-react-patterns/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip clerk-react-patterns.zip -d .agents/skills

Documentation by clerk

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?

TaskReference
useAuth / useUser / useClerk hooksreferences/hooks.md
Protected routes with React Routerreferences/protected-routes.md
Custom sign-in / sign-up formsreferences/custom-flows.md
React Router v6/v7 integrationreferences/router-integration.md

References

ReferenceDescription
references/hooks.mduseAuth, isLoaded guard
references/protected-routes.mdProtectedRoute pattern
references/custom-flows.mduseSignIn, useSignUp flows
references/router-integration.mdReact Router v6/v7 setup

Setup

npm install @clerk/react

.env:

VITE_CLERK_PUBLISHABLE_KEY=pk_...

src/main.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

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)

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 />
}
<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

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

SymptomCauseFix
isSignedIn is undefinedisLoaded is still falseAlways check isLoaded first
ClerkProvider missingProvider not at rootWrap <App> in main.tsx
Env var undefinedWrong Vite prefixUse VITE_CLERK_PUBLISHABLE_KEY, access via import.meta.env
Token is nullUser not signed inNull-check getToken() result
Sign-in component shows blankNo publishableKey on providerPass publishableKey explicitly

See Also

  • clerk-setup - Initial Clerk install

  • clerk-custom-ui - Custom flows & appearance

  • clerk-orgs - B2B organizations

Docs

React SDK

Files

evals/evals.json

{
  "skill_name": "clerk-react-patterns",
  "evals": [
    {
      "id": 1,
      "prompt": "i created a new vite react app and want to add clerk authentication. show me how to set up ClerkProvider and add sign-in and sign-out buttons to my app.",
      "expected_output": "Wraps app in ClerkProvider in main.tsx with publishableKey from VITE_CLERK_PUBLISHABLE_KEY, adds Show/SignInButton/UserButton to App.tsx",
      "scaffold": "react-basic-auth",
      "expectations": [
        "Adds ClerkProvider to src/main.tsx wrapping the App component",
        "Reads publishableKey from import.meta.env.VITE_CLERK_PUBLISHABLE_KEY",
        "Uses Show when='signed-in' and Show when='signed-out' for conditional rendering",
        "Adds UserButton for signed-in state and SignInButton for signed-out",
        ".env file uses VITE_ prefix not NEXT_PUBLIC_"
      ]
    },
    {
      "id": 2,
      "prompt": "i have a react spa with react router v6. i need to protect my /dashboard and /settings routes so only authenticated users can access them. unauthorized users should be redirected to /sign-in.",
      "expected_output": "Creates ProtectedRoute component using useAuth with isLoaded and isSignedIn checks, wraps protected routes in React Router",
      "scaffold": "react-basic-auth",
      "expectations": [
        "Creates a ProtectedRoute wrapper component",
        "Uses useAuth() with isLoaded and isSignedIn checks",
        "Shows loading state while isLoaded is false",
        "Redirects to /sign-in using <Navigate replace> when not signed in",
        "Wraps /dashboard and /settings using the ProtectedRoute in the router config"
      ]
    },
    {
      "id": 3,
      "prompt": "i want to build a custom sign-in form with email and password fields instead of using the hosted sign-in page. use clerk's useSignIn hook.",
      "expected_output": "Custom sign-in form using useSignIn() hook with signIn.password() or signIn.create(), then finalize() or setActive()",
      "scaffold": "react-basic-auth",
      "expectations": [
        "Uses useSignIn hook from @clerk/react",
        "Calls signIn.password({ identifier, password }) or signIn.create({ identifier, password }) to authenticate",
        "Checks for success before activating the session (via status check, error check, or conditional after the auth call)",
        "Activates the session using signIn.finalize() or setActive({ session: createdSessionId })",
        "Catches and displays error messages from the sign-in response"
      ]
    },
    {
      "id": 4,
      "prompt": "i want a user profile page that shows the signed-in user's name, email address, and profile picture. use clerk hooks to get this data.",
      "expected_output": "Profile page using useUser() hook accessing user.firstName, user.emailAddresses[0], user.imageUrl",
      "scaffold": "react-basic-auth",
      "expectations": [
        "Uses useUser() hook from @clerk/react",
        "Guards on isLoaded before rendering user data",
        "Accesses user.firstName and user.lastName for name",
        "Accesses user.emailAddresses[0].emailAddress for email",
        "Displays user.imageUrl in an img element"
      ]
    },
    {
      "id": 5,
      "prompt": "i need to add an organization switcher to my react spa so users can switch between their orgs. how do i render the switcher and read the active org id?",
      "expected_output": "Renders OrganizationSwitcher from @clerk/react and reads orgId from useAuth()",
      "scaffold": "react-basic-auth",
      "expectations": [
        "Imports and renders <OrganizationSwitcher /> from @clerk/react",
        "Uses orgId from useAuth() to get the active organization ID",
        "Handles the case where orgId is null (no org selected)",
        "Places the switcher in a visible location (nav, header, or sidebar)",
        "Imports from @clerk/react not @clerk/nextjs"
      ]
    },
    {
      "id": 6,
      "prompt": "my react app needs to call a protected backend API. how do i get the clerk session token to include in the Authorization header?",
      "expected_output": "Uses getToken() from useAuth() and includes the token as Bearer in the Authorization header",
      "scaffold": "react-basic-auth",
      "expectations": [
        "Uses getToken() from useAuth() hook",
        "Awaits the getToken() call (it returns a Promise)",
        "Null-checks the token before using it",
        "Sets Authorization: Bearer <token> header on the fetch request",
        "Shows a pattern for reuse (custom hook or utility function)"
      ]
    }
  ]
}

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Declares allowed tools, Needs Node.js

Security

What our scanner noticed· Low risk

  • Scripts that your agent may run

This skill includes scripts that your agent may run. Read them before you use it.

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
clerk
Publisher
Clerk (Official)
Source
clerk/skills · skills/clerk-react-patterns · commit c5d2c0d
Licence
MIT License (redistribution allowed)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by clerk or Clerk.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download clerk-react-patterns.zip