Next

How to set up Clerk authentication with passkeys in Next.js 16 App Router?

November 28, 2025

download ready
Thank You
Your submission has been received.
We will be in touch and contact you soon!

Clerk handles passkeys natively; wrap app in <ClerkProvider>, use middleware for protected routes.

Example:-

Step 1: Install Package

Code

npm i @clerk/nextjs
      

Step 2: Environment Variables (.env.local)

Code

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
      

Step 3: Root Layout (app/layout.tsx)

Code

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

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <ClerkProvider publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY!}>
      <html lang="en">
        <body>{children}</body>
      </html>
    </ClerkProvider>
  );
}
      

Step 4: Middleware (middleware.ts)

Code

import { authMiddleware } from '@clerk/nextjs/server';

export default authMiddleware({
  publicRoutes: ['/']
});

export const config = {
  matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)']
};
      

Step 5: Protected Page (app/dashboard/page.tsx)

Code

import { UserButton, currentUser } from '@clerk/nextjs/server';

export default async function Dashboard() {
  const user = await currentUser();
  return (
    <div>
      <h1>Welcome {user?.firstName}</h1>
      <UserButton afterSignOutUrl="/" />
    </div>
  );
}
      

Step 6: Enable Passkeys (Clerk Dashboard > Authentication > Passkeys > Enable).

Hire Now!

Need Help with Next Development ?

Work with our skilled next developers to accelerate your project and boost its performance.
**Hire now**Hire Now**Hire Now**Hire now**Hire now

How to set up Clerk authentication with passkeys in Next.js 16 App Router?

Clerk handles passkeys natively; wrap app in <ClerkProvider>, use middleware for protected routes.

Example:-

Step 1: Install Package

Code

npm i @clerk/nextjs
      

Step 2: Environment Variables (.env.local)

Code

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
      

Step 3: Root Layout (app/layout.tsx)

Code

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

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <ClerkProvider publishableKey={process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY!}>
      <html lang="en">
        <body>{children}</body>
      </html>
    </ClerkProvider>
  );
}
      

Step 4: Middleware (middleware.ts)

Code

import { authMiddleware } from '@clerk/nextjs/server';

export default authMiddleware({
  publicRoutes: ['/']
});

export const config = {
  matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)']
};
      

Step 5: Protected Page (app/dashboard/page.tsx)

Code

import { UserButton, currentUser } from '@clerk/nextjs/server';

export default async function Dashboard() {
  const user = await currentUser();
  return (
    <div>
      <h1>Welcome {user?.firstName}</h1>
      <UserButton afterSignOutUrl="/" />
    </div>
  );
}
      

Step 6: Enable Passkeys (Clerk Dashboard > Authentication > Passkeys > Enable).