Skip to content

Modernize to full Laravel + Livewire (Volt/Flux)#240

Merged
mnapoli merged 9 commits into
masterfrom
livewire-modernization
Jul 1, 2026
Merged

Modernize to full Laravel + Livewire (Volt/Flux)#240
mnapoli merged 9 commits into
masterfrom
livewire-modernization

Conversation

@mnapoli

@mnapoli mnapoli commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Modernizes the app to look and work like it was generated from the current Laravel Livewire starter kit, without changing the product (same pages, same GitHub-only login, same Algolia search, same URLs/RSS).

What changed

Frontend → Livewire + Volt + Flux + Alpine

  • Pages are now Volt full-page components (home, top, news, stats, thread) routed via Volt::route().
  • Voting is a Livewire action (wire:click) with server-side auth + toggle — replacing the jQuery POST /votes/{n} and VoteController (both removed).
  • Email collapse and the "next unread" (n) shortcut are now Alpine; jQuery is gone entirely. Algolia InstantSearch kept, loaded via Livewire @assets/@script.
  • Classic @extends('layout') replaced by an <x-layouts.app> component; View::share globals dropped in favor of auth()->user() + config(). Flux icons replace inline SVGs.

Data layer → typed value objects

  • New readonly App\Support\Email\ThreadSummary replaces the associative arrays ThreadQuery leaked into views and the RSS builder.

Auth → Socialite-shaped

  • LoginController moved into an invokable Auth\GithubController. Callback stays on /login, so no GitHub OAuth app change is needed.

Starter-kit alignment

  • Slimmed config/ to the 3 genuinely-customized files (the other 9 were byte-identical to framework defaults).
  • Migrated the whole suite from PHPUnit to Pest v4.
  • Added the standard composer dev script.
  • Dropped @fluxAppearance (design is fixed-light, no dark mode).

Serverless (Bref)

No config needed: httpApi: '*' already routes /livewire/update + asset endpoints to PHP, and Livewire 4 derives its endpoint prefix deterministically from APP_KEY (stable across Lambda instances) and auto-detects Bref.

Verification

✅ 99 tests pass (Pest) · ✅ vendor/bin/pint clean · ✅ vendor/bin/phpstan (level 7) clean · ✅ live smoke test: all pages 200 with Livewire mounted, Flux icons, Alpine collapse.

Review note

Commits are grouped by primary concern for readability. Because the work is interdependent, only the final HEAD is guaranteed green (not every intermediate commit).

https://claude.ai/code/session_01AdPMVctMEUmKgwMWNNHmRZ

mnapoli added 8 commits July 1, 2026 17:51
Pull in livewire/livewire, livewire/volt and livewire/flux for the frontend
rewrite, and pestphp/pest as the test runner. Register the Volt service
provider and add the standard `composer dev` script.

Claude-Session: https://claude.ai/code/session_01AdPMVctMEUmKgwMWNNHmRZ
Replace the associative arrays that the thread-listing queries used to leak
into views and the RSS builder with a readonly ThreadSummary value object,
following the existing ThreadItem/EmailAddress pattern.

Claude-Session: https://claude.ai/code/session_01AdPMVctMEUmKgwMWNNHmRZ
Replace the Blade @extends layout and jQuery interactions with a component
layout, Volt full-page components (home/top/news/stats/thread), a thread-list
Livewire component that handles voting via wire:click, and Alpine for email
collapse and the next-unread shortcut. Removes the VoteController, the page
controllers and jQuery; voting auth is now server-side. Flux icons replace
the inline SVGs and cross-cutting view globals move off View::share.

Claude-Session: https://claude.ai/code/session_01AdPMVctMEUmKgwMWNNHmRZ
Move the Socialite login flow into an invokable App\Http\Controllers\Auth\GithubController
that handles both the redirect and the callback on the same /login URL,
keeping the existing GitHub OAuth callback registration unchanged.

Claude-Session: https://claude.ai/code/session_01AdPMVctMEUmKgwMWNNHmRZ
Delete the nine published config files that were byte-identical to the
framework defaults (app, auth, cache, database, filesystems, logging, mail,
queue, session); they still resolve from Laravel's merged defaults and env.
Keep only the genuinely customised services, externals and sentry configs.

Claude-Session: https://claude.ai/code/session_01AdPMVctMEUmKgwMWNNHmRZ
Convert the Actions, Unit and remaining HTTP test files from PHPUnit classes
to Pest's function style (setUp fixtures become beforeEach).

Claude-Session: https://claude.ai/code/session_01AdPMVctMEUmKgwMWNNHmRZ
The Livewire conversion had swapped several hand-authored SVG icons for
Flux/Heroicons, which changed the visual design. Revert them to the
original SVGs: the responses chat-bubble, logout arrow, thread back
chevron, and the email collapse minus-circle.

With no icons or components left using it, remove livewire/flux entirely
along with @fluxscripts and its CSS @import/@source lines.

Claude-Session: https://claude.ai/code/session_01AdPMVctMEUmKgwMWNNHmRZ
Since the test suite migrated to Pest, invoking vendor/bin/phpunit fails
with "Please run [./vendor/bin/pest] instead." Point the CI test step at
Pest.

Claude-Session: https://claude.ai/code/session_01AdPMVctMEUmKgwMWNNHmRZ
findTopThreads used MySQL-only DATE_SUB(NOW(), INTERVAL 1 MONTH), which
had no test coverage and could not run on the SQLite test suite. Bind the
one-month cutoff as a parameter computed in PHP instead — same semantics,
now portable across MySQL and SQLite.

Add Livewire tests for the "top" mode: a recently-updated voted thread is
listed, while unvoted threads and voted-but-stale (>1 month) threads are
excluded. These document that an empty Top page is expected when no thread
has positive votes within the last month, not a regression.

Claude-Session: https://claude.ai/code/session_01AdPMVctMEUmKgwMWNNHmRZ
@mnapoli
mnapoli merged commit 62316b4 into master Jul 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant