laravel-frontend-presets/vuetify
A Laravel frontend preset that swaps the default scaffolding for a Vuetify-powered Vue frontend, giving you Material Design components plus prebuilt authentication views so you can start building a polished admin or app UI right away.
Verify your Laravel version before anything else. This preset is built around php artisan preset, a command that was removed in Laravel 7. If you're on 7+ or any current version, Composer will install the package but the preset command won't exist — you're looking at a reference implementation, not a working install.
The three-command install on a compatible app (Laravel 5.5–6.x):
composer require laravel-frontend-presets/vuetify
php artisan preset vuetify
npm install && npm run dev
Some tagged versions also offer php artisan preset vuetify-auth, which scaffolds Vuetify-styled login, register, and password-reset screens instead of raw Blade auth views.
Where to look first. The preset replaces a known set of files; these are the ones that matter:
package.json — pulls in vue, vue-router, vuetify, axios, laravel-mix, and (for Vuetify 1.x) the stylus loaderswebpack.mix.js — build config; check for vuetify-loader and Sass/Stylus plugin setup hereresources/js/app.js and resources/js/plugins/vuetify.js — Vue bootstrap and the theme configuration objectresources/js/router.js and resources/js/components/ — example SPA wiring and starter componentsresources/views/welcome.blade.php and resources/views/layouts/app.blade.php — the <div id="app"> mount point plus the Material Design Icons / Roboto <link> tagsFirst use case — harvest, don't adopt. The strongest day-to-day move is to run the preset once on a throwaway Laravel 6 sandbox, then copy resources/js, the dependency block from package.json, and the Blade layout into your own repo with pinned versions. Given the package's age and zero downstream dependents, this gives you the Vuetify scaffold without inheriting an unmaintained dependency on a retired extension point. If you must install it directly, do it on a fresh branch or spike repo with an explicit plan to stop depending on the preset after the first commit.
Once running, you have a v-app shell, a working router, and a page or two of demo components — enough to render a first Vuetify screen in under an hour on a correctly-versioned Laravel app.
Full-SPA pattern (the intended one). Blade serves a single shell view containing <div id="app"></div>; Vue + vue-router handle every route inside it.
// routes/web.php — catch-all so deep links survive a refresh
Route::get('{any}', fn () => view('app'))->where('any', '.*');
Register new screens as .vue files under resources/js/components/ and point router.js at them. This is where Vuetify earns its keep: v-app → v-navigation-drawer + v-app-bar + v-main for the chrome, v-data-table for index screens, v-form with v-text-field rules arrays for create/edit forms.
Backend-driven forms. Pair v-form with Laravel's 422 responses by piping the error bag straight into error-messages:
axios.post('/api/posts', this.form)
.then(() => this.$router.push('/posts'))
.catch(e => { this.errors = e.response.data.errors });
<v-text-field v-model="form.title" :error-messages="errors.title" />
v-text-field's error-messages prop takes an array, so e.response.data.errors.title drops in untouched — no mapping layer required.
Blade-embedding pattern (smaller surface area). If you don't want a router, mount Vue on individual Blade pages and use Vuetify as an interactive-island library. Keep app.js registering Vuetify globally, and remember Blade eats {{ }} — use @{{ }} for anything Vue should interpolate.
Data tables as the workhorse. For the bulk of admin CRUD, v-data-table with :headers, :items, :search, and :loading replaces a hand-rolled table component. Flip loading in created() and reset it in axios.finally().
Theme as configuration, not code. Put brand colors in plugins/vuetify.js:
export default new Vuetify({
theme: { themes: { light: { primary: '#1976D2', secondary: '#424242' } } }
});
Every component using color="primary" inherits it. This is the single highest-leverage customization point the preset exposes — touch this before touching any component.
Integration tip: the preset's bootstrap.js configures axios with X-Requested-With and credential handling, and reads the CSRF token from <meta name="csrf-token">. If you swap HTTP clients or add Sanctum, verify the header still comes through — auth failures here look like silent 419s.
The preset overwrites files silently. app.js, bootstrap.js, webpack.mix.js, and welcome.blade.php are replaced, not merged. Commit before and after, diff, and never re-run the preset on a branch where you've customized the theme or router.
Pin the preset tag to your Laravel minor. These packages were tagged per-framework-version (^1.0 for 5.5, ^2.0 for 5.6, and so on). Pulling dev-master gets you stubs that assume a directory layout which may not match your app — the big shift was resources/assets/js → resources/js around 5.7.
Vuetify 1.x uses Stylus; 2.x uses Sass. If you copy stubs from an old tag into a modern project, the stylus-loader / vuetify-loader setup and the icon font <link> tags will be wrong. Install Vuetify fresh via npm and port only the layouts and theme file.
Old node-sass will not build on current Node. Expect Node Sass version X is incompatible with Y or binary download failures on install. Either pin Node to an era-appropriate LTS for a quick spike, or (preferred) migrate to Dart Sass plus Laravel Mix 6 — at which point you are effectively doing a manual Vuetify install with the preset as a template.
Icons render as text. Missing the Material Design Icons stylesheet makes <v-icon>home</v-icon> print the literal word "home". Add the CDN <link> to your Blade <head> or install @mdi/font. Same story for Roboto — without the Google Fonts link everything falls back to a system serif/sans stack.
One v-app per page. Vuetify's v-app provides layout context; nesting two (a common accident in multi-page Blade embedding) causes drawer/app-bar positioning to break in ways that are hard to trace. If you have multiple mounted Vue roots, only one should contain v-app.
vuetify-loader and tree-shaking. If your webpack.mix.js doesn't include vuetify-loader, you'll ship the entire Vuetify component library — hundreds of KB of unused JS. It matters less for an internal admin tool, but check the bundle if you're exposing anything externally.
The upgrade cliff is the real gotcha. Every dependency here (Vue 2, Vuetify 1/2, Laravel Mix 4/5, node-sass, artisan preset) is end-of-life. There is no upgrade path from this scaffold to Laravel 11 + Vite + Vue 3 + Vuetify 3 — the migration is a rewrite. Budget for it explicitly if the surface ever becomes customer-facing.
Debugging the preset itself. php artisan preset lives inside laravel/ui's or the framework's preset resolution — if the command runs but nothing changes, check that the package's service provider is auto-registered (composer dump-autoload and inspect bootstrap/cache/packages.php). Preset failures are silent by design; always verify by diffing package.json.
Extension points worth knowing. The preset publishes no config file. The only sanctioned customization surfaces are plugins/vuetify.js (theme + options), webpack.mix.js (build), and the Blade layout (fonts, meta tags). Anything else is a fork.
How can I help you explore Laravel packages today?