{} CodeLift

Laravel + Livewire Starter Kit: Docker-verified fork

We took the official laravel/livewire-starter-kit (Livewire v4 + Flux + Alpine), ran it inside Docker, and published a production-hardened fork. Tests go from the upstream 33 passed to 37 passed / 92 assertions. This article covers the Liv…

Pub 2026-04-19 Verified 2026-04-19 Upd 2026-04-19

Verification environment

  • PHP 8.5.5
  • Laravel 13.x
  • Composer 2.9.7
  • Node 22.22.2
  • npm 10.9.7
  • Frontend Livewire v4 + Flux + Alpine
  • Database SQLite (tests)
  • OS Docker Desktop (php:8.5-cli-bookworm)

Laravel + Livewire Starter Kit: Docker-verified fork

We took the official laravel/livewire-starter-kit (Livewire v4 + Flux + Alpine), ran it inside Docker, and published a production-hardened fork. Tests go from the upstream 33 passed to 37 passed / 92 assertions. This article covers the Livewire-specific findings — of the three starter kits, Livewire has the largest non-backend delta.

The 6 shared backend improvements are consolidated in the pillar:

Hardening the shared Laravel starter-kit backend

Target

Item Value
Name Laravel + Livewire Starter Kit
Official URL https://github.com/laravel/livewire-starter-kit
Improved fork https://github.com/codelift-dev/livewire-starter-kit/tree/improvements
Stack Laravel 13 + Livewire v4 + Flux UI + Alpine + Fortify
Upstream / improved license MIT / MIT
Verification date 2026-04-19
Upstream commit laravel/livewire-starter-kit@62c60c8

Upstream verification result

docker compose run --rm app returns 33 passed (77 assertions). Fewer tests than the React / Vue kits' 40 — this variant exercises form behavior through Livewire's component test harness rather than the Inertia HTTP harness, so the assertion distribution differs. Coverage is not weaker.

Four ways Livewire is structurally different

The Laravel backend is shared across all three kits, but the Livewire variant differs in ways that change the finding set.

Item React / Vue Livewire
@laravel/vite-plugin-wayfinder Yes (shells out to artisan at build) No
Inertia Yes (embeds initial props inline) No
Default middleware in bootstrap/app.php 3 Inertia-related appended Empty (callback body is just //)
Settings routes PATCH/DELETE HTTP verbs + Controller Route::livewire(...) + internal AJAX actions

These four produce the Livewire-specific differences below.

The Wayfinder footgun doesn't happen

The "npm run build before composer install fails opaquely" problem that hits React / Vue does not occur in the Livewire kit. Its vite.config.js (React/Vue use .ts) has no @laravel/vite-plugin-wayfinder, so the build never shells out to artisan and has no dependency on vendor/autoload.php.

The official README lacking a Setup section is a minor gap shared by all three kits, so the fork adds one for contributors — but without the React/Vue-specific "looks like a Wayfinder bug" trap.

Security-header middleware — a worse starting state than React/Vue

Pillar finding D (security headers) is shared across all three, but Livewire's starting state is the worst. The withMiddleware() callback in bootstrap/app.php has a body of just a // comment — zero appended web middleware. React / Vue at least had the three Inertia-related ones; Livewire has none.

The fork's SetSecurityHeaders middleware becomes the first web middleware appended in this fork.

CSP — Livewire can go nonce-based

This is Livewire's biggest specific. The Inertia kits (React/Vue) embed initial state in an inline <script>, so dropping 'unsafe-inline' from the CSP requires patching Inertia.

Livewire does not embed initial state in an inline script. The client JS loads via external <script src>, component state lives in wire:* attributes on HTML elements, and updates go through a fetch to /livewire/update. So it can move to a strict nonce-based CSP without 'unsafe-inline'.

This hardening article keeps the CSP policy aligned with React/Vue (conservatively keeping 'unsafe-inline'), but Livewire can go further. The nonce migration is its own follow-up article:

Laravel + Livewire Starter Kit: nonce-based CSP

J. Settings rate limiting — deferred because the shape differs

In React / Vue, throttling profile update/destroy was just adding throttle middleware to the PATCH/DELETE routes in routes/settings.php.

Livewire is different. routes/settings.php uses Route::livewire('settings/profile', ...) to render component pages, and profile updates and password changes flow through Livewire's internal AJAX endpoint (/livewire/update). A route-level throttle only covers the initial page load, not component actions.

The correct fix is per-component RateLimiter::tooManyAttempts inside the action methods — a substantively different commit from React/Vue. It's deferred this pass for a Livewire-specific follow-up.

Commit layout — 7 commits

Commit Finding Source
README Setup A (weakened — no wayfinder) this article
.env.example comments B pillar
timezone via env C pillar
URL::forceScheme E pillar
SetSecurityHeaders middleware + test D pillar
layered login rate limiter G pillar
auth log channel + subscriber + test I pillar

React/Vue have 8 commits, Livewire has 7. The difference is finding J — deferred here because the fix shape differs.

Tests: upstream 33 passed → improved 37 passed / 92 assertions.

Before / after (Livewire-specific part)

Dimension Official Improved
php artisan test 33 passed / 77 assertions 37 passed / 92 assertions
README Setup section None Added
Initial middleware stack Empty SetSecurityHeaders appended
Reachable CSP strictness Nonce-based possible (see follow-up)

The before/after for the 6 shared backend findings is in the pillar.

When this fits

  • You're starting a production product on laravel/livewire-starter-kit.
  • You want PHP / Blade all the way down.
  • You want a strict CSP — Livewire can drop 'unsafe-inline' via the nonce migration (an edge over the Inertia kits).

Reproduce and adopt

git clone https://github.com/codelift-dev/livewire-starter-kit.git
cd livewire-starter-kit
git checkout improvements
docker compose -f codelift/docker-compose.yml build
docker compose -f codelift/docker-compose.yml run --rm app

Application diff only: git diff main improvements -- . ':!codelift'

Related

License

Upstream and improved fork both MIT. Findings reflect the verification date.

Featured in comparisons

Related articles