Subscribe
12 March, 2026 5 min read Aigars Silkalns

How to Build an Admin Dashboard with shadcn/ui and Next.js (2026 Guide)

Building an admin dashboard from scratch used to mean weeks of work on layout, navigation, data tables, and form components. With shadcn/ui and Next.js, you can scaffold a production-ready admin panel in hours — with accessible components, server-side rendering, and type safety built in.

This guide walks you through the key decisions, architecture patterns, and tools for building an admin dashboard with shadcn/ui and Next.js in 2026. Whether you’re starting from a template or building custom, these are the patterns that work in production. For ready-made options, browse our curated list of shadcn/ui templates that implement many of these patterns out of the box.

Why shadcn/ui + Next.js?

This stack has become the default choice for new React admin dashboards in 2026, and for good reason:

  • You own the component code. shadcn/ui copies components into your project as local TypeScript files. No dependency version conflicts, no fighting library opinions, no breaking changes on upgrade.
  • Radix UI accessibility. Every shadcn component is built on Radix UI primitives with WAI-ARIA compliance, keyboard navigation, and focus management — critical for enterprise admin tools.
  • Next.js App Router. Server Components reduce client-side JavaScript, middleware handles auth and permissions, and the file-based routing maps naturally to admin panel pages.
  • Tailwind CSS styling. Utility classes mean fast iteration without CSS-in-JS runtime overhead. Theme customization via CSS variables.

Step 1: Project Setup

The fastest way to start is with the shadcn CLI:

npx create-next-app@latest my-admin --typescript --tailwind --eslint --app --src-dir
cd my-admin
npx shadcn@latest init

The shadcn init command configures Tailwind CSS, adds a components.json file, and sets up the lib/utils.ts helper with the cn() function for merging class names. Choose the “Default” style and your preferred base color.

Then add the components you’ll need for a dashboard:

npx shadcn@latest add sidebar navigation-menu table card chart button input dialog sheet command dropdown-menu avatar badge separator

Step 2: Dashboard Layout Architecture

The standard admin dashboard layout uses Next.js nested layouts with a sidebar + main content area:

app/
├── (auth)/
│   ├── login/page.tsx
│   └── layout.tsx          # No sidebar
├── (dashboard)/
│   ├── layout.tsx          # Sidebar + header
│   ├── page.tsx            # Main dashboard
│   ├── users/page.tsx
│   ├── settings/page.tsx
│   └── analytics/page.tsx
└── layout.tsx              # Root layout

The route group (dashboard) shares a layout with a collapsible sidebar, while (auth) uses a centered layout without navigation. This pattern avoids layout flash when navigating between dashboard pages.

shadcn/ui’s Sidebar component (added in late 2024) provides a production-ready collapsible sidebar with mobile sheet fallback, keyboard shortcuts, and persistent state via cookies. Use it instead of building your own:

// app/(dashboard)/layout.tsx
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
import { AppSidebar } from "@/components/app-sidebar"

export default function DashboardLayout({ children }) {
  return (
    <SidebarProvider>
      <AppSidebar />
      <main className="flex-1">
        <SidebarTrigger />
        {children}
      </main>
    </SidebarProvider>
  )
}

Step 3: Data Tables with TanStack Table

The shadcn DataTable component wraps TanStack Table v8 with proper TypeScript generics. For admin dashboards, you’ll want server-side pagination, sorting, and filtering:

// Define columns with type safety
const columns: ColumnDef<User>[] = [
  { accessorKey: "name", header: "Name" },
  { accessorKey: "email", header: "Email" },
  { accessorKey: "role", header: "Role",
    cell: ({ row }) => <Badge>{row.getValue("role")}</Badge>
  },
  { id: "actions",
    cell: ({ row }) => <UserActions user={row.original} />
  },
]

For server-side operations, use searchParams in your page component to pass pagination and filter state to your database query. This keeps the URL bookmarkable and shareable — essential for admin tools where users share links to filtered views.

Step 4: Authentication & Authorization

Admin dashboards need auth with role-based access. The three most popular options in the shadcn/Next.js ecosystem:

