🥳 New: 100+ Ready to use Shadcn Pages & Builder Pages Presets, Admin Dashboards & Application Templates.

Visit changelog

Auth Integration

Add Clerk authentication to the shadcn admin dashboard template using the one-click registry install or by wiring the files manually.

What is Clerk?

Clerk is a complete user management and authentication platform for Next.js apps. It adds hosted auth UI, session handling, OAuth providers, MFA, magic links, passkeys, and profile management to the Admin Dashboard Template out of the box.

  • Pre-built UI components like SignIn, SignUp, UserProfile, and UserButton.
  • Server-side auth helpers for App Router, such as auth() and currentUser().
  • Client-side hooks like useUser, useAuth, and useClerk.

Create a Clerk account & application

  1. Go to Clerk Dashboard and sign up or log in.
  2. Click Create application.
  3. Give your app a name, such as my-admin-template.
  4. Choose the sign-in methods you want, such as email/password, Google, or GitHub.
  5. Create the application and keep the API Keys page open.

Environment variables

Add these values from Clerk Dashboard → your application → Configure → API Keys.

File: .env

# Clerk Authentication
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxx
CLERK_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxx

Method 1: One-click install

Use this method when you want the auth files installed by the shadcn registry command. It installs the Clerk package and adds the new auth files for the template.

Command:

pnpm dlx shadcn@latest add https://shadcnstudio.com/r/admin/admin-template-auth.json

After the install finishes, you still need to wire existing project files that the command should not overwrite: provider setup, private layout protection, and header profile rendering.

Method 2: Manual setup

Use this method when you want to add the Clerk files yourself or review every integration point before changing the template. Follow the steps below in order. Each step shows the file name first, then the code you need to add or update.

Step 1: Install SDK - Install the Clerk SDK manually when you are not using the one-click registry command.

Command:

pnpm add @clerk/nextjs

Step 2: Proxy - Add the proxy file so Clerk can read and validate session cookies across the app.

File: src/proxy.ts

import { clerkMiddleware } from '@clerk/nextjs/server'

export default clerkMiddleware()

export const config = {
  matcher: [
    '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
    '/(api|trpc)(.*)'
  ]
}

Step 3: Auth config - Keep login, register, redirect, sidebar, and sign-out URLs in one config file.

File: src/configs/authConfig.ts

export const authConfig = {
  loginUrl: '/login',
  registerUrl: '/register'
} as const

export type AuthConfig = typeof authConfig

Step 4: Provider - Wrap the app with ClerkProvider so Clerk hooks and components work throughout the template.

File: src/components/Providers.tsx

// Third-party Imports
import { ClerkProvider } from '@clerk/nextjs'

const Providers = ({ children }: Props) => {
  return <ClerkProvider>{children}</ClerkProvider>
}

export default Providers

Step 5: Route protection - Use server components so private admin routes render only for signed-in users.

File: src/components/auth/AuthGuard.tsx

import type { ReactNode } from 'react'

import { auth } from '@clerk/nextjs/server'

import AuthRedirect from './AuthRedirect'

export default async function AuthGuard({ children }: { children: ReactNode }) {
  const { userId } = await auth()

  if (!userId) {
    return <AuthRedirect />
  }

  return <>{children}</>
}

File: src/components/auth/AuthRedirect.tsx

'use client'

import { redirect, usePathname } from 'next/navigation'

import { authConfig } from '@/configs/authConfig'
import themeConfig from '@/configs/themeConfig'

const AuthRedirect = () => {
  const pathname = usePathname()
  const redirectUrl = `${authConfig.loginUrl}?redirectTo=${pathname}`

  return redirect(pathname === themeConfig.homePageUrl ? authConfig.loginUrl : redirectUrl)
}

export default AuthRedirect

File: src/components/auth/GuestOnlyRoute.tsx

import type { ReactNode } from 'react'

import { redirect } from 'next/navigation'
import { auth } from '@clerk/nextjs/server'

