How to Build an Admin Dashboard in Next.js with Tailwind CSS

💡 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