Next.js

This guide will help you install and initialize Clerk in a new Next.js app.


1. Create a Next.js app

Start by creating a new Next.js app.

npx create-next-app
# or
yarn create next-app

For more information about these commands, please reference the Next.js documentation.


2. Install Clerk

Install Clerk's NPM package.

# From your application's root directory
cd yourapp
npm install @clerk/clerk-react
# or
yarn add @clerk/clerk-react

3. Configure pages/_app.js

Clerk requires every page to be wrapped in the <ClerkProvider> context. In Next.js, we add this in pages/_app.js.

In the code below, we've also added a sign in requirement for every page, unless the page is listed in the publicPages variable.

This is just one example of how authentication can be handled with Clerk. Feel free to adjust the strategy to better serve your use case!

// Contents of pages/_app.js
import "../styles/globals.css";
import { ClerkProvider, SignedIn, SignedOut } from "@clerk/clerk-react";
import { useRouter } from "next/router";
import { useEffect } from "react";
// Replace with your instance settings
const clerkClientHost = "auth.abc123.lcl.dev";
const clerkSignInURL = "https://accounts.abc123.lcl.dev/sign-in";
/**
* List pages you want to be publicly accessible, or leave empty if
* every page requires authentication. Use this naming strategy:
* "/" for pages/index.js
* "/foo" for pages/foo/index.js
* "/foo/bar" for pages/foo/bar.js
* "/foo/[...bar]" for pages/foo/[...bar].js
*/
const publicPages = [];
function MyApp({ Component, pageProps }) {
const router = useRouter();
/**
* If the current route is listed as public, render it directly.
* Otherwise, use Clerk to require authentication.
*/
return (
<ClerkProvider host={clerkClientHost}>
{publicPages.includes(router.pathname) ? (
<Component {...pageProps} />
) : (
<>
<SignedIn>
<Component {...pageProps} />
</SignedIn>
<SignedOut>
<RedirectToSignIn />
</SignedOut>
</>
)}
</ClerkProvider>
);
}
function RedirectToSignIn() {
const router = useRouter();
useEffect(() => {
window.location = clerkSignInURL;
});
return null;
}
export default MyApp;

4. Hello, world!

That's all you need to get started with Clerk. Now you can say hello to your user:

// Contents of hello.js
import { UserButton, useUser } from "@clerk/clerk-react";
export default function Home() {
const { firstName } = useUser();
return (
<>
<header>
<UserButton />
</header>
<main>Hello, {firstName}!</main>
</>
);
}

5. Mount components

By default, Clerk hosts the SignIn, SignUp, and UserProfile components on the "accounts" subdomain for your instance. In production, this will be accounts.yourdomain.com.

If you prefer, you can also "mount" these components directly in your application.

i. Mount SignIn

Create pages/sign-in/[[...index]].js. This uses an optional catch-all route so the page will be used for /sign-in and all of its subpaths.

import { SignIn } from "@clerk/clerk-react";
export default function SignInPage() {
return <SignIn path="/sign-in" routing="path" />;
}

ii. Mount SignUp

Create pages/sign-up/[[...index]].js. This uses an optional catch-all route so the page will be used for /sign-up and all of its subpaths.

import { SignUp } from "@clerk/clerk-react";
export default function SignUpPage() {
return <SignUp path="/sign-up" routing="path" />;
}

iii. Mount UserProfile

Create pages/user/[[...index]].js. This uses an optional catch-all route so the page will be used for /user and all of its subpaths.

import { UserProfile } from "@clerk/clerk-react";
export default function UserProfilePage() {
return <UserProfile path="/user" routing="path" />;
}

iv. Update pages/_app.js

This is the same logic as the first configuration, but with 3 additional changes:

  1. Pass a navigate prop to <ClerkProvider>. This allows Clerk to navigate inside and between components without conflicting with the Next.js router.

  2. Update RedirectToSignIn to use the router's push method instead of window.location.

  3. Set the new SignIn and SignUp pages as publicPages

import "../styles/globals.css";
import { ClerkProvider, SignedIn, SignedOut } from "@clerk/clerk-react";
import { useRouter } from "next/router";
import { useEffect } from "react";
// Replace with your instance settings
const clerkClientHost = "auth.abc123.lcl.dev";
const clerkSignInPath = "/sign-in";
/**
* List pages you want to be publicly accessible, or leave empty if
* every page requires authentication. Use this naming strategy:
* "/" for pages/index.js
* "/foo" for pages/foo/index.js
* "/foo/bar" for pages/foo/bar.js
* "/foo/[...bar]" for pages/foo/[...bar].js
*/
const publicPages = ["/sign-in/[[...index]]", "/sign-up/[[...index]]"];
function MyApp({ Component, pageProps }) {
const router = useRouter();
/**
* If the current route is listed as public, render it directly.
* Otherwise, use Clerk to require authentication.
*/
return (
<ClerkProvider host={clerkClientHost} navigate={(to) => router.push(to)}>
{publicPages.includes(router.pathname) ? (
<Component {...pageProps} />
) : (
<>
<SignedIn>
<Component {...pageProps} />
</SignedIn>
<SignedOut>
<RedirectToSignIn />
</SignedOut>
</>
)}
</ClerkProvider>
);
}
function RedirectToSignIn() {
const router = useRouter();
useEffect(() => {
router.push(clerkSignInPath);
});
return null;
}
export default MyApp;

v. Update instance settings

The final step is to update your instance settings so that users will be defaulted to your mounted components instead of the "accounts" subdomain.

Dashboard update instructions coming soon.