Clerk Auth Setup in 10 Minutes: 2026 Guide

Get Clerk authentication running in your Next.js app fast. Code examples, common errors, and production patterns included.

TL;DR

Clerk handles auth so you don't have to. Install the SDK, grab API keys from the dashboard, wrap your app with <ClerkProvider>, protect routes with middleware, and you're live. ~10 minutes for a working setup.

---

Why Clerk?

If you're building an indie product, you know the auth tax is real. Clerk abstracts away password hashing, session management, OAuth flows, and MFA. You get a managed solution without managing a user database (unless you want to). The free tier covers most indie launches.

Current pricing (verify in official docs): Free tier includes 5,000 monthly active users. Paid tiers start around $25/month. [Official pricing](https://clerk.com/pricing)

---

Prerequisites

  • Node.js 16+ (recommend 18+)
  • A Next.js 13+ project (v14 LTS is current as of 2026)
  • npm or yarn
  • A Clerk account (sign up free at [clerk.com](https://clerk.com))
  • ---

    Step 1: Create a Clerk Application (2 min)

    1. Go to [Clerk Dashboard](https://dashboard.clerk.com) 2. Click "Create application" 3. Choose your auth strategy (Email + Password, Google OAuth, etc.) 4. Copy your Publishable Key and Secret Key

    These are sensitive—treat CLERK_SECRET_KEY like a database password.

    ---

    Step 2: Install and Configure (3 min)

    Install the SDK

    ```bash npm install @clerk/nextjs ```

    Verify version compatibility: @clerk/nextjs v5.x is current (verify in official docs for latest).

    Set Environment Variables

    Create .env.local:

    ```bash 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 ```

    Note: Keys prefixed with NEXT_PUBLIC_ are exposed to the browser—that's intentional for Clerk's publishable key.

    ---

    Step 3: Wrap Your App (2 min)

    Update 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> ); } ```

    Production pattern: Don't pass appearance props here. Configure branding in the Clerk Dashboard or create a separate theme provider.

    ---

    Step 4: Add Auth Routes (2 min)

    Clerk provides pre-built UI components. Create sign-in and sign-up pages:

    app/sign-in/[[...index]]/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> ); } ```

    app/sign-up/[[...index]]/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 [[...index]] catch-all routing lets Clerk handle multi-step flows internally.

    ---

    Step 5: Protect Routes with Middleware (1 min)

    Create middleware.ts in your project root:

    ```typescript import { authMiddleware } from '@clerk/nextjs';

    export default authMiddleware({ publicRoutes: ['/', '/pricing', '/blog(.*)'], ignoredRoutes: ['/api/webhooks/clerk'], });

    export const config = { matcher: [ '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?))(?:.*)|api|trpc)(.*)', ], }; ```

    Production pattern: List all public routes explicitly. Anything not listed requires authentication.

    ---

    Step 6: Access User Data (Bonus)

    In any Server Component:

    ```typescript import { auth, currentUser } from '@clerk/nextjs';

    export default async function Dashboard() { const { userId } = await auth(); const user = await currentUser();

    if (!userId) { return <div>Not authenticated</div>; }

    return ( <div> <p>Welcome, {user?.firstName}</p> <p>Email: {user?.primaryEmailAddress?.emailAddress}</p> </div> ); } ```

    In Client Components, use the useAuth() hook:

    ```typescript 'use client';

    import { useAuth } from '@clerk/nextjs';

    export function UserNav() { const { userId, isSignedIn } = useAuth();

    if (!isSignedIn) return <a href="/sign-in">Sign In</a>;

    return <span>User ID: {userId}</span>; } ```

    ---

    Common Errors You'll See

    1. Missing Publishable Key

    ``` Error: The Clerk publishable key is missing. Make sure that the NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY environment variable is set. ```

    Fix: Verify .env.local exists and you've restarted your dev server after adding variables.

    2. Secret Key Exposed in Browser

    ``` Warning: The Clerk secret key was found in your public environment variables. Keep your secret key in server-side environment variables only. ```

    Fix: Remove NEXT_PUBLIC_ prefix from CLERK_SECRET_KEY. Never expose it.

    3. Middleware Not Intercepting Routes

    ``` Error: Page ... is not protected. User can access it without authentication. ```

    Fix: Ensure your middleware.ts matcher regex covers your protected routes. Test with console.log() in middleware to debug.

    ---

    Verification Checklist

  • [ ] Environment variables set in .env.local
  • [ ] ClerkProvider wraps root layout
  • [ ] Sign-in/sign-up pages created at correct paths
  • [ ] Middleware configured with correct public/private routes
  • [ ] Dev server restarted after env changes
  • [ ] API keys copied correctly (no extra spaces)
  • ---

    Next Steps

  • Set up [webhook integrations](https://clerk.com/docs/integrations/webhooks) to sync user data to your database
  • Configure [custom branding](https://clerk.com/docs/customization/branding) in the Dashboard
  • Enable [multi-factor authentication](https://clerk.com/docs/users/mfa)
  • Explore [custom JWT claims](https://clerk.com/docs/backend-requests/making-jwt-template) for role-based access
  • For production, review [Clerk's security best practices](https://clerk.com/docs/security/overview) (verify in official docs).

    ---

    Related Guides

  • [Building role-based access control](/?guide=rbac)
  • [Syncing user data to PostgreSQL](/?guide=database-sync)
  • ---

    What am I missing?

    Have you hit snags with Clerk setup? Found version incompatibilities? Set it up differently? Drop corrections and real-world tips in the comments below—let's build a better resource together.

    🔥 0d
    LIVE
    ↓ PlanetScale rage spiking •⚠ Vercel pricing complaints •↑ Railway gaining fast •↑ Supabase happiness rising •↑ Resend loved by devs •↓ PlanetScale rage spiking •⚠ Vercel pricing complaints •↑ Railway gaining fast •↑ Supabase happiness rising
    DEVELOPER PAIN RADAR // Loading...

    Developers complain.
    Opportunities appear.

    We track what developers are struggling with today — and what opportunities that creates.

    —
    guides today
    —
    avg happiness
    🔥 Pain
    📖 Guides
    🔭 Explore
    👤 Mine
    🔥 Pain Radar — rage scores today
    ↗ share
    💡 Opportunity Feed — pain = market gap
    📈 Tool Momentum
    all scores →
    📖 Latest Guide
    all guides →
    📖 All Guides
    📊 Tool Scores
    + Submit
    📰 Hacker News
    ➕ Submit a Tool
    ← back