miaababikir/laravel-tailwind-dashboard-preset
A Laravel preset that scaffolds a clean Tailwind CSS dashboard with authentication views, layout components, and ready-to-use UI pages so you can skip the boilerplate and start building your admin panel faster.
Before you touch anything: this preset was last released in December 2021, so pin your Laravel version. It was built for the Laravel 8 era (laravel/ui style presets). Expect to spend more time fighting Vite/Mix version mismatches than actually using the dashboard.
composer create-project laravel/laravel:^8.0 dashboard-demo
cd dashboard-demo
composer require miaababikir/laravel-tailwind-css-dashboard-preset --dev
php artisan list | grep -i -E "preset|dashboard|ui"
Depending on the version you get, it will be either php artisan preset dashboard (legacy Laravel 6/7 style) or php artisan ui dashboard (Laravel 8 style). Both code paths exist in these packages; check src/ for the command class before running anything.php artisan preset dashboard --auth # add --auth only if you want the login/register stubs
npm install
npm run dev
php artisan serve, hit /login, then /dashboard. The dashboard page renders the layout in resources/views/layouts/ with the sidebar partial — that partial is the thing you'll actually be editing 90% of the time.Where to look first, in order:
vendor/miaababikir/laravel-tailwind-css-dashboard-preset/src/ — the update() method of the service provider is the ground truth for exactly which files get copied and overwritten.resources/views/layouts/app.blade.php (or dashboard.blade.php) — the shell.resources/views/partials/ or components/ — the sidebar/navbar.tailwind.config.js — the design tokens the stubs assume.webpack.mix.js — proof that this is a Mix-era package.Treat it as a one-shot generator, then throw the package away. The standard workflow is: install → scaffold → delete the composer entry. Keeping it around is dangerous because any future composer update combined with a re-run of the command silently overwrites your customized blades.
Fresh-app pattern (the only one that works cleanly):
git checkout -b feature/dashboard-ui
php artisan preset dashboard
git diff --stat # eyeball every overwritten file
npm install && npm run dev
Doing this on a mature app is painful — the preset ships opinionated versions of resources/js/app.js, webpack.mix.js, and tailwind.config.js that will clobber working configs.
Adding pages to the generated dashboard (this is the day-to-day pattern once scaffolding is done):
// routes/web.php
Route::middleware('auth')->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
Route::get('/dashboard/users', [UsersController::class, 'index'])->name('dashboard.users');
});
{{-- resources/views/dashboard/users.blade.php --}}
@extends('layouts.dashboard')
@section('content')
<x-card title="Users">
...
</x-card>
@endsection
Then add a <x-nav-link> (or plain <a>) entry in partials/sidebar.blade.php — that file is the single source of truth for nav.
Integration with existing auth packages: if you already use Breeze, Jetstream, Fortify, or even laravel/ui, do not pass --auth. The preset will generate its own Auth/*Controller classes and auth route group, which will collide with the existing one and cause "duplicate route name" or a 404 on login depending on registration order. Strip auth from the preset; use it purely for the dashboard shell.
Tailwind theming pattern: because the layout is Tailwind classes only (no CSS module / no preprocessor), retheming is done entirely via tailwind.config.js theme.extend. Change colors.primary, fontFamily.sans, and borderRadius, then npm run watch. Do not hand-edit the classes in the blades — you'll lose them on every preset upgrade, and there's no upstream.
Docker / CI pattern for demo apps:
RUN php artisan preset dashboard \
&& npm install && npm run production \
&& rm -rf node_modules
Fine for ephemeral preview environments; not fine for anything you have to maintain.
Multi-dashboard pattern: if you need two panels (admin vs. customer), don't re-run the preset. Copy layouts/dashboard.blade.php to layouts/admin.blade.php, rename the sidebar partial, and route under a different middleware group. The preset has no concept of multiple layouts.
preset command and replaced Mix with Vite. If you're on Laravel 9 or later, you'll need to either downgrade, or copy the stubs manually into resources/ and wire up Vite yourself. That's the real day-to-day cost of this package.php artisan preset not found. The command was removed from Laravel core in laravel/framework 8.x and the preset must register its own. If the command doesn't appear in php artisan list, the service provider wasn't auto-discovered — check composer.json extra.laravel.providers, and if missing, add it to config/app.php.resources/js, resources/css, resources/views, routes/web.php, tailwind.config.js, webpack.mix.js, and package.json. package.json and routes/web.php are merged, not replaced — check the diff carefully; duplicates in routes/web.php are a common failure mode.webpack.mix.js. If your app is on Laravel 9+ with vite.config.js, you have two files fighting for resources/js/app.js. Delete the Mix file and port the Tailwind import + alpine boot manually into resources/js/app.js.purge, not content). If npm install pulls Tailwind 3, the purge key becomes a no-op and your CSS bloat explodes in production. Fix: rename purge → content and update package.json to "tailwindcss": "^3".require('alpinejs') in bootstrap.js. Modern Alpine 3 renamed things (x-data behavior is stable but x-init timing changed). Expect any dropdown/modal in the stubs to silently not open if you're on Alpine 3 with old init code.vendor assets not being included. Run php artisan view:clear && php artisan config:clear, then check the browser network tab — if app.css is 404, your mix() helper path in layouts/app.blade.php doesn't match the output in public/.vendor/miaababikir/.... They're the stubs; edits will be lost on composer update. If you need to customize the generated files repeatedly, fork the repo, edit src/stubs/, and reference your fork from composer.json repositories as a path or VCS repo.update() method in the provider — which is why forking is the pragmatic answer if you need this long-term.--force before you run anything on a non-fresh app. Some preset implementations require --force to overwrite an existing webpack.mix.js / tailwind.config.js; others silently overwrite. Either way, commit first.require('./bootstrap') + a Vue mount in app.js, and reconciling that with Inertia's createInertiaApp boot is more work than hand-writing the layout.How can I help you explore Laravel packages today?