Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Frontend Preset Laravel Package

calebporzio/laravel-frontend-preset

Swap Laravel's default frontend scaffolding with a single Artisan command. This preset installs your chosen CSS and JS stack, including Tailwind, Bootstrap, Vue, or React, plus ready-made auth views.

View on GitHub
Deep Wiki
Context7

Getting Started

What you're actually installing. This is a build-time scaffolding artifact, not a library. It hooks into Laravel's old php artisan preset mechanism (Laravel 5.5–7.x) and overwrites a fresh application's frontend boilerplate with a Tailwind CSS + Alpine.js, Blade-first setup. Once it has run, it has no runtime role in your app. Treat it the way you'd treat laravel new — a one-shot command with side effects on committed files.

Minimal steps (throwaway app only):

laravel new preset-spike          # pin to Laravel 6.x or 7.x
cd preset-spike
git add -A && git commit -m "baseline"   # checkpoint BEFORE running
composer require --dev calebporzio/laravel-frontend-preset
php artisan preset calebporzio    # confirm exact handle by reading the provider
npm install && npm run dev
git diff --stat                   # inventory every file it touched

Where to look first, in this order:

  1. src/ — the PresetServiceProvider (it registers the preset handle with Laravel's PresetCommand) and the preset class itself (install() / uninstall()). This is the whole API surface; it's small.
  2. stubs/ — the actual opinionated output: package.json, webpack.mix.js, tailwind.config.js, resources/css/app.css, resources/js/app.js, and Blade views/layouts. This directory is the product. Everything else is plumbing.
  3. The generated app — git diff your baseline commit against the result. That diff is your deliverable from the spike; write it into a decision record.

First use case that justifies the time. Not "start a new project" — that's Breeze/Jetstream/php artisan ui tailwind territory and those are maintained. The defensible use case is a 1–2 day DevEx spike: you need a concrete, credible prior art example of a minimal-JS Tailwind + Alpine scaffold, and a reference implementation of Laravel's preset contract so you can write your own PresetServiceProvider for an internal starter kit you'll actually own. Harvest patterns; don't adopt the dependency.

Implementation Patterns

Preset contract pattern (the reusable idea). The package implements PresetInterface with paired install() / uninstall() methods and registers itself so php artisan preset <handle> resolves it. install() copies stub files over the app; uninstall() is the nominal inverse and is not a reliable rollback. This two-method shape is worth copying into your own internal preset — it's the only part of the package with lasting leverage.

Wholesale file-copy semantics, no merging. Every stub is written over the target path. That means:

  • Run it only on a pristine app, or behind a git checkpoint.
  • Expect package.json to be replaced, not merged — any dependencies you added before the preset vanish from the manifest.
  • Expect hand-written views under resources/views/ to be clobbered.

This is why the correct integration pattern is diff-and-port, never install-and-continue.

Diff-and-port into a modern (Vite) app. The pattern that actually works for day-to-day use:

# 1. Generate reference output in a throwaway Laravel 6/7 app
# 2. Inventory these files specifically:
#    package.json, webpack.mix.js, tailwind.config.js,
#    resources/css/app.css, resources/js/app.js,
#    resources/views/layouts/*.blade.php
# 3. Port into your Vite app, upgrading as you go:
#    webpack.mix.js        -> vite.config.js
#    mix.postCss(...)      -> vite css.postcss + postcss.config.js
#    mix.js('resources/js/app.js','public/js') -> vite input array
# 4. Compare line-by-line against Breeze / `php artisan ui tailwind`.
#    If you can't name a genuine differentiator, kill the spike — that's a win.

Alpine bootstrap pattern. The stub app.js almost certainly does the small, correct thing — import Alpine, attach it to window, start it — so Blade can use x-data / x-on without a module bundler leaking scope. Verify the version: Alpine 2 (import 'alpinejs', window.Alpine = Alpine) and Alpine 3 (import Alpine from 'alpinejs'; window.Alpine = Alpine; Alpine.start()) differ, and stubs from early 2020 predate v3. If you port, rewrite for v3 and re-check every x- directive — v3 renamed and removed several.

Tailwind config pattern. The stub's tailwind.config.js is 2020-vintage: expect purge (not content), no @tailwindcss/forms or @tailwindcss/typography, and possibly a custom color palette. When porting to Tailwind 3+, migrate purge → content, confirm the content globs actually match your Blade paths (a silent cause of "my classes are missing in production"), and re-run @apply usages — some utilities changed names.

Blade layout pattern. The valuable, portable part is the layout skeleton: <html>, @yield/@section slots or {{ $slot }} if it uses components, a @stack('scripts')-style hook before </body> for page-level Alpine, @vite or mix() asset calls. Read this file first when you sit down with the stubs — it's where the "opinion" lives, and it's the easiest thing to lift verbatim into a house starter kit.

Writing your own preset, using this as the template. If the spike convinces you a house preset is worth owning:

class HousePresetServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // Register the handle with Laravel's preset resolution
        // (mirror exactly what src/ does — do not guess)
    }
}