import themeConfig from '@/configs/themeConfig'

const GuestOnlyRoute = async ({ children }: { children: ReactNode }) => {
  const { userId } = await auth()

  if (userId) {
    redirect(themeConfig.homePageUrl)
  }

  return <>{children}</>
}

export default GuestOnlyRoute

Then wrap the main admin layout so every route inside src/app/(pages) is protected automatically.

Replace the src/app/(pages)/layout.tsx with the following code:

import type { ReactNode } from 'react'

import AuthGuard from '@/components/auth/AuthGuard'
import PagesLayoutClient from '@/components/layout/PagesLayoutClient'

const PagesLayout = ({ children }: Readonly<{ children: ReactNode }>) => {
  return (
    <AuthGuard>
      <PagesLayoutClient>{children}</PagesLayoutClient>
    </AuthGuard>
  )
}

export default PagesLayout

Step 6: Auth pages - Keep login and register pages visible only to signed-out users with GuestOnlyRoute.

File: src/app/(blank)/(auth)/layout.tsx

import type { ReactNode } from 'react'

import GuestOnlyRoute from '@/components/auth/GuestOnlyRoute'
import BlankLayout from '@/components/layout/BlankLayout'

const GuestOnlyLayout = ({ children }: { children: ReactNode }) => {
  return (
    <GuestOnlyRoute>
      <BlankLayout>{children}</BlankLayout>
    </GuestOnlyRoute>
  )
}

export default GuestOnlyLayout

File: src/app/(blank)/(auth)/login/[[...login]]/page.tsx

import { SignIn as ClerkSignInForm } from '@clerk/nextjs'

import { authConfig } from '@/configs/authConfig'
import themeConfig from '@/configs/themeConfig'

const SignInPage = async ({ searchParams }: { searchParams: Promise<{ redirectTo?: string }> }) => {
  const params = await searchParams
  const redirectUrl = params.redirectTo || themeConfig.homePageUrl

  return (
    <ClerkSignInForm
      routing='path'
      path={authConfig.loginUrl}
      signUpUrl={authConfig.registerUrl}
      forceRedirectUrl={redirectUrl}
    />
  )
}

export default SignInPage

File: src/app/(blank)/(auth)/register/[[...register]]/page.tsx

import { SignUp as ClerkSignUpForm } from '@clerk/nextjs'

import { authConfig } from '@/configs/authConfig'
import themeConfig from '@/configs/themeConfig'

const SignUpPage = () => {
  return <ClerkSignUpForm routing='hash' signInUrl={authConfig.loginUrl} forceRedirectUrl={themeConfig.homePageUrl} />
}

export default SignUpPage

Step 7: Header & profile - Use Clerk client hooks for session state, profile data, and sign-out behavior.

File: src/components/layout/Header.tsx

'use client'

import { useAuth } from '@clerk/nextjs'

const Header = () => {
  ...
  const { isSignedIn } = useAuth()

  return (
    <header>
      ...
      {/* activity, notifications, theme toggle */}
      {isSignedIn && <ProfileDropdown />}
    </header>
  )
}

File: src/views/pages/profile/index.tsx

'use client'

import { UserProfile, useUser } from '@clerk/nextjs'

const ProfilePage = () => {
  const { isLoaded, isSignedIn } = useUser()

  if (!isLoaded) return <div>Loading profile...</div>
  if (!isSignedIn) return null

  return <UserProfile />
}

export default ProfilePage

Test the integration

  1. Run the dev server with pnpm dev.
  2. Visit the home page while signed out. You should be redirected to the login page.
  3. Sign in or create an account with the Clerk form.
  4. After sign-in, confirm the dashboard renders and the profile avatar appears in the header.
  5. Sign out from the profile dropdown and confirm you return to the login page.
  6. Visit a private route while signed out and confirm the redirectTo parameter is preserved.
  7. Visit the login page while signed in and confirm GuestOnlyRoute redirects you back to the dashboard.