clerk-core-workflow-a
Configures user authentication flows using Clerk, including sign-up, sign-in, and OAuth social login.
Install
mkdir -p .claude/skills/clerk-core-workflow-a && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/6630" && unzip -o skill.zip -d .claude/skills/clerk-core-workflow-a && rm skill.zipInstalls to .claude/skills/clerk-core-workflow-a
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Implement user sign-up and sign-in flows with Clerk.Key capabilities
- →Implement sign-up and sign-in flows
- →Configure OAuth social login providers
- →Customize authentication UI components
- →Handle multi-factor authentication
- →Manage session redirects
How it works
It integrates Clerk components or custom forms into the application to handle authentication state, session activation, and user verification.
Inputs & outputs
When to use clerk-core-workflow-a
- →Implement Clerk sign-in and sign-up flows
- →Set up OAuth social login providers
- →Customize authentication UI components
- →Handle multi-factor authentication
About this skill
Clerk Core Workflow A: Sign-Up & Sign-In
Overview
Implement authentication flows with Clerk: pre-built components for rapid setup, custom forms for full UI control, OAuth social login, email/phone verification, and multi-factor authentication.
Prerequisites
- Clerk SDK installed and configured (
clerk-install-authcompleted) - OAuth providers enabled in Dashboard > User & Authentication > Social Connections
- Sign-in/sign-up environment variables set
Instructions
Step 1: Pre-Built Components (Quick Start)
// app/sign-in/[[...sign-in]]/page.tsx
import { SignIn } from '@clerk/nextjs'
export default function SignInPage() {
return (
<div className="flex min-h-screen items-center justify-center">
<SignIn
appearance={{
elements: {
rootBox: 'mx-auto',
card: 'shadow-xl rounded-2xl',
headerTitle: 'text-2xl',
socialButtonsBlockButton: 'rounded-lg',
},
}}
routing="path"
path="/sign-in"
signUpUrl="/sign-up"
/>
</div>
)
}
// app/sign-up/[[...sign-up]]/page.tsx
import { SignUp } from '@clerk/nextjs'
export default function SignUpPage() {
return (
<div className="flex min-h-screen items-center justify-center">
<SignUp routing="path" path="/sign-up" signInUrl="/sign-in" />
</div>
)
}
# .env.local — routing configuration
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/onboarding
Step 2: Custom Sign-In Form (Full UI Control)
'use client'
import { useSignIn } from '@clerk/nextjs'
import { useRouter } from 'next/navigation'
import { useState } from 'react'
export function CustomSignIn() {
const { signIn, setActive, isLoaded } = useSignIn()
const router = useRouter()
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState('')
const [loading, setLoading] = useState(false)
if (!isLoaded) return null
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setError('')
setLoading(true)
try {
const result = await signIn.create({
identifier: email,
password,
})
if (result.status === 'complete') {
// Session created — activate it and redirect
await setActive({ session: result.createdSessionId })
router.push('/dashboard')
} else if (result.status === 'needs_second_factor') {
// MFA required — handled in Step 5
router.push('/sign-in/mfa')
} else if (result.status === 'needs_identifier') {
setError('Please enter your email address')
}
} catch (err: any) {
const clerkError = err.errors?.[0]
switch (clerkError?.code) {
case 'form_identifier_not_found':
setError('No account found with this email')
break
case 'form_password_incorrect':
setError('Incorrect password')
break
case 'session_exists':
router.push('/dashboard')
break
default:
setError(clerkError?.message || 'Sign-in failed')
}
} finally {
setLoading(false)
}
}
return (
<form onSubmit={handleSubmit} className="space-y-4 max-w-sm mx-auto">
<input
type="email" value={email}
onChange={e => setEmail(e.target.value)}
placeholder="Email address" required
className="w-full p-2 border rounded"
/>
<input
type="password" value={password}
onChange={e => setPassword(e.target.value)}
placeholder="Password" required
className="w-full p-2 border rounded"
/>
{error && <p className="text-red-500 text-sm">{error}</p>}
<button type="submit" disabled={loading} className="w-full p-2 bg-blue-600 text-white rounded">
{loading ? 'Signing in...' : 'Sign In'}
</button>
</form>
)
}
Step 3: OAuth Social Login
'use client'
import { useSignIn } from '@clerk/nextjs'
export function OAuthButtons() {
const { signIn, isLoaded } = useSignIn()
if (!isLoaded) return null
const signInWith = (strategy: 'oauth_google' | 'oauth_github' | 'oauth_apple') => {
signIn.authenticateWithRedirect({
strategy,
redirectUrl: '/sso-callback',
redirectUrlComplete: '/dashboard',
})
}
return (
<div className="flex flex-col gap-3">
<button onClick={() => signInWith('oauth_google')} className="p-2 border rounded">
Continue with Google
</button>
<button onClick={() => signInWith('oauth_github')} className="p-2 border rounded">
Continue with GitHub
</button>
<button onClick={() => signInWith('oauth_apple')} className="p-2 border rounded">
Continue with Apple
</button>
</div>
)
}
// app/sso-callback/page.tsx — handles OAuth redirect
import { AuthenticateWithRedirectCallback } from '@clerk/nextjs'
export default function SSOCallback() {
return <AuthenticateWithRedirectCallback />
}
Step 4: Custom Sign-Up with Email Verification
'use client'
import { useSignUp } from '@clerk/nextjs'
import { useRouter } from 'next/navigation'
import { useState } from 'react'
export function CustomSignUp() {
const { signUp, setActive, isLoaded } = useSignUp()
const router = useRouter()
const [step, setStep] = useState<'form' | 'verify'>('form')
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [code, setCode] = useState('')
const [error, setError] = useState('')
if (!isLoaded) return null
const handleSignUp = async (e: React.FormEvent) => {
e.preventDefault()
try {
await signUp.create({ emailAddress: email, password })
// Send verification email
await signUp.prepareEmailAddressVerification({ strategy: 'email_code' })
setStep('verify')
} catch (err: any) {
setError(err.errors?.[0]?.longMessage || 'Sign-up failed')
}
}
const handleVerify = async (e: React.FormEvent) => {
e.preventDefault()
try {
const result = await signUp.attemptEmailAddressVerification({ code })
if (result.status === 'complete') {
await setActive({ session: result.createdSessionId })
router.push('/onboarding')
}
} catch (err: any) {
setError(err.errors?.[0]?.longMessage || 'Verification failed')
}
}
if (step === 'verify') {
return (
<form onSubmit={handleVerify} className="space-y-4">
<p>Check your email for a verification code</p>
<input
value={code} onChange={e => setCode(e.target.value)}
placeholder="Enter 6-digit code" required
/>
{error && <p className="text-red-500">{error}</p>}
<button type="submit">Verify Email</button>
</form>
)
}
return (
<form onSubmit={handleSignUp} className="space-y-4">
<input type="email" value={email} onChange={e => setEmail(e.target.value)} placeholder="Email" required />
<input type="password" value={password} onChange={e => setPassword(e.target.value)} placeholder="Password" required />
{error && <p className="text-red-500">{error}</p>}
<button type="submit">Create Account</button>
</form>
)
}
Step 5: Multi-Factor Authentication (TOTP)
'use client'
import { useSignIn } from '@clerk/nextjs'
import { useRouter } from 'next/navigation'
import { useState } from 'react'
export function MFAVerification() {
const { signIn, setActive } = useSignIn()
const router = useRouter()
const [code, setCode] = useState('')
const [error, setError] = useState('')
const handleMFA = async (e: React.FormEvent) => {
e.preventDefault()
try {
const result = await signIn!.attemptSecondFactor({
strategy: 'totp',
code,
})
if (result.status === 'complete') {
await setActive!({ session: result.createdSessionId })
router.push('/dashboard')
}
} catch (err: any) {
setError(err.errors?.[0]?.message || 'Invalid code')
}
}
return (
<form onSubmit={handleMFA} className="space-y-4">
<h2>Two-Factor Authentication</h2>
<p>Enter the code from your authenticator app</p>
<input
value={code} onChange={e => setCode(e.target.value)}
placeholder="6-digit TOTP code" maxLength={6} required
inputMode="numeric" pattern="[0-9]*"
/>
{error && <p className="text-red-500">{error}</p>}
<button type="submit">Verify</button>
</form>
)
}
Error Handling
| Error | Cause | Solution |
|---|---|---|
form_identifier_not_found | Email not registered | Show sign-up link or check Clerk instance |
form_password_incorrect | Wrong password | Display error, offer password reset link |
session_exists | Already signed in | Redirect to dashboard |
verification_failed | Wrong or expired code | Allow retry; offer "Resend code" button |
oauth_callback_error | OAuth misconfigured | Check redirect URIs in Dashboard > Social Connections |
identifier_already_signed_in | Multi-session not enabled | Enable multi-session or redirect to dashboard |
Enterprise Considerations
- Customize component appearance with Clerk's
appearanceprop or custom CSS -- matches your design system without building from scratch - For Enterprise SSO (SAML/OIDC), users authenticate through their IdP; the
<SignIn>component handles the redirect automatically - Phone number verification uses
phone_codestrategy instead ofemail_code - Magic link sign-in uses
email_linkstrategy for passwordless auth - Track sign-up conversion rates by subscribing to
user.createdwebhooks - MFA enrollment is managed via
<UserProfile />component or `use
Content truncated.
Prerequisites
Limitations
- →Multi-session not enabled
- →OAuth misconfigured
How it compares
It offers a choice between pre-built components for rapid development and custom forms for complete brand control over the authentication UI.
Compared to similar skills
clerk-core-workflow-a side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| clerk-core-workflow-a (this skill) | 1 | 27d | Review | Beginner |
| nextjs-supabase-auth | 12 | 6mo | No flags | Intermediate |
| better-auth | 5 | 9mo | Review | Intermediate |
| auth-patterns | 7 | 7mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by jeremylongshore
View all by jeremylongshore →You might also like
nextjs-supabase-auth
davila7
Expert integration of Supabase Auth with Next.js App Router Use when: supabase auth next, authentication next.js, login supabase, auth middleware, protected route.
better-auth
mrgoonie
Implement authentication and authorization with Better Auth - a framework-agnostic TypeScript authentication framework. Features include email/password authentication with verification, OAuth providers (Google, GitHub, Discord, etc.), two-factor authentication (TOTP, SMS), passkeys/WebAuthn support, session management, role-based access control (RBAC), rate limiting, and database adapters. Use when adding authentication to applications, implementing OAuth flows, setting up 2FA/MFA, managing user sessions, configuring authorization rules, or building secure authentication systems for web applications.
auth-patterns
davepoon
This skill should be used when the user asks about "authentication in Next.js", "NextAuth", "Auth.js", "middleware auth", "protected routes", "session management", "JWT", "login flow", or needs guidance on implementing authentication and authorization in Next.js applications.
clerk-common-errors
jeremylongshore
Troubleshoot common Clerk errors and issues. Use when encountering authentication errors, SDK issues, or configuration problems with Clerk. Trigger with phrases like "clerk error", "clerk not working", "clerk authentication failed", "clerk issue", "fix clerk".
clerk-enterprise-rbac
jeremylongshore
Configure enterprise SSO, role-based access control, and organization management. Use when implementing SSO integration, configuring role-based permissions, or setting up organization-level controls. Trigger with phrases like "clerk SSO", "clerk RBAC", "clerk enterprise", "clerk roles", "clerk permissions", "clerk SAML".
clerk-performance-tuning
jeremylongshore
Optimize Clerk authentication performance. Use when improving auth response times, reducing latency, or optimizing Clerk SDK usage. Trigger with phrases like "clerk performance", "clerk optimization", "clerk slow", "clerk latency", "optimize clerk".