Then keep your stubs in your own repo, version them against the Laravel major you're on, and add a test that runs the preset on a scaffolded app and asserts the file inventory. That test is the thing this package never had and the reason it died.

Gotchas and Tips

php artisan preset doesn't exist on Laravel 8+. The command was removed. On 8/9/10/11 the install will appear to succeed and the command will fail with "Command not found." The package is unusable as a drop-in from Laravel 8 onward — extraction is manual. Confirm your target Laravel version before you scope any work.

Never run the preset in CI or a Dockerfile. It rewrites committed source files. Running it mid-build produces nondeterministic images, silently clobbers hand-edited views, and makes the build artifact impossible to diff. Same rule for any post-install script: scaffolding belongs on a developer's machine, once, behind a git commit.

Don't edit vendor/calebporzio/laravel-frontend-preset/stubs/. It works for about five minutes and then composer update eats your changes. Fork, or copy stubs into your own repo — nothing in between.

uninstall() is not a rollback. There's no merge semantics and no file backup, so a "let me try it and undo" workflow doesn't exist. Your undo is git checkout .. Set the checkpoint commit before you type anything.

The generated package.json will be stale enough to fight you. Tailwind 1.x-era, old PostCSS, old Node assumptions. npm install may emit peer-dependency errors or refuse to build on a modern Node. Don't fix the generated manifest — use it as a spec and write a fresh one against current versions. If you insist on installing the ancient manifest, pin your Node version explicitly or the build failure is a rabbit hole.

mix() vs @vite() will bite you on every layout file. If you port the Blade layout into a Vite app and leave the mix() helper in place, you get a vague "mix manifest not found" 500 in local and a broken asset path in CI. Grep for mix( after porting. Also swap webpack.mix.js for vite.config.js in the same commit — half-migrated asset pipelines are the most common botched attempt.

Alpine v2 → v3 silent breakage. Code that "looks fine" fails at runtime: x-data object syntax changed subtly, $refs behavior shifted, Alpine.start() is now required, and plugins moved to separate packages (@alpinejs/focus, etc.). If a ported component renders but does nothing, open the console before touching the Blade file.

Tailwind purge/content mismatch causes the classic "works locally, unstyled in prod" failure. The 2020 stub's purge globs predate the resources/js/**/*.vue-era layouts and may not cover your component paths. After porting to content, hard-refresh a production build and eyeball a page that uses @apply-heavy custom classes.

Debugging: read the stubs, not the docs. There is no documentation beyond a 2020 release note. The only source of truth for what the preset does is stubs/ plus a git diff of a real run. If someone tells you it "sets up Tailwind and Alpine," verify which versions — the whole migration plan hinges on it.

Abandoned-package warnings in composer audit / compliance review. Adding this to a long-lived composer.json is a standing exception with no accountable owner, no CVE response path, and no cadence. It's require-dev-only at absolute best; ideally it lives in a throwaway repo you delete after the spike, and the only artifact that survives is the file inventory in your decision record.

Extension point worth remembering: the preset handle is just a config lookup. Because registration goes through Laravel's preset resolution, you can define your own handle pointing at your own class in an app-level provider, without forking this package at all. If you like one specific stub (the layout, say), copy that one file and skip the rest of the machinery.

One thing to genuinely credit it for: it validates the Blade-first, minimal-JS, Tailwind+Alpine opinion years before Breeze made it mainstream. That's the pattern to harvest. The package itself is prior art, budgeted at zero for support.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings