clerk-reference-architecture

Reference architecture patterns for Clerk authentication. Use when designing application architecture, planning auth flows, or implementing enterprise-grade authentication. Trigger with phrases like "clerk architecture", "clerk design", "clerk system design", "clerk integration patterns". 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 Reference Architecture ## Overview Reference architectures for implementing Clerk in various application types. ## Prerequisites - Understanding of web application architecture - Familiarity with authentication patterns - Knowledge of your tech stack ## Architecture 1: Next.js Full-Stack Application ``` +------------------+ +------------------+ +------------------+ | Next.js App | | Clerk Service | | Database | | (App Router) | | | | (Postgres) | +------------------+ +------------------+ +------------------+ | | | | ClerkProvider | | | (wraps all pages) | | v v v +------------------+ +------------------+ +------------------+ | Middleware |<--->| Auth API | | Prisma Client | | (clerkMiddleware)| | (JWT verify) | | | +------------------+ +------------------+ +------------------+ | | | v v v +------------------+ +------------------+ +------------------+ | Protected | | Webhooks |---->| User Sync | | Server Actions | | (user events) | | (user table) | +------------------+ +------------------+ +------------------+ ``` ### Implementation ```typescript // app/layout.tsx import { ClerkProvider } from '@clerk/nextjs' export default function RootLayout({ children }) { return ( {children} ) } // middleware.ts import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server' const isPublicRoute = createRouteMatcher(['/', '/sign-in(.*)', '/sign-up(.*)']) export default clerkMiddleware(async (auth, req) => { if (!isPublicRoute(req)) await auth.protect() }) // lib/db.ts - User sync via webhooks import { prisma } from './prisma' export async function syncUserFromClerk(clerkUser: any) { await prisma.user.upsert({ where: { clerkId: clerkUser.id }, update: { email: clerkUser.email_addresses[0]?.email_address, name: `${clerkUser.first_name} ${clerkUser.last_name}`, imageUrl: clerkUser.image_url }, create: { clerkId: clerkUser.id, email: clerkUser.email_addresses[0]?.email_address, name: `${clerkUser.first_name} ${clerkUser.last_name}`, imageUrl: clerkUser.image_url } }) } ``` ## Architecture 2: Microservices with Shared Auth ``` +------------------+ | API Gateway | | (JWT Verify) | +------------------+ | | Bearer Token v +-------+-------+-------+-------+ | | | | | v v v v v +-----+ +-----+ +-----+ +-----+ +-----+ |User | |Order| |Pay | |Inv | |Notif| |Svc | |Svc | |Svc | |Svc | |Svc | +-----+ +-----+ +-----+ +-----+ +-----+ | | | | | v v v v v +------------------------------------------+ | Shared User Store | | (Synced via Webhooks) | +------------------------------------------+ ``` ### Implementation ```typescript // API Gateway - Verify Clerk JWT // gateway/src/middleware/auth.ts import { createClerkClient } from '@clerk/backend' const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY }) export async function verifyToken(req: Request): Promise { const token = req.headers.get('authorization')?.replace('Bearer ', '') if (!token) return null try { const { sub: userId } = await clerk.verifyToken(token) return { userId } } catch { return null } } // Microservice - Trust gateway-verified user // services/order/src/handlers/create-order.ts export async function createOrder(req: AuthenticatedRequest) { const { userId } = req.auth // Set by gateway return await db.order.create({ data: { userId, items: req.body.items, status: 'pending' } }) } ``` ## Architecture 3: Multi-Tenant SaaS ``` +------------------+ +------------------+ | Tenant A | | Tenant B | | (Org: acme) | | (Org: globex) | +------------------+ +------------------+ | | v v +------------------------------------------+ | Clerk Organizations | | - Member management | | - Role-based permissions | | - SSO per organization | +------------------------------------------+ | v +------------------------------------------+ | Application Layer | | - Organization context in all queries | | - Data isolation by orgId | +------------------------------------------+ | v +------------------------------------------+ | Database (Multi-tenant) | | - All tables have organizationId | | - RLS policies enforce isolation | +------------------------------------------+ ``` ### Implementation ```typescript // middleware.ts - Organization context import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server' export default clerkMiddleware(async (auth, req) => { const { userId, orgId, orgRole } = await auth() if (!userId) { return auth.redirectToSignIn() } // Require organization for app routes if (req.nextUrl.pathname.startsWith('/app') && !orgId) { return Response.redirect(new URL('/select-organization', req.url)) } }) // lib/db-context.ts - Tenant-scoped queries import { auth } from '@clerk/nextjs/server' import { prisma } from './prisma' export async function getTenantPrisma() { const { orgId } = await auth() if (!orgId) { throw new Error('Organization context required') } // Return prisma client with tenant filter return prisma.$extends({ query: { $allOperations({ operation, args, query }) { // Inject orgId into all queries if ('where' in args) { args.where = { ...args.where, organizationId: orgId } } if ('data' in args) { args.data = { ...args.data, organizationId: orgId } } return query(args) } } }) } ``` ## Architecture 4: Mobile + Web with Shared Backend ``` +-------------+ +-------------+ +-------------+ | Web App | | iOS App | | Android App | | (Next.js) | | (Swift) | | (Kotlin) | +-------------+ +-------------+ +-------------+ | | | v v v +------------------------------------------+ | Clerk SDKs | | - @clerk/nextjs | | - clerk-expo (React Native) | | - Native SDKs | +------------------------------------------+ | | | +-------+-------+-------+-------+ | v +------------------------------------------+ | Shared API Backend | | - Verify JWT from any platform | | - Consistent user model | +------------------------------------------+ ``` ### Implementation ```typescript // Backend API - Platform-agnostic auth // api/src/middleware/verify-clerk.ts import { createClerkClient } from '@clerk/backend' const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY }) export async function verifyRequest(req: Request) { const token = req.headers.get('authorization')?.replace('Bearer ', '') if (!token) { throw new Error('No token provided') } // Works with tokens from any Clerk SDK const { sub: userId, metadata } = await clerk.verifyToken(token) return { userId, platform: metadata?.platform || 'unknown' } } ``` ## Architecture Decision Matrix | Use Case | Architecture | Key Components | |----------|--------------|----------------| | Simple SaaS | Full-stack Next.js | ClerkProvider, Middleware | | Microservices | API Gateway + Services | JWT verification, User sync | | Multi-tenant | Organization-based | Org context, RLS | | Mobile + Web | Shared backend | Platform-agnostic JWT | | Enterprise | SSO + RBAC | SAML/OIDC, Roles | ## Output - Architecture pattern selected - Component diagram defined - Implementation patterns ready - Data flow documented ## Best Practices 1. **Always sync users to local database** - Don't rely solely on Clerk API 2. **Use webhooks for real-time sync** - Don't poll for changes 3. **Implement organization context early** - Retrofitting is painful 4. **Cache aggressively** - Reduce Clerk API calls 5. **Plan for SSO** - Enterprise customers will need it ## Resources - [Clerk Architecture Guide](https://clerk.com/docs/architecture) - [Multi-tenant Patterns](https://clerk.com/docs/organizations/overview) - [Backend Integration](https://clerk.com/docs/backend-requests/overview) ## Next Steps Proceed to `clerk-multi-env-setup` for multi-environment configuration.

Skill file: plugins/saas-packs/clerk-pack/skills/clerk-reference-architecture/SKILL.md