Claude-code-plugins clerk-prod-checklist
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/clerk-pack/skills/clerk-prod-checklist" ~/.claude/skills/jeremylongshore-claude-code-plugins-clerk-prod-checklist && rm -rf "$T"
manifest:
plugins/saas-packs/clerk-pack/skills/clerk-prod-checklist/SKILL.mdsource content
Clerk Production Checklist
Overview
Complete checklist to ensure your Clerk integration is production-ready. Covers environment config, security hardening, monitoring, error handling, and compliance.
Prerequisites
- Clerk integration working in development
- Production environment and domain configured
- CI/CD pipeline ready
Instructions
Step 1: Environment Configuration Checklist
| Check | Status | Action |
|---|---|---|
Using keys | [ ] | Switch from test to live keys |
is | [ ] | Never use test keys in production |
in | [ ] | Prevent accidental secret commits |
set | [ ] | Required for webhook verification |
| Production domain in Clerk Dashboard | [ ] | Dashboard > Domains |
| Sign-in/sign-up URLs configured | [ ] | Set etc. |
Step 2: Validation Script
// scripts/prod-readiness.ts import { createClerkClient } from '@clerk/backend' async function validateProduction() { const checks: { name: string; pass: boolean; detail: string }[] = [] // 1. Live keys check const pk = process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY || '' const sk = process.env.CLERK_SECRET_KEY || '' checks.push({ name: 'Live publishable key', pass: pk.startsWith('pk_live_'), detail: pk.startsWith('pk_live_') ? 'Using live key' : `Using ${pk.slice(0, 8)}... (should be pk_live_)`, }) checks.push({ name: 'Live secret key', pass: sk.startsWith('sk_live_'), detail: sk.startsWith('sk_live_') ? 'Using live key' : 'Should be sk_live_ for production', }) // 2. API connectivity try { const clerk = createClerkClient({ secretKey: sk }) await clerk.users.getUserList({ limit: 1 }) checks.push({ name: 'API connectivity', pass: true, detail: 'Backend API reachable' }) } catch (err: any) { checks.push({ name: 'API connectivity', pass: false, detail: err.message }) } // 3. Webhook secret checks.push({ name: 'Webhook secret configured', pass: !!process.env.CLERK_WEBHOOK_SECRET, detail: process.env.CLERK_WEBHOOK_SECRET ? 'Set' : 'CLERK_WEBHOOK_SECRET missing', }) // 4. Middleware exists const fs = await import('fs') const hasMiddleware = fs.existsSync('middleware.ts') || fs.existsSync('src/middleware.ts') checks.push({ name: 'Middleware present', pass: hasMiddleware, detail: hasMiddleware ? 'Found' : 'middleware.ts not found at project root', }) // Print results console.log('\n=== Clerk Production Readiness ===\n') for (const check of checks) { const icon = check.pass ? 'PASS' : 'FAIL' console.log(`[${icon}] ${check.name}: ${check.detail}`) } const allPass = checks.every((c) => c.pass) console.log(`\nResult: ${allPass ? 'READY for production' : 'NOT READY — fix failing checks'}`) process.exit(allPass ? 0 : 1) } validateProduction()
Run with:
npx tsx scripts/prod-readiness.ts
Step 3: Security Checklist
| Check | Status | Action |
|---|---|---|
| Middleware protects all routes | [ ] | Verify non-public routes require auth |
API routes check | [ ] | Return 401 if is null |
| Webhook signatures verified | [ ] | Use library for verification |
| CORS configured correctly | [ ] | Only allow production domain |
| Rate limiting on sensitive endpoints | [ ] | Use or similar |
| CSP headers set | [ ] | Add Clerk domains to Content-Security-Policy |
| No secret keys in client code | [ ] | never exposed |
Step 4: Monitoring Checklist
| Check | Status | Action |
|---|---|---|
| Health check endpoint | [ ] | monitoring Clerk API |
| Error tracking (Sentry) | [ ] | Clerk user context in error reports |
| Auth event logging | [ ] | Log sign-in, sign-out, permission denied |
| Webhook monitoring | [ ] | Alert on failed webhook deliveries |
| Uptime monitoring | [ ] | External monitor hitting health endpoint |
Step 5: Error Handling Checklist
| Check | Status | Action |
|---|---|---|
| Custom error pages | [ ] | , pages handle auth errors |
| Graceful auth failures | [ ] | Redirect to sign-in, don't show stack traces |
| Webhook retry handling | [ ] | Idempotency keys prevent duplicate processing |
| Session expiry UX | [ ] | Show "session expired" prompt, not blank page |
// app/error.tsx — global error boundary with auth context 'use client' import { useAuth } from '@clerk/nextjs' export default function Error({ error, reset }: { error: Error; reset: () => void }) { const { isSignedIn } = useAuth() return ( <div> <h2>Something went wrong</h2> <p>{error.message}</p> <button onClick={reset}>Try again</button> {!isSignedIn && <a href="/sign-in">Sign in</a>} </div> ) }
Step 6: Performance Checklist
| Check | Status | Action |
|---|---|---|
| Middleware matcher excludes static files | [ ] | Don't auth-check images, fonts, CSS |
User data cached () | [ ] | Deduplicate within request |
| Auth components lazy loaded | [ ] | for , |
| Edge Runtime for middleware | [ ] | Faster cold starts on Vercel |
Output
- Environment configuration verified (live keys, webhook secret, domain)
- Automated validation script (run in CI or before deploy)
- Security, monitoring, error handling, and performance checklists
- Global error boundary component with auth context
Error Handling
| Error | Cause | Solution |
|---|---|---|
| Validation script fails | Test keys in production | Switch to / keys |
| API connectivity check fails | Wrong secret key | Verify key in Clerk Dashboard > API Keys |
| Middleware not found | File in wrong location | Place at project root (not inside ) |
| Health check returns 503 | Clerk API unreachable | Check network, verify key, check status.clerk.com |
Examples
CI Production Gate
# .github/workflows/deploy.yml — add as pre-deploy step - name: Clerk production readiness run: npx tsx scripts/prod-readiness.ts env: NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ secrets.CLERK_PK_PROD }} CLERK_SECRET_KEY: ${{ secrets.CLERK_SK_PROD }} CLERK_WEBHOOK_SECRET: ${{ secrets.CLERK_WEBHOOK_SECRET_PROD }}
Resources
Next Steps
Proceed to
clerk-upgrade-migration for SDK version upgrades.