Solution Type Best For
Clerk Hosted service Fastest setup, organizations, RBAC, SSO
Auth.js (NextAuth) Self-hosted library Full control, multiple OAuth providers, JWT/DB sessions
Better Auth Self-hosted library New alternative to Auth.js with simpler API, 2FA, passkeys

For most admin dashboards, Clerk gets you to production fastest — organizations, role management, impersonation, and audit logs are built in. For self-hosted requirements (HIPAA, data residency), Auth.js or Better Auth give you full control.

Protect routes using Next.js middleware:

// middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'

const isProtectedRoute = createRouteMatcher(['/dashboard(.*)'])

export default clerkMiddleware(async (auth, req) => {
  if (isProtectedRoute(req)) await auth.protect()
})

Step 5: Charts & Data Visualization

shadcn/ui includes a Chart component built on Recharts. For admin dashboards, combine it with Card components for KPI displays:

<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
  <Card>
    <CardHeader>
      <CardTitle>Total Revenue</CardTitle>
    </CardHeader>
    <CardContent>
      <div className="text-2xl font-bold">$45,231</div>
      <p className="text-muted-foreground">+20.1% from last month</p>
    </CardContent>
  </Card>
  {/* More KPI cards */}
</div>

<ChartContainer config={chartConfig}>
  <BarChart data={revenueData}>
    <Bar dataKey="revenue" fill="var(--color-revenue)" />
  </BarChart>
</ChartContainer>

For more advanced visualizations (real-time charts, complex dashboards), consider Tremor — a dashboard-focused component library built on the same Radix + Tailwind foundation as shadcn/ui.

Step 6: Command Palette (Cmd+K)

The Command component (based on cmdk) gives your admin panel a Spotlight-style search. Users can navigate between pages, search users, and trigger actions without reaching for the mouse:

npx shadcn@latest add command dialog

Wire it to Cmd+K / Ctrl+K with a global keyboard listener. Populate the command list with your admin routes and searchable entities. This single feature dramatically improves admin dashboard usability for power users.

Step 7: Dark Mode & Theming

shadcn/ui uses CSS variables for theming. Add next-themes for dark mode toggle:

npm install next-themes

Wrap your root layout with ThemeProvider and add a toggle button. All shadcn components automatically adapt to dark mode through the CSS variables defined in your globals.css. Custom colors can be changed by modifying the HSL values in the :root and .dark selectors.

Skip the Setup: Use a Template

If building from scratch isn’t the right call for your timeline, these templates implement everything above:

  • next-shadcn-dashboard-starter (6,000+ stars) — Free. Next.js 16, Clerk auth, TanStack Tables, kanban, 6+ themes, RBAC. The most popular option.
  • DashboardPack Zenith — Premium. Achromatic design, 50+ pages, 6 dashboard variants. Also available as Laravel 12 + Inertia.js.
  • DashboardPack Apex — Premium. Comprehensive component library, dark/light themes. Laravel version includes Spatie permissions.
  • next-forge (6,900+ stars) — Free. Full monorepo with app, docs, email, API, and Storybook. Opinionated but production-ready.

All of these templates use the same shadcn/ui + Next.js + Tailwind CSS foundation described in this guide. For a broader selection, see our full roundup of Next.js admin templates including options beyond shadcn/ui. The patterns are interchangeable — learn them once and you can work with any shadcn-based dashboard.

Production Checklist

Before shipping your shadcn/ui admin dashboard (and if you’re still evaluating options, our guide on how to choose an admin dashboard template can help narrow your decision):

  • Middleware auth protection — Every dashboard route must require authentication.
  • Role-based access — Different roles see different navigation items and have different permissions.
  • Loading states — Use React Suspense boundaries and shadcn Skeleton components for server-fetched data.
  • Error boundaries — Add error.tsx files in route segments to catch and display errors gracefully.
  • Responsive design — The sidebar should collapse to a sheet on mobile. Test at 768px breakpoint.
  • Keyboard navigation — Tab order, focus management, and the command palette should work without a mouse.
  • Audit logging — Track who changed what and when. Use middleware or database triggers.

Comments (No Comments)

Add Your Comment