Claude Code Plugins

Community-maintained marketplace

Feedback
943
0

|

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

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.0.0
license MIT
author Jeremy Longshore <jeremy@intentsolutions.io>

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

// app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs'

export default function RootLayout({ children }) {
  return (
    <ClerkProvider>
      <html><body>{children}</body></html>
    </ClerkProvider>
  )
}

// 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

// 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<JWTPayload | null> {
  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

// 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

// 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

Next Steps

Proceed to clerk-multi-env-setup for multi-environment configuration.