This project replicates Django-style admin features in a Laravel 10+ app using Laravel Breeze (Blade stack), Spatie Laravel-Permission for role-based access, and custom admin views.
- Laravel Breeze authentication with Blade and Tailwind
- Role-based access control (admin vs. normal users)
- Protected admin dashboard
- User management panel with paginated list and role display
- Clean, extensible structure (can be expanded to include create/edit/delete, etc.)
- Laravel 10+
- Laravel Breeze (Blade + Alpine.js)
- Tailwind CSS (via Vite)
- Spatie Laravel-Permission
- MySQL
- PHP 8.1+
- Composer
- Node.js v18+
- MySQL
- Laravel CLI (
composer global require laravel/installer)
# Clone your repo or start a new Laravel project
laravel new laravel-admin
cd laravel-admin
# Install Breeze
composer require laravel/breeze --dev
php artisan breeze:install blade
npm install && npm run dev
# Configure .env
cp .env.example .env
php artisan key:generate
Update .env database values:
DB_DATABASE=laravel_admin
DB_USERNAME=laravel_user
DB_PASSWORD=secret
Create the DB and user:
CREATE DATABASE laravel_admin;
CREATE USER 'laravel_user'@'localhost' IDENTIFIED BY 'secret';
GRANT ALL PRIVILEGES ON laravel_admin.* TO 'laravel_user'@'localhost';
FLUSH PRIVILEGES;
Then run:
php artisan migrate
php artisan serve
Visit: http://localhost:8000
🔐 Admin Role Setup
Install Spatie's permission package:
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\\Permission\\PermissionServiceProvider"
php artisan migrate
Assign the admin role:
php artisan tinker
use Spatie\Permission\Models\Role;
use App\Models\User;
Role::create(['name' => 'admin']);
$user = \App\Models\User::find(1); // replace with your user ID
$user->assignRole('admin');
🧭 Admin Routes
In routes/web.php:
use App\Http\Controllers\AdminDashboardController;
use App\Http\Controllers\Admin\AdminUserController;
Route::middleware(['auth', 'role:admin'])->prefix('admin')->group(function () {
Route::get('/dashboard', [AdminDashboardController::class, 'index'])->name('admin.dashboard');
Route::resource('users', AdminUserController::class)->names('admin.users');
});
📂 Admin Controllers & Views
1. Admin Dashboard
php artisan make:controller AdminDashboardController
// app/Http/Controllers/AdminDashboardController.php
public function index() {
return view('admin.dashboard');
}
Create the view:
mkdir -p resources/views/admin
touch resources/views/admin/dashboard.blade.php
<!-- resources/views/admin/dashboard.blade.php -->
<x-app-layout>
<x-slot name="header">Admin Dashboard</x-slot>
<div class="py-12">Welcome, Admin!</div>
</x-app-layout>
2. User Management Panel
php artisan make:controller Admin/AdminUserController --resource
// app/Http/Controllers/Admin/AdminUserController.php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\User;
class AdminUserController extends Controller
{
public function index() {
$users = User::paginate(20);
return view('admin.users.index', compact('users'));
}
}
Create the view:
mkdir -p resources/views/admin/users
touch resources/views/admin/users/index.blade.php
<!-- resources/views/admin/users/index.blade.php -->
<x-app-layout>
<x-slot name="header">User Management</x-slot>
<div class="py-8">
<table class="min-w-full bg-white border shadow-sm">
<thead>
<tr>
<th class="px-4 py-2 border-b">ID</th>
<th class="px-4 py-2 border-b">Name</th>
<th class="px-4 py-2 border-b">Email</th>
<th class="px-4 py-2 border-b">Role(s)</th>
</tr>
</thead>
<tbody>
@foreach ($users as $user)
<tr>
<td class="px-4 py-2 border-b">{{ $user->id }}</td>
<td class="px-4 py-2 border-b">{{ $user->name }}</td>
<td class="px-4 py-2 border-b">{{ $user->email }}</td>
<td class="px-4 py-2 border-b">{{ implode(', ', $user->getRoleNames()->toArray()) }}</td>
</tr>
@endforeach
</tbody>
</table>
<div class="mt-4">
{{ $users->links() }}
</div>
</div>
</x-app-layout>