clerk-auth
Expert patterns for Clerk auth implementation, middleware, organizations, webhooks, and user sync
Documentation
Clerk Authentication
Expert patterns for Clerk auth implementation, middleware, organizations, webhooks, and user sync
Patterns
Next.js App Router Setup
Complete Clerk setup for Next.js 14/15 App Router.
Includes ClerkProvider, environment variables, and basic sign-in/sign-up components.
Key components:
- ClerkProvider: Wraps app for auth context
- <SignIn />, <SignUp />: Pre-built auth forms
- <UserButton />: User menu with session management
Code_example
Environment variables (.env.local)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... 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
// app/layout.tsx import { ClerkProvider } from '@clerk/nextjs';
export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <ClerkProvider> <html lang="en"> <body>{children}</body> </html> </ClerkProvider> ); }
// app/sign-in/[[...sign-in]]/page.tsx import { SignIn } from '@clerk/nextjs';
export default function SignInPage() { return ( <div className="flex justify-center items-center min-h-screen"> <SignIn /> </div> ); }
// app/sign-up/[[...sign-up]]/page.tsx import { SignUp } from '@clerk/nextjs';
export default function SignUpPage() { return ( <div className="flex justify-center items-center min-h-screen"> <SignUp /> </div> ); }
// components/Header.tsx import { SignedIn, SignedOut, SignInButton, UserButton } from '@clerk/nextjs';
export function Header() { return ( <header className="flex justify-between p-4"> <h1>My App</h1> <SignedOut> <SignInButton /> </SignedOut> <SignedIn> <UserButton afterSignOutUrl="/" /> </SignedIn> </header> ); }
Anti_patterns
- Pattern: ClerkProvider inside page component | Why: Provider must wrap entire app in root layout | Fix: Move ClerkProvider to app/layout.tsx
- Pattern: Using auth() without middleware | Why: auth() requires clerkMiddleware to be configured | Fix: Set up middleware.ts with clerkMiddleware
References
Middleware Route Protection
Protect routes using clerkMiddleware and createRouteMatcher.
Best practices:
- Single middleware.ts file at project root
- Use createRouteMatcher for route groups
- auth.protect() for explicit protection
- Centralize all auth logic in middleware
Code_example
// middleware.ts import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
// Define protected route patterns const isProtectedRoute = createRouteMatcher([ '/dashboard(.)', '/settings(.)', '/api/private(.*)', ]);
// Define public routes (optional, for clarity) const isPublicRoute = createRouteMatcher([ '/', '/sign-in(.)', '/sign-up(.)', '/api/webhooks(.*)', ]);
export default clerkMiddleware(async (auth, req) => { // Protect matched routes if (isProtectedRoute(req)) { await auth.protect(); } });
export const config = { matcher: [ // Match all routes except static files '/((?!_next|[^?]\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).)', // Always run for API routes '/(api|trpc)(.*)', ], };
// Advanced: Role-based protection export default clerkMiddleware(async (auth, req) => { if (isProtectedRoute(req)) { await auth.protect(); }
// Admin routes require admin role if (req.nextUrl.pathname.startsWith('/admin')) { await auth.protect({ role: 'org:admin', }); }
// Premium routes require premium permission if (req.nextUrl.pathname.startsWith('/premium')) { await auth.protect({ permission: 'org:premium:access', }); } });
Anti_patterns
- Pattern: Multiple middleware.ts files | Why: Causes conflicts and redirect loops | Fix: Use single middleware.ts with route matchers
- Pattern: Manual redirects in components | Why: Double redirects, missed routes | Fix: Handle all redirects in middleware
- Pattern: Missing matcher config | Why: Middleware won't run on all routes | Fix: Add comprehensive matcher pattern
References
Server Component Authentication
Access auth state in Server Components using auth() and currentUser().
Key functions:
- auth(): Returns userId, sessionId, orgId, claims
- currentUser(): Returns full User object
- Both require clerkMiddleware to be configured
Code_example
// app/dashboard/page.tsx (Server Component) import { auth, currentUser } from '@clerk/nextjs/server'; import { redirect } from 'next/navigation';
export default async function DashboardPage() { const { userId } = await auth();
if (!userId) { redirect('/sign-in'); }
// Full user data (counts toward rate limits) const user = await currentUs
Use Cases
- User mentions or implies: adding authentication
- User mentions or implies: clerk auth
- User mentions or implies: user authentication
- User mentions or implies: sign in
- User mentions or implies: sign up
Quick Info
- Source
- antigravity
- Category
- Development & Code Tools
- Repository
- View Repo
- Scraped At
- Jan 26, 2026
Tags
Related Skills
2d-games
2D game development principles. Sprites, tilemaps, physics, camera.
add_repo_inst
Please browse the current repository under /workspace/{{ REPO_FOLDER_NAME }}, look at the documentation and relevant code, and understand the purpose of this repository.
address_pr_comments
First, check the branch {{ BRANCH_NAME }} and read the diff against the main branch to understand the purpose.