Skip to main content

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".

Quellinformationen

Repository
jeremylongshore/claude-code-plugins-plus-skills
Letzte Quellaktivität
19. Juli 2026 um 02:55
Erkannte Sprache von SKILL.md
Englisch
Sterne
2.604
Forks
378

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
2 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
clerk-reference-architecture
description
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.14.0
license
MIT
author
Jeremy Longshore <jeremy@intentsolutions.io>
tags
["saas","clerk","authentication"]
compatibility
Designed for Claude Code, also compatible with Codex and OpenClaw
# Clerk Reference Architecture ## Overview Reference architectures for implementing Clerk in common application patterns: Next.js full-stack, microservices with shared auth, multi-tenant SaaS, and mobile + web with shared backend. ## Prerequisites - Understanding of web application architecture - Familiarity with authentication patterns (JWT, sessions, OAuth) - Knowledge of your tech stack and scaling requirements ## Instructions ### Architecture 1: Next.js Full-Stack Application ``` Browser │ ├─▸ Next.js Middleware (clerkMiddleware) │ └─▸ Validates session token on every request │ ├─▸ Server Components (auth(), currentUser()) │ └─▸ Direct access to user data, no network call │ ├─▸ Client Components (useUser(), useAuth()) │ └─▸ Real-time auth state via ClerkProvider │ ├─▸ API Routes (auth() for userId, getToken() for JWT) │ └─▸ Call external services with Clerk JWT │ └─▸ Webhooks (/api/webhooks/clerk) └─▸ Sync user data to database ``` ```typescript // app/layout.tsx — entry point import { ClerkProvider } from '@clerk/nextjs' export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <ClerkProvider> <html><body>{children}</body></html> </ClerkProvider> ) } ``` ```typescript // middleware.ts — auth boundary import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server' const isPublic = createRouteMatcher(['/', '/sign-in(.*)', '/sign-up(.*)', '/api/webhooks(.*)']) export default clerkMiddleware(async (auth, req) => { if (!isPublic(req)) await auth.protect() }) ``` ### Architecture 2: Microservices with Shared Auth ``` Browser ─▸ API Gateway / BFF (Next.js + Clerk) │ ├─▸ Service A (Node.js) ──── verifies JWT ├─▸ Service B (Python) ──── verifies JWT └─▸ Service C (Go) ──────── verifies JWT ``` ```typescript // BFF: Generate service-specific JWT // app/api/proxy/[service]/route.ts import { auth } from '@clerk/nextjs/server' export async function GET(req: Request, { params }: { params: { service: string } }) { const { userId, getToken } = await auth() if (!userId) return Response.json({ error: 'Unauthorized' }, { status: 401 }) // Get JWT with service-specific claims const token = await getToken({ template: params.service }) const serviceUrls: Record<string, string> = { billing: process.env.BILLING_SERVICE_URL!, analytics: process.env.ANALYTICS_SERVICE_URL!, notifications: process.env.NOTIFICATION_SERVICE_URL!, } const response = await fetch(`${serviceUrls[params.service]}/api/data`, { headers: { Authorization: `Bearer ${token}` }, }) return Response.json(await response.json()) } ``` ```typescript // Downstream service: Verify Clerk JWT // services/billing/src/middleware.ts (Express) import { clerkMiddleware, requireAuth } from '@clerk/express' app.use(clerkMiddleware()) app.get('/api/data', requireAuth(), (req, res) => { // req.auth.userId is available res.json({ userId: req.auth.userId }) }) ``` ### Architecture 3: Multi-Tenant SaaS ``` Tenant A (org_abc) ──┐ Tenant B (org_def) ──┤──▸ Shared App ──▸ Shared DB (tenant-scoped queries) Tenant C (org_ghi) ──┘ ``` ```typescript // lib/tenant.ts — tenant-scoped data access import { auth } from '@clerk/nextjs/server' export async function getTenantData<T>(query: (orgId: string) => Promise<T>): Promise<T> { const { orgId } = await auth() if (!orgId) throw new Error('No organization selected') return query(orgId) } // Usage: export async function getProjects() { return getTenantData((orgId) => db.project.findMany({ where: { organizationId: orgId } }) ) } ``` ```typescript // middleware.ts — enforce org context on tenant routes import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server' const isTenantRoute = createRouteMatcher(['/app(.*)']) export default clerkMiddleware(async (auth, req) => { if (isTenantRoute(req)) { const { orgId } = await auth.protect() if (!orgId) { // Redirect to org selector if no org is active return Response.redirect(new URL('/select-org', req.url)) } } }) ``` ```typescript // app/select-org/page.tsx import { OrganizationSwitcher } from '@clerk/nextjs' export default function SelectOrg() { return ( <div className="flex min-h-screen items-center justify-center"> <div> <h1>Select Your Organization</h1> <OrganizationSwitcher afterSelectOrganizationUrl="/app/dashboard" hidePersonal={true} /> </div> </div> ) } ``` ### Architecture 4: Mobile + Web with Shared Backend ``` Web App (Next.js + @clerk/nextjs) ──┐ Mobile App (React Native + @clerk/clerk-expo) ──┤──▸ Backend API (Express + @clerk/express) └──▸ Database ``` ```typescript // Backend API: Express with Clerk // server.ts import express from 'express' import { clerkMiddleware, requireAuth, getAuth } from '@clerk/express' const app = express() // Apply Clerk middleware globally app.use(clerkMiddleware()) // Public endpoint app.get('/api/public', (req, res) => { res.json({ message: 'Public endpoint' }) }) // Protected endpoint (works with both web and mobile clients) app.get('/api/profile', requireAuth(), async (req, res) => { const { userId } = getAuth(req) const user = await db.user.findUnique({ where: { clerkId: userId } }) res.json({ user }) }) app.listen(3001) ``` ## Output - Next.js full-stack architecture with middleware, server/client components, and webhooks - Microservices architecture with BFF proxy and JWT-based service auth - Multi-tenant SaaS with organization-scoped data access - Mobile + web with shared Express backend using `@clerk/express` ## Error Handling | Pattern | Common Issue | Solution | |---------|-------------|----------| | Full-stack | Middleware redirect loop | Add sign-in route to public routes | | Microservices | JWT template not configured | Create JWT template in Dashboard per service | | Multi-tenant | No org selected | Redirect to org selector before tenant routes | | Mobile + Web | Token not sent from mobile | Include `Authorization: Bearer <token>` in mobile fetch | ## Examples ### Database Schema for Clerk Integration ```prisma // prisma/schema.prisma model User { id String @id @default(cuid()) clerkId String @unique email String @unique name String? createdAt DateTime @default(now()) posts Post[] orgMemberships OrgMembership[] } model OrgMembership { id String @id @default(cuid()) userId String orgId String // Clerk organization ID role String // org:admin, org:member, etc. user User @relation(fields: [userId], references: [id]) @@unique([userId, orgId]) } ``` ## Resources - [Clerk Architecture Patterns](https://clerk.com/docs/quickstarts/nextjs) - [Clerk Organizations (Multi-Tenant)](https://clerk.com/docs/organizations/overview) - [Clerk Express Integration](https://clerk.com/docs/quickstarts/express) ## Next Steps Proceed to `clerk-multi-env-setup` for multi-environment configuration.
Auf GitHub ansehen