Building a Responsive Admin Dashboard in Next.js
A clean, functional admin dashboard is the heart of any SaaS app. It’s where you (and your users) manage customers, view analytics, handle billing, and monitor health all while feeling fast and modern.
This guide shows you how to build a fully responsive admin dashboard in Next.js 16+ using React Server Components, Tailwind CSS, and shadcn/ui the exact pattern shipped in SaaSJet. By the end, you’ll have protected routes, sidebar navigation, dark mode support, and reusable components ready for production.
Why This Dashboard Setup Wins for SaaS
- Server Components by default → Faster loads, less client JS
- Fully responsive → Works perfectly on mobile & desktop
- Accessible & beautiful → Built with shadcn/ui + Tailwind
- Easy to extend → Add charts, tables, modals in minutes
- Protected out of the box → Role-based guards included
Step 1: Protected Dashboard Layout
Create a layout that wraps all admin routes:
// src/app/(dashboard)/layout.tsx
import { Sidebar } from '@/components/sidebar';
import { auth } from '@/lib/auth';
export default async function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
const session = await auth.api.getSession();
if (!session.user) {
redirect('/sign-in');
}
// Optional: Admin-only guard
// if (session.user.role !== 'admin') notFound();
return (
<div className="flex h-screen bg-gray-50 dark:bg-[#0D0D0D]">
<Sidebar user={session.user} />
<main className="flex-1 overflow-y-auto p-4 md:p-8">
{children}
</main>
</div>
);
}
Step 2: Responsive Sidebar Navigation
// src/components/sidebar.tsx
'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { Home, Users, CreditCard, Settings, BarChart3 } from 'lucide-react';
const navItems = [
{ name: 'Overview', href: '/dashboard', icon: Home },
{ name: 'Users', href: '/dashboard/users', icon: Users },
{ name: 'Billing', href: '/dashboard/billing', icon: CreditCard },
{ name: 'Analytics', href: '/dashboard/analytics', icon: BarChart3 },
{ name: 'Settings', href: '/dashboard/settings', icon: Settings },
];
export function Sidebar({ user }: { user: any }) {
const pathname = usePathname();
return (
<aside className="w-64 border-r border-gray-200 dark:border-gray-800 bg-white dark:bg-[#111111] hidden md:block">
<div className="p-6">
<h2 className="text-2xl font-bold text-gray-900 dark:text-white">SaaSJet</h2>
<p className="text-sm text-gray-600 dark:text-gray-400 mt-1">{user.email}</p>
</div>
<nav className="px-4">
{navItems.map((item) => (
<Link
key={item.href}
href={item.href}
className={`flex items-center gap-3 px-4 py-3 rounded-lg mb-1 transition-colors ${
pathname === item.href
? 'bg-blue-500/10 text-blue-600 dark:text-blue-400'
: 'text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800'
}`}
>
<item.icon className="w-5 h-5" />
<span className="font-medium">{item.name}</span>
</Link>
))}
</nav>
</aside>
);
}
Step 3: Key Dashboard Pages
Overview Page with Stats
// src/app/(dashboard)/page.tsx
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
export default async function Overview() {
// Fetch real data from Prisma or external APIs
const stats = {
revenue: '$12,450',
users: '1,234',
growth: '+23%',
activeSubs: '892',
};
return (
<>
<h1 className="text-3xl font-bold text-gray-900 dark:text-white mb-8">Overview</h1>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
<Card>
<CardHeader>
<CardTitle className="text-sm font-medium text-gray-600 dark:text-gray-400">
Total Revenue
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-2xl font-bold text-gray-900 dark:text-white">{stats.revenue}</p>
<p className="text-sm text-green-600 dark:text-green-400">+12% from last month</p>
</CardContent>
</Card>
{/* Repeat for users, growth, active subs */}
</div>
</>
);
}
Users Table with Search & Pagination
Use shadcn/ui Data Table component pre-styled, sortable, and responsive.
Billing Overview
Show subscription tiers, recent transactions, and customer portal link.
Step 4: Mobile-Friendly Improvements
- Add a mobile hamburger menu toggle
- Collapse sidebar on small screens
- Use responsive grid classes (
grid-cols-1 md:grid-cols-2 lg:grid-cols-4)
Final Tips for a Pro Dashboard
- Use Recharts or Tremor for analytics charts
- Add dark mode toggle (next-themes)
- Implement real-time updates with Server Sent Events (optional)
- Always protect routes server-side (never trust client)
That's It!
You now have a modern, responsive admin dashboard that's fast, secure, and easy to extend perfect for managing your growing SaaS.
SaaSJet ships with all of this pre-built: sidebar, protected routes, overview stats, users table, and billing views ready for your branding and data.
Build this faster with SaaSJet → clone the repo saasjet
Happy coding! Published: January 28, 2026