بنقرة واحدة
clerk-nextjs-patterns
Advanced Next.js patterns - middleware, Server Actions, caching with Clerk.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Advanced Next.js patterns - middleware, Server Actions, caching with Clerk.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Designs complex generic types, refactors `any` types to strict alternatives, creates type guards and utility types, and resolves TypeScript compiler errors. Use when the user asks about TypeScript (TS) types, generics, type inference, type guards, removing `any` types, strict typing, type errors, `infer`, `extends`, conditional types, mapped types, template literal types, branded/opaque types, or utility types like `Partial`, `Record`, `ReturnType`, and `Awaited`.
Clerk Backend REST API explorer and executor. Browse tags, inspect endpoint schemas, and execute authenticated requests. Use when listing users, managing organizations, or calling any Clerk API endpoint.
Clerk authentication router. Use when user asks about adding authentication, setting up Clerk, custom sign-in flows, Swift or native iOS auth, native Android auth, Next.js patterns, React patterns, Vue patterns, Nuxt patterns, Astro patterns, TanStack Start patterns, Expo patterns, React Router patterns, Chrome Extension patterns, organizations, syncing users, or testing. Automatically routes to the specific skill based on their task.
Clerk webhooks for real-time events and data syncing. Always output complete, copy-paste-ready webhook handlers with verifyWebhook(req) verification. Listen for user creation, updates, deletion, and organization events. Build event-driven features like database sync, notifications, integrations.
| name | clerk-nextjs-patterns |
| description | Advanced Next.js patterns - middleware, Server Actions, caching with Clerk. |
| license | MIT |
| allowed-tools | WebFetch |
| metadata | {"author":"clerk","version":"2.2.0"} |
Version: Check
package.jsonfor the SDK version — seeclerkskill for the version table. Core 2 differences are noted inline with> **Core 2 ONLY (skip if current SDK):**callouts.
For basic setup, see clerk-setup skill.
| Task | Reference |
|---|---|
Server vs client auth (auth() vs hooks) | references/server-vs-client.md |
| Configure middleware (public-first vs protected-first) | references/middleware-strategies.md |
| Protect Server Actions | references/server-actions.md |
| API route auth (401 vs 403) | references/api-routes.md |
| Cache auth data (user-scoped caching) | references/caching-auth.md |
| Reference | Description |
|---|---|
references/server-vs-client.md | await auth() vs hooks |
references/middleware-strategies.md | Public-first vs protected-first, proxy.ts (Next.js <=15: middleware.ts) |
references/server-actions.md | Protect mutations |
references/api-routes.md | 401 vs 403 |
references/caching-auth.md | User-scoped caching |
Server vs Client = different auth APIs:
await auth() from @clerk/nextjs/server (async!)useAuth() hook from @clerk/nextjs (sync)Never mix them. Server Components use server imports, Client Components use hooks.
Key properties from auth():
isAuthenticated — boolean, replaces the !!userId patternsessionStatus — 'active' | 'pending', for detecting incomplete session tasksuserId, orgId, orgSlug, has(), protect() — unchangedCore 2 ONLY (skip if current SDK):
isAuthenticatedandsessionStatusare not available. Check!!userIdinstead.
// Server Component
import { auth } from '@clerk/nextjs/server'
export default async function Page() {
const { isAuthenticated, userId } = await auth() // MUST await!
if (!isAuthenticated) return <p>Not signed in</p>
return <p>Hello {userId}</p>
}
Core 2 ONLY (skip if current SDK):
isAuthenticatedis not available. Useif (!userId)instead.
<Show>For client-side conditional rendering based on auth state:
import { Show } from '@clerk/nextjs';
<Show when="signed-in" fallback={<p>Please sign in</p>}>
<Dashboard />
</Show>;
Core 2 ONLY (skip if current SDK): Use
<SignedIn>and<SignedOut>components instead of<Show>. Seeclerk-custom-uiskill,core-3/show-component.mdfor the full migration table.
| Symptom | Cause | Fix |
| -------------------------------------- | ------------------------- | ---------------------------------------- | ------------------------------------------------------ |
| undefined userId in Server Component | Missing await | await auth() not auth() |
| Auth not working on API routes | Missing matcher | Add '/(api | trpc)(.\*)'toproxy.ts(Next.js <=15:middleware.ts) |
| Cache returns wrong user's data | Missing userId in key | Include userId in unstable_cache key |
| Mutations bypass auth | Unprotected Server Action | Check auth() at start of action |
| Wrong HTTP error code | Confused 401/403 | 401 = not signed in, 403 = no permission |
Pass a custom JWT to third-party services (Hasura, Supabase, etc.) using JWT templates defined in the Clerk dashboard.
Server-side (Server Component or Route Handler):
import { auth } from '@clerk/nextjs/server'
export default async function Page() {
const { getToken } = await auth()
const token = await getToken({ template: 'hasura' })
if (!token) return <p>Not authenticated</p>
const res = await fetch('https://api.example.com/graphql', {
headers: { Authorization: `Bearer ${token}` },
})
const data = await res.json()
return <pre>{JSON.stringify(data)}</pre>
}
Client-side (Client Component):
'use client'
import { useAuth } from '@clerk/nextjs'
export function DataFetcher() {
const { getToken } = useAuth()
async function fetchData() {
const token = await getToken({ template: 'supabase' })
if (!token) return
const res = await fetch('https://api.example.com/data', {
headers: { Authorization: `Bearer ${token}` },
})
return res.json()
}
return <button onClick={fetchData}>Fetch</button>
}
getToken() returns null when the user is not authenticated — always null-check before use.
Access session metadata in client components:
'use client'
import { useSession } from '@clerk/nextjs'
export function SessionInfo() {
const { session } = useSession()
if (!session) return null
return (
<p>
Session {session.id} — last active: {session.lastActiveAt.toISOString()}
</p>
)
}
For standalone API servers that receive Clerk session tokens from the Authorization header or the __session cookie (same-origin).
Using @clerk/backend verifyToken (recommended):
import { verifyToken } from '@clerk/backend';
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) return res.status(401).json({ error: 'No token' });
try {
const claims = await verifyToken(token, {
jwtKey: process.env.CLERK_JWT_KEY,
});
// claims.sub = userId
} catch {
return res.status(401).json({ error: 'Invalid token' });
}
Using jsonwebtoken (when you can't use @clerk/backend):
import jwt from 'jsonwebtoken';
const publicKey = process.env.CLERK_PEM_PUBLIC_KEY!.replace(/\\n/g, '\n');
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) return res.status(401).json({ error: 'No token' });
try {
const claims = jwt.verify(token, publicKey, {
algorithms: ['RS256'],
}) as jwt.JwtPayload;
// Manually check exp and nbf (jsonwebtoken does this automatically, but verify azp if needed)
// claims.sub = userId
} catch {
return res.status(401).json({ error: 'Invalid or expired token' });
}
Token sources:
__session cookie (Clerk sets this automatically)Authorization: Bearer <token> headerCRITICAL: Always check
expandnbfclaims.verifyTokenfrom@clerk/backendhandles this automatically; with rawjsonwebtoken, setignoreExpiration: false(default) and ensureclockToleranceis minimal.
clerk-setupclerk-orgs