For most Next.js applications, Clerk is the right choice for authentication. It handles sign-in, sign-up, multi-factor authentication, session management, and organization management with pre-built UI that looks good and works correctly. You ship auth in hours instead of weeks.
What Clerk Provides
Clerk is a complete authentication and user management platform. Unlike authentication libraries that give you primitives to build on, Clerk gives you finished, hosted components and a management dashboard.
Pre-built UI components. Clerk's <SignIn /> and <SignUp /> components are fully functional, customizable authentication forms. They handle email/password, magic link, and social login (Google, GitHub, Twitter/X, Discord, and more) out of the box. The components match your brand via a dashboard theme editor. You embed them in your Next.js pages and they work.
Session management. Clerk manages JWT sessions automatically. The session token is stored in a cookie and verified on each request. You do not need to write any token management code.
Multi-factor authentication. TOTP, SMS, and backup codes are supported and configurable from the Clerk dashboard. No code changes required.
Organization management. Clerk has first-class support for multi-tenant applications. Organizations have members, each member has a role, and you can configure custom roles with permissions. Invitations, member management, and organization switching are handled by Clerk's pre-built components.
User management dashboard. The Clerk dashboard shows all users, their login history, linked devices, and active sessions. You can impersonate users, delete accounts, and manage individual sessions without building any admin tooling.
Setup in Next.js
Install Clerk and wrap your app:
npm install @clerk/nextjs
Add your keys to .env.local:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
Wrap your layout with ClerkProvider:
import { ClerkProvider } from "@clerk/nextjs";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<ClerkProvider>
<html lang="en">
<body>{children}</body>
</html>
</ClerkProvider>
);
}
Protect routes in middleware:
import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server";
const isPublicRoute = createRouteMatcher(["/", "/sign-in(.*)", "/sign-up(.*)"]);
export default clerkMiddleware((auth, req) => {
if (!isPublicRoute(req)) {
auth().protect();
}
});
Access the current user in Server Components:
import { currentUser } from "@clerk/nextjs/server";
export default async function Page() {
const user = await currentUser();
return <div>Hello, {user?.firstName}</div>;
}
Access user state in Client Components:
"use client";
import { useUser, useAuth } from "@clerk/nextjs";
export function ProfileButton() {
const { user } = useUser();
const { signOut } = useAuth();
return <button onClick={() => signOut()}>{user?.firstName}</button>;
}