clerk-sdk-patterns

Common Clerk SDK patterns and best practices. Use when implementing authentication flows, accessing user data, or integrating Clerk SDK methods in your application. Trigger with phrases like "clerk SDK", "clerk patterns", "clerk best practices", "clerk API usage". allowed-tools: Read, Write, Edit, Grep version: 1.0.0 license: MIT author: Jeremy Longshore <jeremy@intentsolutions.io>

Allowed Tools

No tools specified

Provided by Plugin

clerk-pack

Claude Code skill pack for Clerk authentication (24 skills)

saas packs v1.0.0
View Plugin

Installation

This skill is included in the clerk-pack plugin:

/plugin install clerk-pack@claude-code-plugins-plus

Click to copy

Instructions

# Clerk SDK Patterns ## Overview Learn common patterns and best practices for using the Clerk SDK effectively. ## Prerequisites - Clerk SDK installed and configured - Basic understanding of React/Next.js - ClerkProvider wrapping application ## Instructions ### Pattern 1: Server-Side Authentication ```typescript // app/api/protected/route.ts import { auth, currentUser } from '@clerk/nextjs/server' export async function GET() { // Quick auth check const { userId, sessionId, orgId } = await auth() if (!userId) { return Response.json({ error: 'Unauthorized' }, { status: 401 }) } // Full user data when needed const user = await currentUser() return Response.json({ userId, sessionId, orgId, email: user?.primaryEmailAddress?.emailAddress }) } ``` ### Pattern 2: Client-Side Hooks ```typescript 'use client' import { useUser, useAuth, useClerk, useSession } from '@clerk/nextjs' export function AuthenticatedComponent() { // User data and loading state const { user, isLoaded, isSignedIn } = useUser() // Auth utilities const { userId, getToken, signOut } = useAuth() // Full Clerk instance const clerk = useClerk() // Session info const { session } = useSession() // Get JWT token for API calls const callExternalAPI = async () => { const token = await getToken({ template: 'supabase' }) // or custom template const res = await fetch('https://api.example.com', { headers: { Authorization: `Bearer ${token}` } }) } if (!isLoaded) return
Loading...
if (!isSignedIn) return
Please sign in
return
Welcome, {user.firstName}
} ``` ### Pattern 3: Protected Routes with Middleware ```typescript // middleware.ts import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server' const isPublicRoute = createRouteMatcher([ '/', '/sign-in(.*)', '/sign-up(.*)', '/api/webhooks(.*)' ]) const isProtectedRoute = createRouteMatcher([ '/dashboard(.*)', '/api/protected(.*)' ]) export default clerkMiddleware(async (auth, request) => { if (isProtectedRoute(request)) { await auth.protect() } }) export const config = { matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'] } ``` ### Pattern 4: Organization-Aware Queries ```typescript import { auth } from '@clerk/nextjs/server' export async function GET() { const { userId, orgId, orgRole } = await auth() // Check organization membership if (!orgId) { return Response.json({ error: 'No organization selected' }, { status: 400 }) } // Check role-based access if (orgRole !== 'org:admin') { return Response.json({ error: 'Admin access required' }, { status: 403 }) } // Query with organization scope const data = await db.query.resources.findMany({ where: eq(resources.organizationId, orgId) }) return Response.json(data) } ``` ### Pattern 5: Custom JWT Templates ```typescript // Use custom JWT claims for external services const { getToken } = useAuth() // Standard Clerk token const clerkToken = await getToken() // Custom template for Supabase const supabaseToken = await getToken({ template: 'supabase' }) // Custom template for Hasura const hasuraToken = await getToken({ template: 'hasura' }) ``` ## Output - Server and client authentication patterns - Protected route middleware - Organization-aware queries - Custom JWT tokens for integrations ## Error Handling | Error | Cause | Solution | |-------|-------|----------| | auth() returns null | Not in server context | Use in Server Components or API routes | | useUser() not updating | Component not re-rendering | Check ClerkProvider placement | | getToken() fails | Template not configured | Configure JWT template in dashboard | | orgId is null | No organization selected | Prompt user to select organization | ## Examples ### Complete Protected Page Pattern ```typescript // app/dashboard/page.tsx import { auth, currentUser } from '@clerk/nextjs/server' import { redirect } from 'next/navigation' export default async function DashboardPage() { const { userId } = await auth() if (!userId) { redirect('/sign-in') } const user = await currentUser() return (

Dashboard

) } ``` ### Typed User Metadata ```typescript // types/clerk.d.ts interface UserPublicMetadata { tier: 'free' | 'pro' | 'enterprise' onboarded: boolean } interface UserPrivateMetadata { stripeCustomerId?: string } // Usage const user = await currentUser() const tier = user?.publicMetadata?.tier ?? 'free' ``` ## Resources - [Clerk SDK Reference](https://clerk.com/docs/references/nextjs/overview) - [Authentication Patterns](https://clerk.com/docs/references/nextjs/auth) - [JWT Templates](https://clerk.com/docs/backend-requests/making/jwt-templates) ## Next Steps Proceed to `clerk-core-workflow-a` for user sign-up and sign-in flows.

Skill file: plugins/saas-packs/clerk-pack/skills/clerk-sdk-patterns/SKILL.md