openrouter-compliance-review
Review OpenRouter integration for regulatory compliance (SOC2, GDPR,
clerk-migration-deep-dive
Migrate from other authentication providers to Clerk.
Full skill instructions
!npm list @auth0/nextjs-auth0 next-auth @supabase/auth-helpers-nextjs firebase 2>/dev/null | grep -E "auth0|next-auth|supabase|firebase" || echo 'No auth providers detected'
Comprehensive guide to migrating from Auth0, Firebase Auth, Supabase Auth, or NextAuth to Clerk. Covers user data export, bulk import, parallel running, and phased migration.
Auth0 Export:
# Export users via Auth0 Management API
curl -s -H "Authorization: Bearer $AUTH0_TOKEN" \
"https://$AUTH0_DOMAIN/api/v2/users?per_page=100&page=0" \
| jq '[.[] | {email: .email, name: .name, picture: .picture, created_at: .created_at}]' \
> auth0-users.json
NextAuth (Prisma) Export:
// scripts/export-nextauth-users.ts
const users = await prisma.user.findMany({
include: { accounts: true },
})
const exported = users.map((u) => ({
email: u.email,
name: u.name,
image: u.image,
provider: u.accounts[0]?.provider,
createdAt: u.createdAt,
}))
await fs.writeFile('nextauth-users.json', JSON.stringify(exported, null, 2))
// scripts/import-to-clerk.ts
import { createClerkClient } from '@clerk/backend'
import users from './auth0-users.json'
const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY! })
interface MigrationResult {
email: string
status: 'created' | 'exists' | 'error'
clerkId?: string
error?: string
}
async function importUsers(): Promise<MigrationResult[]> {
const results: MigrationResult[] = []
for (const user of users) {
try {
const created = await clerk.users.createUser({
emailAddress: [user.email],
firstName: user.name?.split(' ')[0],
lastName: user.name?.split(' ').slice(1).join(' '),
skipPasswordRequirement: true, // User will set password on first sign-in
})
results.push({ email: user.email, status: 'created', clerkId: created.id })
console.log(`Created: ${user.email} -> ${created.id}`)
} catch (err: any) {
if (err.status === 422) {
results.push({ email: user.email, status: 'exists' })
} else {
results.push({ email: user.email, status: 'error', error: err.message })
}
}
// Respect rate limits
await new Promise((resolve) => setTimeout(resolve, 100))
}
return results
}
importUsers().then((results) => {
const summary = {
total: results.length,
created: results.filter((r) => r.status === 'created').length,
exists: results.filter((r) => r.status === 'exists').length,
errors: results.filter((r) => r.status === 'error').length,
}
console.log('Migration summary:', summary)
fs.writeFileSync('migration-results.json', JSON.stringify(results, null, 2))
})
// scripts/update-db-references.ts
import { createClerkClient } from '@clerk/backend'
const clerk = createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY! })
async function updateDatabaseReferences() {
// Get all users from your database
const dbUsers = await db.user.findMany()
for (const dbUser of dbUsers) {
// Find corresponding Clerk user by email
const clerkUsers = await clerk.users.getUserList({
emailAddress: [dbUser.email],
})
if (clerkUsers.totalCount > 0) {
const clerkUser = clerkUsers.data[0]
await db.user.update({
where: { id: dbUser.id },
data: {
clerkId: clerkUser.id,
// Keep old auth ID for rollback
legacyAuthId: dbUser.authProviderId,
},
})
console.log(`Mapped: ${dbUser.email} -> ${clerkUser.id}`)
}
}
}
// BEFORE: NextAuth
// import { getServerSession } from 'next-auth'
// import { authOptions } from '@/lib/auth'
// const session = await getServerSession(authOptions)
// const userId = session?.user?.id
// AFTER: Clerk
import { auth } from '@clerk/nextjs/server'
const { userId } = await auth()
// BEFORE: NextAuth client hook
// import { useSession } from 'next-auth/react'
// const { data: session } = useSession()
// AFTER: Clerk client hook
import { useUser } from '@clerk/nextjs'
const { user, isLoaded } = useUser()
// BEFORE: NextAuth middleware
// export { default } from 'next-auth/middleware'
// export const config = { matcher: ['/dashboard(.*)'] }
// AFTER: Clerk middleware
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
const isProtected = createRouteMatcher(['/dashboard(.*)'])
export default clerkMiddleware(async (auth, req) => {
if (isProtected(req)) await auth.protect()
})
// lib/auth-bridge.ts — run both auth systems during transition
import { auth as clerkAuth } from '@clerk/nextjs/server'
export async function getAuthUser() {
// Try Clerk first (new system)
const { userId: clerkUserId } = await clerkAuth()
if (clerkUserId) {
return { provider: 'clerk', userId: clerkUserId }
}
// Fall back to legacy system during migration window
// const legacySession = await getLegacySession()
// if (legacySession) return { provider: 'legacy', userId: legacySession.userId }
return null
}
# After migration is verified (2+ weeks in production):
npm uninstall next-auth @auth0/nextjs-auth0 # Remove old auth packages
# Delete old auth files: pages/api/auth/[...nextauth].ts, lib/auth.ts
# Remove legacy database columns after confirming all users migrated
| Error | Cause | Solution |
|---|---|---|
| Duplicate email on import | User already exists in Clerk | Skip (status: 'exists') or merge |
| Invalid email format | Dirty data from export | Clean/validate before import |
| Rate limited during import | Too many API calls | Add 100ms delay between creates |
| Password can't be migrated | Passwords are hashed | Use skipPasswordRequirement, user sets new password |
| OAuth accounts | Social login tokens non-transferable | Users re-link OAuth accounts on first Clerk sign-in |
// scripts/verify-migration.ts
async function verifyMigration() {
const dbUsers = await db.user.findMany({ where: { clerkId: { not: null } } })
const unmapped = await db.user.findMany({ where: { clerkId: null } })
console.log(`Mapped: ${dbUsers.length}, Unmapped: ${unmapped.length}`)
if (unmapped.length > 0) {
console.log('Unmapped users:', unmapped.map((u) => u.email))
}
}
After migration, review clerk-prod-checklist for production readiness.
Review OpenRouter integration for regulatory compliance (SOC2, GDPR,
Data synchronization, ETL patterns, and data management for MaintainX.
Execute Groq primary workflow: chat completions with tool use and JSON
Validate CSRF protection implementations for security gaps. Use when
Configure this skill should be used when the user asks about "API contract",
Execute Ideogram incident response with triage, mitigation, and postmortem.
Execute create, select, and transform features to improve machine learning
Reusable patterns for the Gamma REST API (no SDK exists).
Apply production-ready Deepgram SDK patterns for TypeScript and Python.
Migrate to OpenRouter from direct provider APIs or upgrade between SDK/model
Diagnose and fix common OpenRouter API errors. Use when encountering
Optimize Linear API usage, reduce unnecessary calls, and maximize
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience