on June 30, 2026 at 9:15 am Forking laravel-livewire-tables for Laravel 13 + Livewire 4​Nasrul Hazim Bin Mohamad

TL;DR

  • Upstream rappasoft/laravel-livewire-tables marked Livewire 4 support wontfix, so I forked it.
  • The fork now targets Laravel 13 (keeps 12), runs on Livewire 4, and drops Livewire 3.
  • Tests moved to Pest 4 (old PHPUnit classes still run via interop), with a Testbench workbench demo app.
  • Takeaway: when an upstream says no, a fork is fine — but only if you bring the test harness with you.

Why fork at all

I lean on this package across projects: sortable, searchable, filterable tables for Livewire. The problem: upstream declined Livewire 4 support (wontfix) and hadn’t shipped Laravel 13. I didn’t want to be stuck on Livewire 3 forever, so I started a v4 line in my fork at cleaniquecoders/laravel-livewire-tables.

A fork is like renovating a rented house you’ve decided to buy — worth it only if you’re committed to maintaining it. I am, so the roadmap lives in GitHub milestones M1–M8.

What landed today

Milestone Change
M1 Laravel 13 + Livewire 4 support; drop Livewire 3
M2 Migrate test suite to Pest 4 + Testbench workbench demo
M3 Upstream bug-fix cluster + regression tests
CI Replace L10/L11 workflows with a v4 matrix
Pint formatting pass under the upgraded toolchain

The constraint matrix

The dependency floor moved up. Here’s the before/after:

Before After
PHP 8.1+ 8.2+
Laravel 10 / 11 12 / 13
Livewire 3 4 (3 dropped)
Tests PHPUnit Pest 4 (PHPUnit interop)

CI now runs the cross-product so a regression on any combo shows up fast:

# .github/workflows/ci.yml
matrix:
  php: ['8.3', '8.4', '8.5']
  laravel: ['12.*', '13.*']
# ...
- run: composer require "laravel/framework:$ matrix.laravel " --no-interaction --no-update
- run: vendor/bin/pest --no-coverage
Enter fullscreen modeExit fullscreen mode

Pest without a big-bang rewrite

The trick to migrating tests is don’t rewrite them all at once. Pest runs class-based PHPUnit tests unchanged via its interop layer, so the ~hundreds of existing test_* methods keep passing while new tests are written Pest-native.

The bind is one line in tests/Pest.php:

uses(TestCase::class)->in('Unit', 'Visuals', 'Feature');
Enter fullscreen modeExit fullscreen mode

And new tests read the way Pest tests should — fluent, no class boilerplate:

use function PestLivewirelivewire;
it('builds a configurable column fluently', function () 
    $column = Column::make('Name', 'name')->sortable()->searchable();
    expect($column->getTitle())->toBe('Name')
        ->and($column->isSortable())->toBeTrue()
        ->and($column->isSearchable())->toBeTrue();
);
Enter fullscreen modeExit fullscreen mode

So the migration is incremental: old suite stays green, new work goes Pest-first.

A workbench you can actually click

Testing a UI package against assertions only gets you so far. M2 adds an Orchestra Testbench workbench — a tiny real Laravel app inside the package you can boot and click through:

composer build   # testbench workbench:build
composer serve   # testbench serve
Enter fullscreen modeExit fullscreen mode

It ships demo models (Owner, Species, Breed, Pet), a seeder, and a DemoPetsTable Livewire component, so you can see the table render against real data instead of imagining it from a test name. For a component library, that’s the difference between “tests pass” and “it actually looks right.”

What’s next

The heavy refactor is still ahead (M6): the component composes ~26 load-order-dependent With* traits and inlines theme branches across ~59 Blade files. That sprawl is the real target — but the rule is behaviour-preserving and test-guarded. Today’s job was getting onto Laravel 13 + Livewire 4 with a green Pest suite first, so the refactor has a safety net.

If you’re maintaining a package and upstream says no to the version you need: fork it, but bring the tests. The test harness is what makes a fork maintainable instead of a liability.

 

Leave a Reply

Your email address will not be published. Required fields are marked *