Frameworks
Skill 14 of 22
React SPA auth patterns with @clerk/react for Vite/CRA - ClerkProvider setup, useAuth/useUser/useClerk hooks, React Router protected routes, custom sign-in flows.
1 minute · 182 words · 11 sections
Install
npx skills add clerk/skills --skill clerk-react-patternsnpx skills add clerk/skills/plugin marketplace add clerk/skillsThe first command installs just this skill, by the name in its SKILL.md; the second installs the whole repository.
This skill covers
@clerk/reactfor Vite/CRA SPAs. For Next.js useclerk-nextjs-patterns. For TanStack Start useclerk-tanstack-patterns.
| 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 |
| 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 |
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>,
)@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 isLoadeduseClerk() gives access to signOut, openSignIn, openUserProfile and other methodsgetToken() from useAuth() fetches the session JWT for API callsimport { 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>
}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>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>
}| 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 |
clerk-setup - Initial Clerk installclerk-custom-ui - Custom flows & appearanceclerk-orgs - B2B organizationsReact 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 verbatim description from this skill’s front matter — the string an agent matches on to decide whether to load it.
WebFetchskills/frameworks/clerk-react-patterns/SKILL.mdmain, last pushed 21 September 2026.SKILL.md, not by matching a directory convention. 5 distinct layouts observed: .agents/skills/*/SKILL.md, skills/core/*/SKILL.md, skills/features/*/SKILL.md, skills/frameworks/*/SKILL.md, skills/mobile/*/SKILL.md.h1 and no skipped levels:.claude-plugin/marketplace.json by Clerk, declaring 4 plugins. It is read for editorial metadata only — never as the skill index, which is always the repository tree./clerk/skills.md, and each skill at its own .md URL.11 files · 15 KB
Everything this skill ships beside its prose. All of it is set here, as subchapters of skill 14.
Documentation the agent loads on demand, rather than up front.
Templates, schemas and fixtures the skill draws on.
Everything else published alongside the skill.