💡 This tutorial is explained step-by-step in the video above—watch if you want the full breakdown with visuals.
Introduction
Modern admin dashboard built with Next.js and Tailwind CSS, offering responsive UI and smooth user experience.
Project Installation
npx create-next-app@latest admin-dashboard
During Installation
- ✅ Would you like to use TypeScript? press Yes.
- ✅ Which linter would you like to use? press ESLint.
- ❌ Would you like to use Tailwind CSS? press No.
- ✅ Would you like your code inside a `src/` directory? press Yes.
- ✅ Would you like to use App Router? press Yes .
- ❌ Would you like to use Turbopack? press No.
- ❌ Would you like to customize the import alias (`@/*` by default)? press No.
Then run this commands to install Tailwind CSS and lucide-react
cd admin-dashboard
npm install tailwindcss@3.4.3 postcss@8.4.38 autoprefixer@10.4.19
npm install lucide-react
npx tailwindcss init -p
Add this to tailwind.config.js file
content: [
'./src/**/*.{js,ts,jsx,tsx}',
'./app/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
]
Add this to the top of globals.css file in /app folder
@tailwind base;
@tailwind components;
@tailwind utilities;
Write this code in /app/layout.tsx file
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" dir="ltr">
<body className="h-screen">
{children}
</body>
</html>
);
}
Add the following code to the /app/page.tsx file
import Link from "next/link";
export default function Home() {
return (
<div>
<Link href="/dashboard"
className="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded">Go to dashboard</Link>
</div>
);
}
In the /app directory, create a folder named dashboard. Inside it, add two files: layout.tsx and page.tsx
Add the following code to the /app/dashboard/layout.tsx file
"use client";
import { useState } from "react";
import Link from "next/link";
import Image from "next/image";
import { LayoutDashboard, Users, UserCircle, ChevronDown
,User, Settings, LogOut
} from "lucide-react";
export default function DashboardLayout({ children } : { children: React.ReactNode }){
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
return (
<div className="flex h-screen bg-gray-300">
<aside className="fixed inset-y-0 left-0 w-64 bg-gray-900 text-white
flex flex-col transform transition-transform duration-300
z-20 md:translate-x-0 md:static">
<div className="p-[20px] text-2xl font-bold border-b border-gray-700
flex justify-between items-center">
Admin Dashboard
</div>
<nav className="flex-1 p-4 space-y-2">
<Link
href="/dashboard"
className="flex items-center gap-2 px-4 py-2 rounded">
<LayoutDashboard size={18} />
Dashboard
</Link>
<Link
href="/dashboard/staff"
className="flex items-center gap-2 px-4 py-2 rounded">
<Users size={18} />
Staff
</Link>
<Link
href="/dashboard/clients"
className="flex items-center gap-2 px-4 py-2 rounded">
<UserCircle size={18} />
Clients
</Link>
</nav>
</aside>
<div className="flex-1 flex flex-col">
<nav className="bg-white shadow-md px-4 py-[12px] flex items-center">
<div className="flex-1" />
<div className="relative flex items-center gap-2">
<button
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
className="flex items-center gap-2 px-2 py-1 rounded-full
focus:outline-none">
<div
className="w-10 h-10 rounded-full overflow-hidden relative">
<Image
src="/images/profile-image.jpg"
alt="avatar"
fill
className="object-cover" />
</div>
<span className="font-medium text-blue-700 hidden sm:inline">Todik</span>
<ChevronDown size={18} />
</button>
{isDropdownOpen && (
<div className="absolute right-0 mt-48 w-40 bg-white border
border-gray-200 rounded-md shadow-lg py-1 z-30">
<Link
href="/dashboard/profile"
onClick={() => setIsDropdownOpen(false)}
className="flex items-center gap-2 w-full text-left
px-4 py-2 hover:bg-gray-100"
>
<User size={18} />
Profile
</Link>
<Link
href="/dashboard/settings"
onClick={() => setIsDropdownOpen(false)}
className="flex items-center gap-2 w-full text-left
px-4 py-2 hover:bg-gray-100"
>
<Settings size={18} />
Settings
</Link>
<button
onClick={() => setIsDropdownOpen(false)}
className="flex items-center gap-2 w-full text-left
px-4 py-2 hover:bg-gray-100"
>
<LogOut size={18} />
Logout
</button>
</div>
)}
</div>
</nav>
<main className="flex-1 overflow-auto">{children}</main>
</div>
</div>
)
}
Add the following code to the /app/dashboard/page.tsx file
export default function DashboardHome() {
return(
<h1 className="text-3xl text-red-500">Dashboard home page</h1>
)
}
Inside /app/dashboard, create four folders: staff, clients, profile, and settings. Then, add a page.tsx file in each folder
Add the following code to the /app/dashboard/staff/page.tsx file
export default function Staff(){
return (
<h1 className="text-3xl text-red-500">Staff page</h1>
)
}
Add the following code to the /app/dashboard/clients/page.tsx file
export default function Clients(){
return(
<h1 className="text-3xl text-red-500">Clients page</h1>
)
}
Add the following code to the /app/dashboard/profile/page.tsx file
export default function Profile(){
return(
<h1 className="text-3xl text-red-500">Profile page</h1>
)
}
Add the following code to the /app/dashboard/settings/page.tsx file
export default function Settings(){
return (
<h1 className="text-3xl text-red-500">Settings page</h1>
)
}
Now run this command and enjoy Admin Dashboard
npm run dev
github
git clone https://github.com/todik50/admin-dashboard.git