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…
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
- Pillar: Hardening the shared Laravel starter-kit backend
- Follow-up: Livewire Starter Kit: nonce-based CSP
- Sister clusters: React / Vue
- Comparison: React vs Vue vs Livewire
License
Upstream and improved fork both MIT. Findings reflect the verification date.
Featured in comparisons
Related articles
- Laravel + React Starter Kit: Docker-verified fork We took the official laravel/react-starter-kit (Inertia + React 19 + shadcn/ui + Fortify), ran it inside Docker Desktop, and published a production-hardened fork. The test suite goes from the upstream 40 passed to 44 passed / 151 assertion…
- Laravel + Vue Starter Kit: Docker-verified fork We took the official laravel/vue-starter-kit (Inertia + Vue 3 + shadcn-vue + Fortify), ran it inside Docker, and published a production-hardened fork. Tests go from 40 passed to 44 passed / 151 assertions. This article covers the Vue / Ine…
- Hardening the shared Laravel starter-kit backend Laravel's official starter kits (React / Vue / Livewire) differ in their frontend layer, but they share the same Laravel + Fortify backend code. So most of the production-hardening work is identical across all three. This is the pillar art…
- Laravel + Livewire Starter Kit: nonce-based CSP The SetSecurityHeaders middleware shipped in our Livewire Starter Kit Docker-verified fork kept 'unsafe-inline' in script-src and style-src. That was a deliberate placeholder to match the React/Vue forks; the Livewire architecture doesn't …