patterntypescriptMajor
Clerk Integration in Next.js App Router
Viewed 0 times
@clerk/nextjs v4
clerknext.jsauthMiddlewareClerkProviderauth()currentUserpublicRoutes
Error Messages
Problem
Integrating Clerk with App Router requires correctly layering ClerkProvider, authMiddleware, and server-side auth() helpers. Missing any piece results in session not being available in Server Components or protected routes being publicly accessible.
Solution
Wrap the root layout with ClerkProvider. Export authMiddleware from middleware.ts with publicRoutes defined. Use auth() or currentUser() in Server Components and useAuth() / useUser() in Client Components.
Why
Clerk uses an edge-compatible middleware that forwards session tokens to Server Components via request headers. ClerkProvider propagates session state to client components via React context.
Gotchas
- NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY must both be set — missing the secret key causes server-side auth() to return null
- Routes listed in publicRoutes still run the middleware but skip authentication requirements — don't confuse with ignoredRoutes which skip Clerk entirely
- auth() in App Router Server Components is synchronous in Clerk v4 but async in v5 — check your version
Code Snippets
middleware.ts with Clerk
import { authMiddleware } from '@clerk/nextjs';
export default authMiddleware({
publicRoutes: ['/', '/sign-in(.*)', '/sign-up(.*)'],
});
export const config = {
matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
};Server Component using auth()
import { auth, currentUser } from '@clerk/nextjs';
export default async function DashboardPage() {
const { userId } = auth();
if (!userId) redirect('/sign-in');
const user = await currentUser();
return <div>Hello, {user?.firstName}</div>;
}Revisions (0)
No revisions yet.