laravel-frontend-presets/material-dashboard
Laravel frontend preset that scaffolds the Material Dashboard admin theme into your app, complete with authentication views and a ready-to-use Bootstrap Material Design layout. Install the preset, run the preset command, and get a polished dashboard UI without wiring up templates by hand.
Install the package
composer require laravel-frontend-presets/material-dashboard
The package ships a service provider that registers an Artisan preset command (in the laravel-frontend-presets family this is usually php artisan ui material-dashboard). Confirm the exact command name against the README before running it — this package targets Laravel 11+, which no longer ships the old preset command, so all scaffolding is driven by the package's own command.
Scaffold the frontend
php artisan ui material-dashboard
# optionally scaffold auth views too
php artisan ui material-dashboard --auth
This publishes Blade layouts, a dashboard view, auth views (if requested), and the Material Dashboard CSS/JS assets. Run this on a clean branch — the preset will overwrite resources/views/layouts/, resources/views/auth/, resources/css/, resources/js/, and possibly routes/web.php.
Install frontend dependencies and build
npm install
npm run dev # or npm run build for production
Where to look first
resources/views/layouts/ — the master layout with sidebar, navbar, and content slot.resources/views/dashboard.blade.php (or equivalent) — the reference page demonstrating cards, tables, and chart widgets.resources/views/auth/ — login/register/password-reset views if you used --auth.src/ directory (in vendor/laravel-frontend-presets/material-dashboard/) — the preset command code and stub paths tell you exactly which files get copied and where.First use case: point an authenticated route at the dashboard view and use the layout as the shell for an admin area:
Route::get('/dashboard', fn () => view('dashboard'))
->middleware(['auth'])->name('dashboard');
Extend the provided layout, don't rebuild it. The preset's value is the layout shell (sidebar, topbar, footer, asset includes). New pages should inherit it:
@extends('layouts.app')
@section('content')
<div class="row">
<div class="col-md-4">
@include('partials.stat-card', ['title' => 'Users', 'value' => $userCount])
</div>
</div>
@endsection
If the layout uses named sections (@yield('content'), @yield('title'), @stack('scripts')), match those names exactly — they're defined in the published layout, not in Laravel core.
Keep the preset's partials as reference components. Most Material Dashboard presets ship reusable card/table/chart snippets. Copy one into a Blade partial (resources/views/partials/) and pass data in via @include or a Blade component rather than duplicating markup per page.
Sidebar navigation is usually hand-maintained. The sidebar links typically live in the layout or a sidebar.blade.php. Centralize the menu as an array so you can mark the active item:
@php
$menu = [
['route' => 'dashboard', 'icon' => 'dashboard', 'label' => 'Dashboard'],
['route' => 'users.index', 'icon' => 'person', 'label' => 'Users'],
];
@endphp
@foreach ($menu as $item)
<li class="nav-item {{ request()->routeIs($item['route']) ? 'active' : '' }}">
<a class="nav-link" href="{{ route($item['route']) }}">
<i class="material-icons">{{ $item['icon'] }}</i>
<p>{{ $item['label'] }}</p>
</a>
</li>
@endforeach
Integrate, don't replace, your auth stack. Laravel 11 apps commonly use Breeze or Jetstream. Two viable patterns:
--auth and let the preset own resources/views/auth/* and the login route. Remove or disable Breeze's auth views to avoid duplicate/conflicting layouts.Pick one early — mixing both layouts on the same route produces a confusing double-navbar result.
Wire data at the controller, keep the view dumb. Dashboard cards and tables should receive data from a controller or view composer, not query inside Blade:
public function index()
{
return view('dashboard', [
'stats' => $this->statsService->summary(),
'recent' => User::latest()->take(5)->get(),
]);
}
Use the preset's chart/table markup as a template for your own widgets. Chart widgets usually expect a <canvas> plus a small init script; keep those scripts in @push('scripts') so they load only on pages that need them.
Version-control the scaffold as a single commit. After running the preset command, commit the generated files before customizing. This makes it trivial to see exactly what the preset changed and to revert if you later swap to Breeze/Tailwind.
preset or ui command. If php artisan ui ... fails with "command not found," the package's service provider wasn't auto-discovered (check bootstrap/providers.php in Laravel 11) or the command name differs. Run php artisan list and grep for the preset command.resources/views/layouts/*, resources/views/auth/*, resources/css/app.css, resources/js/app.js, routes/web.php, vite.config.js. Diff after running.npm run dev produces no styles, check whether the preset modified vite.config.js to include the Material CSS/JS entry points, or whether it dropped compiled assets into public/assets/ that you should reference via asset()./assets/css/material-dashboard.css or use a {{ asset('...') }} wrapper. In subdirectory deployments, search-and-replace these paths or centralize them in a config value.ml-3 vs ms-3, float-left vs float-start will silently no-op.@stack('scripts') is easy to miss. Chart widget snippets often rely on a stack defined at the bottom of the layout. If your chart doesn't render, confirm the layout includes @stack('scripts') and that your page uses @push('scripts') (not @section).php artisan view:clear && php artisan route:clear && php artisan config:clear.preset:uninstall. Keep a clean commit or a fresh branch per attempt; restoring the prior frontend means git checkout of the affected paths and re-running npm install.vendor/laravel-frontend-presets/material-dashboard/src/) can be published/overridden if the package exposes a vendor:publish tag. Check php artisan vendor:publish --provider="..." — overriding stubs is cleaner than patching published output if you'll re-run the preset on multiple apps.composer.json so a future update doesn't rewrite your routes/web.php mid-sprint.--auth was used and your app already has Auth\LoginController or Breeze's AuthenticatedSessionController, resolve the conflict before running — otherwise you'll get duplicate route definitions for login/register.How can I help you explore Laravel packages today?