Clerk Auth Setup in Under 10 Minutes — 2026 Guide
Production-ready Clerk authentication setup for Next.js apps. Real errors, exact versions, and copy-paste code patterns developers actually use.
TL;DR
Clerk handles authentication so you don't have to. Install @clerk/nextjs, add environment variables, wrap your app in <ClerkProvider>, protect routes with middleware, and you're live in ~10 minutes. Real errors included below.
---
Why Clerk?
If you're building a SaaS or any app requiring user auth, Clerk eliminates the pain of password hashing, email verification, session management, and OAuth providers. You get:
Most indie hackers spend 4-6 weeks building auth from scratch. Clerk does it in 10 minutes.
---
Step 1: Create a Clerk Account & Get Keys
1. Head to [https://dashboard.clerk.com](https://dashboard.clerk.com) and sign up 2. Create a new application 3. Choose your framework (Next.js, React, etc.) 4. Copy your Publishable Key and Secret Key
You'll need both in your .env.local file:
```bash NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_[your-key] CLERK_SECRET_KEY=sk_live_[your-key] 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=/dashboard ```
Important: Verify the exact environment variable names in [Clerk's official docs](https://clerk.com/docs/references/nextjs/overview) — they've updated between versions.
---
Step 2: Install Dependencies
For Next.js 13+ (App Router), install Clerk v5.x (verify current version on npm):
```bash npm install @clerk/nextjs ```
For other frameworks, substitute accordingly (@clerk/react, @clerk/remix, etc.).
---
Step 3: Wrap Your App in ClerkProvider
Edit your app/layout.tsx:
```typescript import { ClerkProvider } from '@clerk/nextjs'; import type { Metadata } from 'next';
export const metadata: Metadata = { title: 'My App', };
export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <ClerkProvider> <html lang="en"> <body>{children}</body> </html> </ClerkProvider> ); } ```
---
Step 4: Create Sign-In & Sign-Up Pages
Create app/sign-in/[[...sign-in]]/page.tsx:
```typescript import { SignIn } from '@clerk/nextjs';
export default function SignInPage() { return ( <div className="flex items-center justify-center min-h-screen"> <SignIn /> </div> ); } ```
Create app/sign-up/[[...sign-up]]/page.tsx:
```typescript import { SignUp } from '@clerk/nextjs';
export default function SignUpPage() { return ( <div className="flex items-center justify-center min-h-screen"> <SignUp /> </div> ); } ```
The [[...sign-in]] syntax is Next.js [optional catch-all routing](/?guide=nextjs-routing) — Clerk needs this to handle multi-step flows.
---
Step 5: Protect Routes with Middleware
Create middleware.ts at your project root:
```typescript import { authMiddleware } from '@clerk/nextjs';
export default authMiddleware({ publicRoutes: ['/', '/sign-in', '/sign-up', '/pricing'], ignoredRoutes: ['/api/webhooks(.*)'], });
export const config = { matcher: [ '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|gif|svg|ttf|woff2?)|[^?]*\\.(?:webp|gif|svg)|api/webhooks).*)', '/(api|trpc)(.*)', ], }; ```
This prevents unauthenticated access to protected routes automatically.
---
Step 6: Access User Data in Components
Use the useUser hook in client components:
```typescript 'use client';
import { useUser, UserButton } from '@clerk/nextjs';
export function Header() { const { isLoaded, isSignedIn, user } = useUser();
if (!isLoaded) { return <div>Loading...</div>; }
if (isSignedIn) { return ( <div> <p>Welcome, {user.firstName}!</p> <UserButton afterSignOutUrl="/" /> </div> ); }
return <a href="/sign-in">Sign In</a>; } ```
---
Common Errors You'll Hit
Error 1: Missing Environment Variables
``` Error: The following environment variables are missing: NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY ```Fix: Double-check your .env.local file has both keys. Restart your dev server after adding them.
Error 2: Redirect Loop at Sign-In
``` Error: Redirect at sign-in URL: http://localhost:3000/sign-in?redirect_url=... ```Fix: You likely have /sign-in in your publicRoutes but the path doesn't match the NEXT_PUBLIC_CLERK_SIGN_IN_URL. Ensure they're identical.
Error 3: useUser() Hook Outside ClerkProvider
``` Error: useUser() must be used within <ClerkProvider> ```Fix: Mark your component with 'use client' at the top. Ensure it's a child of the <ClerkProvider> in your layout.
---
Accessing User Data on the Server
For API routes or server actions, use the auth() helper:
```typescript import { auth } from '@clerk/nextjs';
export async function GET(request: Request) { const { userId } = await auth();
if (!userId) { return new Response('Unauthorized', { status: 401 }); }
// Your protected logic here return Response.json({ userId }); } ```
---
Connect to Your Database
After users sign up, sync their data to your database via Clerk's webhooks. See [webhooks guide](/?guide=clerk-webhooks) for detailed setup.
---
Production Checklist
---
Pricing Reality Check
As of 2026, Clerk's free tier includes:
Always verify current pricing and limits in [official pricing docs](https://clerk.com/pricing) — these change annually.
---
What am I missing?
Did this guide gloss over something? Comment below:
Send corrections or additions in the comments. Keep indie hackers shipping.