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