Use Clerk with Next.js
Learn how to use Clerk to quickly and easily add secure authentication and user management to your Next.js application. Clerk works seamlessly in both client side and server side components.
Install @clerk/nextjs
Once you have a Next.js application ready, you need to install Clerk's Next.js SDK. This gives you access to prebuilt components and hooks, as well as helpers for Next.js API routes, server-side rendering, and middleware.
terminalnpm install @clerk/nextjs
terminalyarn add @clerk/nextjs
terminalpnpm add @clerk/nextjs
Set environment keys
Below is an example of an .env.local
file. If you are signed into your Clerk Dashboard, your keys should become visible by clicking on the eye icon.
.env.localNEXT_PUBLIC_CLERK_PUBLISHABLE_KEY={{pub_key}} CLERK_SECRET_KEY={{secret}}
Mount <ClerkProvider />
Add the <ClerkProvider />
wrapper to your application. The <ClerkProvider />
component wraps your Next.js application to provide active session and user context to Clerk's hooks and other components. A reasonable default approach is to have <ClerkProvider />
wrap the <body/>
to enable the context to be accessible anywhere within the app.
The <ClerkProvider />
component needs to access headers to authenticate correctly. This means anything wrapped by the provider will be opted into dynamic rendering at request time. If you have static-optimized or ISR pages that you would prefer not to be opted into dynamic rendering, make sure they are not wrapped by <ClerkProvider />
.
This is easiest to accomplish by ensuring that <ClerkProvider />
is added further down the tree to wrap route groups that explicitly need authentication instead of having the provider wrap your application root as recommended above. For example, if your project includes a set of landing/marketing pages as well as a dashboard that requires login, you would create separate (marketing)
and (dashboard)
route groups. Adding <ClerkProvider />
to the (dashboard)/layout.jsx
layout file will ensure that only those routes are opted into dynamic rendering, allowing the marketing routes to be statically optimized.
app/layout.tsximport { ClerkProvider } from '@clerk/nextjs' export const metadata = { title: 'Next.js 13 with Clerk', } export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( <ClerkProvider> <html lang="en"> <body>{children}</body> </html> </ClerkProvider> ) }
_app.tsximport { ClerkProvider } from "@clerk/nextjs"; import type { AppProps } from "next/app"; function MyApp({ Component, pageProps }: AppProps) { return ( <ClerkProvider {...pageProps}> <Component {...pageProps} /> </ClerkProvider> ); } export default MyApp;
The root layout is a server component. If you plan to use the <ClerkProvider />
outside the root layout, it will need to be a server component as well.
Protect your application
Now that Clerk is installed and mounted in your application, it’s time to decide which pages are public and which need to hide behind authentication. We do this by creating a middleware.ts
file at the root folder (or inside src/
if that is how you set up your app).
middleware.tsimport { authMiddleware } from "@clerk/nextjs"; // This example protects all routes including api/trpc routes // Please edit this to allow other routes to be public as needed. // See https://clerk.com/docs/references/nextjs/auth-middleware for more information about configuring your middleware export default authMiddleware({}); export const config = { matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'], };
With this middleware, your entire application is protected. If you try to access it, the middleware will redirect you to your Sign Up page. If you want to make other routes public, check out the authMiddleware reference page.
At this point, your application is fully protected by Clerk and uses Clerk's Account Portal pages that are available out of box.
Start your Next.js application via npm run dev
, visit http://localhost:3000
, and sign up to get access to your application.
Build your own sign in and sign up pages
In addition to the Account Portal, Clerk also offers a set of prebuilt components that you can use instead to embed sign in, sign up, and other user management functions into your Next.js application. We are going to use the <SignIn />
and <SignUp />
components by utilizing the Next.js optional catch-all route.
Build your sign up page
app/sign-up/[[...sign-up]]/page.tsximport { SignUp } from "@clerk/nextjs"; export default function Page() { return <SignUp />; }
/pages/sign-up/[[...index]].tsximport { SignUp } from "@clerk/nextjs"; export default function Page() { return <SignUp />; }
Build your sign in page
app/sign-in/[[...sign-in]]/page.tsximport { SignIn } from "@clerk/nextjs"; export default function Page() { return <SignIn />; }
/pages/sign-in/[[...index]].tsximport { SignIn } from "@clerk/nextjs"; export default function Page() { return <SignIn />; }
By default, the Clerk components inherit the font family. create-next-app
does not apply a global font family. When you launch your application, you may notice that the font family is different.
Update your environment variables
Next, add environment variables for the signIn
, signUp
, afterSignUp
, and afterSignIn
paths:
.env.localNEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/ NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/
These values control the behavior of the components when you sign in or sign up and when you click on the respective links at the bottom of each component.
Embed the <UserButton />
The <UserButton />
allows users to manage their account information and log out, thus allowing you to complete a full authentication circle.
You can add it anywhere you want, but next to the logo in your main application page is a good start.
app/page.tsximport { UserButton } from "@clerk/nextjs"; export default function Home() { return ( <div> <UserButton afterSignOutUrl="/"/> </div> ) }
pages/example.tsximport { UserButton } from "@clerk/nextjs"; export default function Example() { return ( <> <header> <UserButton afterSignOutUrl="/"/> </header> <div>Your page's content can go here.</div> </> ); }
Sign up for your application
Now start your Next.js application via npm run dev
, visit http://localhost:3000
, and sign up to get access to your application.
Read session and user data
Clerk provides a set of hooks and helpers that you can use to access the active session and user data in your Next.js application. Here are examples of how to use these helpers in both the client and server side to get you started.
Client side
useAuth
The useAuth
hook is a convenient way to access the current auth state. This hook provides the minimal information needed for data-loading and helper methods to manage the current active session.
example.tsx"use client"; import { useAuth } from "@clerk/nextjs"; export default function Example() { const { isLoaded, userId, sessionId, getToken } = useAuth(); // In case the user signs out while on the page. if (!isLoaded || !userId) { return null; } return ( <div> Hello, {userId} your current active session is {sessionId} </div> ); }
useUser
The useUser
hook is a convenient way to access the current user data where you need it. This hook provides the user data and helper methods to manage the current active session.
example.tsx"use client"; import { useUser } from "@clerk/nextjs"; export default function Example() { const { isLoaded, isSignedIn, user } = useUser(); if (!isLoaded || !isSignedIn) { return null; } return <div>Hello, {user.firstName} welcome to Clerk</div>; }
Server side
API Routes
You can protect your API routes by using the getAuth
helper and retrieve data from your own systems.
pages/api/auth.tsimport type { NextApiRequest, NextApiResponse } from "next"; import { getAuth } from "@clerk/nextjs/server"; export default function handler(req: NextApiRequest, res: NextApiResponse) { const { userId } = getAuth(req); if (!userId) { res.status(401).json({ error: "Unauthorized" }); return; } // retrieve data from your database res.status(200).json({}); }
In some cases, you may need the full User
object. For example, if you want to access the user's email address or name. You can use the clerkClient
helper to get the full User
object.
pages/api/auth.tsimport { clerkClient } from "@clerk/nextjs"; import { getAuth } from "@clerk/nextjs/server"; import type { NextApiRequest, NextApiResponse } from "next"; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { const { userId } = getAuth(req); if (!userId) { return res.status(401).json({ error: "Unauthorized" }); } const user = userId ? await clerkClient.users.getUser(userId) : null; // use the user object to decide what data to return return res.status(200).json({}); }
Server side render user data
currentUser()
currentUser()
loads the User
object for the authenticated user from Clerk's backend API. This is helpful if you want to render information, like their first and last name, directly from the server.
Under the hood, this calls fetch()
so it is automatically deduped per request.
page.tsximport { currentUser } from "@clerk/nextjs"; import type { User } from "@clerk/nextjs/api"; export default async function Page() { const user: User | null = await currentUser(); // ... }
auth()
Clerk has introduced a new auth()
helper that returns the same Authentication
Object as getAuth(req)
in middleware, getServerSideProps, and API routes.
Since request data like headers()
and cookies()
is now available in the global scope for Next.js, you no longer need to explicitly pass a Request
object to Clerk.
app/page.tsximport { auth } from "@clerk/nextjs"; export default function Page() { const { userId } = auth(); // ... }
You can access the active session and user data in your getServerSideProps
using the getAuth
helper.
Please note the addition of buildClerkProps in the return statement, which informs our React helpers of the authentication state during server-side rendering (like useAuth()
, <SignedIn>
, and <SignedOut>
).
pages/example.tsximport { getAuth, buildClerkProps } from "@clerk/nextjs/server"; import { GetServerSideProps } from "next"; export const getServerSideProps: GetServerSideProps = async (ctx) => { const { userId } = getAuth(ctx.req); if (!userId) { // handle user is not logged in. } // Load any data your application needs for the page using the userId return { props: { ...buildClerkProps(ctx.req) } }; };
You can also access the full user object before passing it to the page using the clerkClient
helper.
pages/example.tsximport { clerkClient } from "@clerk/nextjs"; import { getAuth, buildClerkProps } from "@clerk/nextjs/server"; import { GetServerSideProps } from "next"; export const getServerSideProps: GetServerSideProps = async (ctx) => { const { userId } = getAuth(ctx.req); const user = userId ? await clerkClient.users.getUser(userId) : undefined; return { props: { ...buildClerkProps(ctx.req, { user }) } }; };
Next steps
Now that your Next.js application is integrated with Clerk, you will want to read the following documentation:
Customization & Localization
Learn how to customize and localize the Clerk components.
Learn More
Authentication Components
Learn more about all our authentication components.
Learn More
Client Side Helpers
Learn more about our client side helpers and how to use them.
Learn More
Next.js SDK Reference
Learn more about additional Next.js methods.
Learn More