I was implementing an authentication in my Next.js project with Clerk when I realized some of the syntax that I was using were deprecated.
So I decided to use this chance to document Clerk + Next.js.
Setting Up Clerk
1.Install @clerk/nextjs
npm install @clerk/nextjs
2.Add clerkMiddleware() to app
clerkMiddleware() grants access to user auth state throughout the app
Make middleware.ts and put
import { clerkMiddleware } from '@clerk/nextjs/server'
export default clerkMiddleware()
export const config = {
matcher: [
// Skip Next.js internals and all static files, unless found in search params
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
// Always run for API routes
'/(api|trpc)(.*)',
],
}
3.Add ClerkProvider and Clerk components to your app
In layout.tsx
import { ClerkProvider } from "@clerk/nextjs";
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<ClerkProvider>
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased bg-background`}
>
{children}
</body>
</html>
</ClerkProvider>
);
}
4.Build Sign-in-page
In app/sign-in/[[...sign-in]]/page.tsx
import { SignIn } from '@clerk/nextjs'
export default function Page() {
return <SignIn />
}
5.Making sign-in route public
In middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
const isPublicRoute = createRouteMatcher(['/sign-in(.*)'])
export default clerkMiddleware(async (auth, req) => {
if (!isPublicRoute(req)) {
await auth.protect()
}
})
export const config = {
matcher: [
// Skip Next.js internals and all static files, unless found in search params
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
// Always run for API routes
'/(api|trpc)(.*)',
],
}
This makes only /sign-in public route and rest are private route that cannot be accessed with out credential
6.Update your environmental variables
- Set the CLERK_SIGN_IN_URL environmental variable to tell Clerk where the SignIn component is being hosted
- (I didn't) but set CLERK_SIGN_IN_FALLBACK_REDIRECT_URL as a fallback URL incase iusers visit the /sign-in route directly
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
And with this I quickly implemented my project's authentication 🎉