Clerk Auth Setup in Under 10 Minutes 2026
Set up production-ready authentication with Clerk in minutes. Exact steps, real errors, and copy-paste code for Next.js apps.
TL;DR
Clerk handles auth complexity so you don't. Install the SDK, create a Clerk app, wrap your routes, add one middleware line. Done. We'll walk through real errors you'll hit and how to avoid them.
---
What You Need
node >= 18.17Step 1: Create Your Clerk Project (2 minutes)
1. Sign up at [clerk.com](https://clerk.com)
2. Create a new application
3. Choose "Next.js" as your framework
4. Copy your NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY
Why separate keys? The publishable key is safe in browser code (prefixed with NEXT_PUBLIC_). The secret key never leaves your server.
Step 2: Install Dependencies (1 minute)
```bash npm install @clerk/nextjs@latest ```
Verify you're installing version 5.x or later (check official docs for current version). We'll verify the exact version:
```bash npm list @clerk/nextjs ```
Step 3: Environment Variables (1 minute)
Create .env.local:
```bash NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxx CLERK_SECRET_KEY=sk_test_xxx 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: These values are environment-specific. Verify in your Clerk dashboard that keys match your development instance.
Step 4: Wrap Your App (2 minutes)
Modify app/layout.tsx:
```typescript import { ClerkProvider } from '@clerk/nextjs';
export const metadata = { title: 'My App', };
export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <ClerkProvider> <html lang="en"> <body>{children}</body> </html> </ClerkProvider> ); } ```
Step 5: Middleware Protection (1 minute)
Create middleware.ts in your project root:
```typescript import { authMiddleware } from '@clerk/nextjs';
export default authMiddleware({ // Routes that don't require authentication publicRoutes: ['/', '/pricing', '/about'], // Routes that require authentication ignoredRoutes: ['/api/webhook'], });
export const config = { matcher: [ '/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)', ], }; ```
Common error #1: Missing middleware.ts
``` Error: Clerk: _useSessionContext must be used within <ClerkProvider> ```
This happens when routes aren't wrapped by middleware. Add the file above.
Step 6: Create Auth Pages (2 minutes)
Clerk provides pre-built UI components. Create app/sign-in/[[...sign-in]]/page.tsx:
```typescript import { SignIn } from '@clerk/nextjs';
export default function Page() { return <SignIn />; } ```
Create app/sign-up/[[...sign-up]]/page.tsx:
```typescript import { SignUp } from '@clerk/nextjs';
export default function Page() { return <SignUp />; } ```
The [[...sign-in]] syntax is Next.js catch-all routing—handles /sign-in, /sign-in/callback, etc.
Step 7: Protect Routes & Access User Data (2 minutes)
Create a protected page at app/dashboard/page.tsx:
```typescript import { currentUser, auth } from '@clerk/nextjs'; import { redirect } from 'next/navigation';
export default async function DashboardPage() { const user = await currentUser(); if (!user) { redirect('/sign-in'); }
return ( <div> <h1>Welcome, {user.firstName}</h1> <p>Email: {user.emailAddresses[0]?.emailAddress}</p> <p>ID: {user.id}</p> </div> ); } ```
Common error #2: Accessing user on client component without proper hook
``` Error: currentUser() can only be used in Server Components or Route Handlers ```
Solution: Use useUser() hook in client components instead:
```typescript 'use client'; import { useUser } from '@clerk/nextjs';
export default function ClientComponent() { const { user, isLoaded } = useUser(); if (!isLoaded) return <div>Loading...</div>; if (!user) return <div>Not signed in</div>; return <div>Welcome, {user.firstName}</div>; } ```
Step 8: Add Sign-Out (Client Component)
Create app/components/UserButton.tsx:
```typescript 'use client'; import { UserButton } from '@clerk/nextjs';
export default function UserButtonComponent() { return <UserButton afterSignOutUrl="/" />; } ```
Use it in your layout:
```typescript import UserButtonComponent from './components/UserButton';
// In your navbar or header: <UserButtonComponent /> ```
Step 9: Test Locally (1 minute)
```bash npm run dev ```
Visit http://localhost:3000/sign-up. You should see Clerk's sign-up form.
Common error #3:
``` Error: Invalid NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY ```
This means your environment variable isn't loaded. Check:
1. File is named .env.local (not .env)
2. Keys match your Clerk dashboard exactly
3. Restart dev server after changing env vars
Production Checklist
.env.production with production keys (in your deployment platform)Real-World Pattern: Protected API Routes
Create app/api/user/route.ts:
```typescript import { auth } from '@clerk/nextjs'; import { NextResponse } from 'next/server';
export async function GET() { const { userId } = auth(); if (!userId) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } return NextResponse.json({ userId, message: 'Authenticated' }); } ```
Call it from your client:
```typescript const response = await fetch('/api/user'); const data = await response.json(); ```
Version Notes
Verify in official docs: Clerk updates frequently. Check [clerk.com/docs/quickstarts/nextjs](https://clerk.com/docs/quickstarts/nextjs) for:
@clerk/nextjsNext Steps
---
What am I missing?
Hit the comments with:
This guide is living—let's keep it accurate together.