clerk-migration-deep-dive
Migrate from other authentication providers to Clerk. Use when migrating from Auth0, Firebase, Supabase Auth, NextAuth, or custom authentication solutions. Trigger with phrases like "migrate to clerk", "clerk migration", "switch to clerk", "auth0 to clerk", "firebase auth to clerk".
Best use case
clerk-migration-deep-dive is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Migrate from other authentication providers to Clerk. Use when migrating from Auth0, Firebase, Supabase Auth, NextAuth, or custom authentication solutions. Trigger with phrases like "migrate to clerk", "clerk migration", "switch to clerk", "auth0 to clerk", "firebase auth to clerk".
Teams using clerk-migration-deep-dive should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/clerk-migration-deep-dive/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How clerk-migration-deep-dive Compares
| Feature / Agent | clerk-migration-deep-dive | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Migrate from other authentication providers to Clerk. Use when migrating from Auth0, Firebase, Supabase Auth, NextAuth, or custom authentication solutions. Trigger with phrases like "migrate to clerk", "clerk migration", "switch to clerk", "auth0 to clerk", "firebase auth to clerk".
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Clerk Migration Deep Dive
## Current State
!`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'`
## Overview
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.
## Prerequisites
- Current auth provider access with admin/export permissions
- Clerk account with API keys
- Git repository with clean working state
- Migration timeline planned (recommend 2-4 weeks)
## Instructions
### Step 1: Export Users from Current Provider
**Auth0 Export:**
```bash
# 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:**
```typescript
// 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))
```
### Step 2: Import Users to Clerk
```typescript
// 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))
})
```
### Step 3: Update Database References
```typescript
// 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}`)
}
}
}
```
### Step 4: Replace Auth Code (NextAuth to Clerk Example)
```typescript
// 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()
```
```typescript
// 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()
```
```typescript
// 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()
})
```
### Step 5: Parallel Running (Optional Safety Net)
```typescript
// 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
}
```
### Step 6: Cleanup After Migration
```bash
# 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
```
## Output
- User export from current auth provider (Auth0, NextAuth, Firebase)
- Bulk import script with rate limiting and error handling
- Database reference mapping (old auth IDs to Clerk IDs)
- Code migration examples (NextAuth to Clerk)
- Parallel running bridge for safe transition
- Cleanup checklist for removing old auth code
## Error Handling
| 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 |
## Examples
### Migration Verification Script
```typescript
// 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))
}
}
```
## Resources
- [Clerk Migration Overview](https://clerk.com/docs/deployments/migrate-overview)
- [Migrate from Auth0](https://clerk.com/docs/deployments/migrate-from-auth0)
- [Migrate from NextAuth](https://clerk.com/docs/deployments/migrate-from-nextauth)
## Next Steps
After migration, review `clerk-prod-checklist` for production readiness.Related Skills
sql-migration-generator
Sql Migration Generator - Auto-activating skill for Backend Development. Triggers on: sql migration generator, sql migration generator Part of the Backend Development skill category.
neurodivergent-visual-org
Creates ADHD-friendly visual organizational tools using Mermaid diagrams optimized for neurodivergent thinking patterns. Auto-detects overwhelm, provides compassionate task breakdowns with realistic time estimates. Use when creating visual task breakdowns, decision trees, or organizational diagrams for neurodivergent users or accessibility-focused projects. Trigger with 'neurodivergent', 'visual', 'org'.
managing-database-migrations
Process use when you need to work with database migrations. This skill provides schema migration management with comprehensive guidance and automation. Trigger with phrases like "create migration", "run migrations", or "manage schema versions".
exa-upgrade-migration
Upgrade exa-js SDK versions and handle breaking changes safely. Use when upgrading the Exa SDK, detecting deprecations, or migrating between exa-js versions. Trigger with phrases like "upgrade exa", "exa update", "exa breaking changes", "update exa-js", "exa new version".
exa-migration-deep-dive
Migrate from other search APIs (Google, Bing, Tavily, Serper) to Exa neural search. Use when switching to Exa from another search provider, migrating search pipelines, or evaluating Exa as a replacement for traditional search APIs. Trigger with phrases like "migrate to exa", "switch to exa", "replace google search with exa", "exa vs tavily", "exa migration", "move to exa".
evernote-upgrade-migration
Upgrade Evernote SDK versions and migrate between API versions. Use when upgrading SDK, handling breaking changes, or migrating to newer API patterns. Trigger with phrases like "upgrade evernote sdk", "evernote migration", "update evernote", "evernote breaking changes".
evernote-migration-deep-dive
Deep dive into Evernote data migration strategies. Use when migrating to/from Evernote, bulk data transfers, or complex migration scenarios. Trigger with phrases like "migrate to evernote", "migrate from evernote", "evernote data transfer", "bulk evernote migration".
elevenlabs-upgrade-migration
Upgrade ElevenLabs SDK versions and migrate between API model generations. Use when upgrading the elevenlabs-js or elevenlabs Python SDK, migrating from v1 to v2 models, or handling deprecations. Trigger: "upgrade elevenlabs", "elevenlabs migration", "elevenlabs breaking changes", "update elevenlabs SDK", "migrate elevenlabs model", "eleven_v3 migration".
documenso-upgrade-migration
Manage Documenso API version upgrades and SDK migrations. Use when upgrading from v1 to v2 API, updating SDK versions, or migrating between Documenso versions. Trigger with phrases like "documenso upgrade", "documenso v2 migration", "update documenso SDK", "documenso API version".
documenso-migration-deep-dive
Execute comprehensive Documenso migration strategies for platform switches. Use when migrating from other signing platforms, re-platforming to Documenso, or performing major infrastructure changes. Trigger with phrases like "migrate to documenso", "documenso migration", "switch to documenso", "documenso replatform", "replace docusign".
deepgram-webhooks-events
Implement Deepgram callback and webhook handling for async transcription. Use when implementing callback URLs, processing async transcription results, or handling Deepgram event notifications. Trigger: "deepgram callback", "deepgram webhook", "async transcription", "deepgram events", "deepgram notifications", "deepgram async".
deepgram-upgrade-migration
Plan and execute Deepgram SDK upgrades and model migrations. Use when upgrading SDK versions (v3->v4->v5), migrating models (Nova-2 to Nova-3), or planning API version transitions. Trigger: "upgrade deepgram", "deepgram migration", "update deepgram SDK", "deepgram version upgrade", "nova-3 migration".