Laravel 12 Dashboard Layout Sidebar and Navbar (Bootstrap 5.3)

Laravel 12 Dashboard Layout Sidebar and Navbar (Bootstrap 5.3)

This project demonstrates how to create a Laravel 12 dashboard with a dynamic sidebar and responsive navbar, utilizing Bootstrap 5.3. It features manual login/logout authentication, multi-level menu support, and a clean, maintainable Blade layout.

Step 1: Create a Laravel 12 Project

Open a terminal and run:

composer create-project laravel/laravel laravel-dashboard

Step 2: Set Up Authentication (Manual)

Create manual authentication:

2.1 Create Auth Routes

Edit routes/web.php:

use App\Http\Controllers\AuthController; // Redirect root to login page Route::get('/', function () { return redirect()->route('login'); }); // Login/Logout routes Route::get('/login', [AuthController::class, 'showLoginForm'])->name('login'); Route::post('/login', [AuthController::class, 'login']); Route::post('/logout', [AuthController::class, 'logout'])->name('logout');

2.2 Create AuthController

Create a controller:

php artisan make:controller AuthController

Add inside app/Http/Controllers/AuthController.php:

<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class AuthController extends Controller { // Show login form public function showLoginForm() { return view('auth.login'); } // Handle login post public function login(Request $request) { $credentials = $request->validate([ 'email' => ['required', 'email'], 'password' => ['required'], ]); if (Auth::attempt($credentials)) { $request->session()->regenerate(); return redirect()->intended('dashboard'); } return back()->withErrors([ 'email' => 'The provided credentials do not match our records.', ]); } // Logout user public function logout(Request $request) { Auth::logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect('/login'); } }

2.3 Create Login Blade View

Create a directory:

mkdir -p resources/views/auth

Create file resources/views/auth/login.blade.php:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Login</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" /> </head> <body class="bg-light d-flex align-items-center" style="height: 100vh;"> <div class="container"> <div class="row justify-content-center"> <div class="col-md-4"> <div class="card shadow-sm"> <div class="card-body"> <h3 class="card-title mb-4 text-center">Login</h3> @if ($errors->any()) <div class="alert alert-danger"> <ul class="mb-0"> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form method="POST" action="{{ url('/login') }}"> @csrf <div class="mb-3"> <label for="email" class="form-label">Email address</label> <input type="email" class="form-control" id="email" name="email" value="{{ old('email') }}" required autofocus> </div> <div class="mb-3"> <label for="password" class="form-label">Password</label> <input type="password" class="form-control" id="password" name="password" required> </div> <button type="submit" class="btn btn-primary w-100">Login</button> </form> </div> </div> </div> </div> </div> </body> </html>

Step 3: Create Dashboard and Sidebar Layout Structure

3.1 Create a Folder Structure inside resources/views

mkdir -p resources/views/layouts mkdir -p resources/views/partials

3.2 Create Files:

touch resources/views/layouts/app.blade.php touch resources/views/partials/sidebar.blade.php touch resources/views/partials/navbar.blade.php touch resources/views/dashboard.blade.php

3.3 File Purpose Recap:

  • layouts/app.blade.php — Main layout wrapping navbar, sidebar, and content.

  • partials/sidebar.blade.php — Dynamic sidebar navigation.

  • partials/navbar.blade.php — Top navbar with user info & logout.

  • dashboard.blade.php — Dashboard content page.

Step 4: Create Menu in DashboardController

Create a controller:

php artisan make:controller DashboardController

Add menu and view logic in app/Http/Controllers/DashboardController.php:

<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class DashboardController extends Controller { public function index() { $menuItems = [ [ 'label' => 'Dashboard', 'icon' => 'bi bi-house', 'route' => 'dashboard', ], [ 'label' => 'Users', 'icon' => 'bi bi-people', 'route' => 'users.index', 'children' => [ ['label' => 'All Users', 'route' => 'users.index'], ['label' => 'Add User', 'route' => 'users.create'], ], ], [ 'label' => 'Reports', 'icon' => 'bi bi-graph-up', 'route' => 'reports.index', ], ]; return view('dashboard', compact('menuItems')); } }

Step 5: Define Additional Routes

Add routes for users and reports (for demo, can be placeholders):

// in routes/web.php Route::middleware('auth')->group(function () { Route::get('/dashboard', [App\Http\Controllers\DashboardController::class, 'index'])->name('dashboard'); // Dummy routes for Users and Reports (replace with real controllers later) Route::get('/users', function() { return 'Users list'; })->name('users.index'); Route::get('/users/create', function() { return 'Add user form'; })->name('users.create'); Route::get('/reports', function() { return 'Reports page'; })->name('reports.index'); });
Step 6: Create Sidebar Partial (resources/views/partials/sidebar.blade.php)
<div class="sidebar bg-dark text-white p-3" style="width: 250px; height: 100vh; position: fixed; top: 0; left: 0;"> <h4 class="text-center mb-4">Admin Panel</h4> <ul class="nav flex-column"> @foreach ($menuItems as $item) @php $isActive = request()->routeIs($item['route'] ?? '') || collect($item['children'] ?? [])->pluck('route')->contains(fn($r) => request()->routeIs($r)); @endphp @if (!empty($item['children'])) <li class="nav-item"> <a class="nav-link text-white d-flex justify-content-between {{ $isActive ? '' : 'collapsed' }}" data-bs-toggle="collapse" href="#menu-{{ \Illuminate\Support\Str::slug($item['label']) }}" role="button" aria-expanded="{{ $isActive ? 'true' : 'false' }}" aria-controls="menu-{{ \Illuminate\Support\Str::slug($item['label']) }}"> <span><i class="{{ $item['icon'] }}"></i> {{ $item['label'] }}</span> <i class="bi bi-chevron-down small"></i> </a> <div class="collapse {{ $isActive ? 'show' : '' }}" id="menu-{{ \Illuminate\Support\Str::slug($item['label']) }}"> <ul class="nav flex-column ms-3"> @foreach ($item['children'] as $child) <li> <a href="{{ route($child['route']) }}" class="nav-link text-white {{ request()->routeIs($child['route']) ? 'active fw-bold' : '' }}"> {{ $child['label'] }} </a> </li> @endforeach </ul> </div> </li> @else <li> <a href="{{ route($item['route']) }}" class="nav-link text-white {{ $isActive ? 'active fw-bold' : '' }}"> <i class="{{ $item['icon'] }}"></i> {{ $item['label'] }} </a> </li> @endif @endforeach </ul> </div>
Step 7: Create Navbar Partial (resources/views/partials/navbar.blade.php)
<nav class="navbar navbar-expand-lg navbar-light bg-light ps-3" style="margin-left: 250px;"> <div class="container-fluid"> <span class="navbar-brand">Laravel Dashboard</span> <ul class="navbar-nav ms-auto me-4"> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> {{ auth()->user()->name ?? 'User' }} </a> <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="userDropdown"> <li><a class="dropdown-item" href="#">Profile</a></li> <li> <form method="POST" action="{{ route('logout') }}"> @csrf <button type="submit" class="dropdown-item">Logout</button> </form> </li> </ul> </li> </ul> </div> </nav>
Step 8: Create Main Layout (resources/views/layouts/app.blade.php)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>@yield('title', 'Dashboard')</title> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" /> <!-- Bootstrap Icons --> <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet" /> <style> body { overflow-x: hidden; } .content { margin-left: 250px; padding: 20px; } .sidebar { background-color: #1e293b; /* dark blue-gray background */ color: #fff; width: 250px; height: 100vh; position: fixed; top: 0; left: 0; padding: 1rem; overflow-y: auto; border-right: 1px solid #334155; } .sidebar h4 { font-weight: bold; color: #f8fafc; margin-bottom: 2rem; } .sidebar .nav-link { color: #cbd5e1; font-size: 16px; margin-bottom: 0.5rem; transition: all 0.2s; display: flex; align-items: center; gap: 8px; } .sidebar .nav-link:hover { color: #fff; background-color: #334155; border-radius: 5px; } .sidebar .nav-link.fw-bold { color: #fff; font-weight: bold; } .sidebar .collapse .nav-link { padding-left: 1.5rem; } .sidebar .nav-item .bi-chevron-down { transition: transform 0.3s ease; } .sidebar .nav-item .collapsed .bi-chevron-down { transform: rotate(0deg); } .sidebar .nav-item[aria-expanded="true"] .bi-chevron-down { transform: rotate(180deg); } .sidebar .nav-link.active { background-color: #495057; color: #ffffff !important; border-radius: 5px; } </style> </head> <body> @include('partials.sidebar') <div class="main-content"> @include('partials.navbar') <div class="content"> @yield('content') </div> </div> <!-- Bootstrap JS Bundle --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> </body> </html>
Step 9: Create Dashboard Content (resources/views/dashboard.blade.php)
@extends('layouts.app') @section('title', 'Dashboard') @section('content') <h1>Welcome to your Dashboard</h1> <p>Hello <strong>{{ Auth::user()->name }}</strong>, You are logged in!</p> @endsection

Step 10: Set Up Database and User Model

Open the .env file located at the root of your Laravel project.
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravel_dashboard_db DB_USERNAME=root DB_PASSWORD=

Create a users table and migrate:

php artisan migrate
Example using Tinker:
php artisan tinker
Inside Tinker, paste the following exact code (no line breaks in the wrong place):
\App\Models\User::create([ 'name' => 'Admin User', 'email' => 'admin@example.com', 'password' => bcrypt('password'), ]);

This will create a new user with the hashed password.

To exit Laravel Tinker, just type:

exit

or press Ctrl + D on your keyboard — no semicolon (;) needed.

Step 11: Test Your App

  • Start the Laravel dev server:

php artisan serve

Summary of Folder Structure:

resources/views/ ├── auth/ │ └── login.blade.php # Login form ├── layouts/ │ └── app.blade.php # Main layout with sidebar & navbar ├── partials/ │ ├── navbar.blade.php # Top navbar with user & logout │ └── sidebar.blade.php # Sidebar with dynamic menu └── dashboard.blade.php # Dashboard main page content
Souy Soeng

Souy Soeng

Hi there 👋, I’m Soeng Souy (StarCode Kh)
-------------------------------------------
🌱 I’m currently creating a sample Laravel and React Vue Livewire
👯 I’m looking to collaborate on open-source PHP & JavaScript projects
💬 Ask me about Laravel, MySQL, or Flutter
⚡ Fun fact: I love turning ☕️ into code!

Post a Comment

CAN FEEDBACK
close