jeremylongshore/claude-code-plugins-plus-skills
clerk-pack
plugins/saas-packs/clerk-pack/skills/clerk-security-basics/SKILL.md
January 22, 2026
Select agents to install to:
npx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/blob/main/plugins/saas-packs/clerk-pack/skills/clerk-security-basics/SKILL.md -a claude-code --skill clerk-security-basicsInstallation paths:
.claude/skills/clerk-security-basics/# Clerk Security Basics
## Overview
Implement security best practices for Clerk authentication in your application.
## Prerequisites
- Clerk SDK installed and configured
- Understanding of authentication security concepts
- Production deployment planned or active
## Instructions
### Step 1: Secure Environment Variables
```bash
# .env.local (development)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
# .env.production (production - use secrets manager)
# NEVER commit production keys to git
# Use Vercel/Railway/AWS Secrets Manager
# .gitignore
.env.local
.env.production
.env*.local
```
```typescript
// lib/env.ts - Validate environment at startup
const requiredEnvVars = [
'NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY',
'CLERK_SECRET_KEY'
]
export function validateEnv() {
for (const envVar of requiredEnvVars) {
if (!process.env[envVar]) {
throw new Error(`Missing required environment variable: ${envVar}`)
}
}
// Validate key format
const pk = process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY!
if (!pk.startsWith('pk_test_') && !pk.startsWith('pk_live_')) {
throw new Error('Invalid publishable key format')
}
}
```
### Step 2: Secure Middleware Configuration
```typescript
// middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
import { NextResponse } from 'next/server'
const isPublicRoute = createRouteMatcher([
'/',
'/sign-in(.*)',
'/sign-up(.*)',
'/api/webhooks(.*)'
])
const isAdminRoute = createRouteMatcher(['/admin(.*)'])
const isSensitiveRoute = createRouteMatcher(['/api/admin(.*)', '/api/billing(.*)'])
export default clerkMiddleware(async (auth, request) => {
const { userId, orgRole } = await auth()
// Security headers
const response = NextResponse.next()
response.headers.set('X-Frame-Options', 'DENY')
response.headers.set('X-Content-Type-Options', 'nosniff')
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
// Protect route