Filament v5 Preview: Schema Unification, Performance Shifts, and How to Prepare Now
#filament #laravel #php #filament-v5

Filament v5 Preview: Schema Unification, Performance Shifts, and How to Prepare Now

4 min read Mohamed Said Mohamed Said

What Filament v5 Is Actually Changing

Filament v5 is not a cosmetic release. The core team is pushing three structural bets: a unified render pipeline across forms, infolists, and tables; first-class support for deferred/streamed component hydration; and a leaner JavaScript footprint that removes the remaining Alpine coupling from the PHP layer.

If you are running a large Filament v4 panel today, some of these changes will require deliberate refactoring — not just a composer update.


The Unified Render Pipeline

In v4, forms and infolists share the Schema API, but table columns still carry their own rendering contract. In v5, columns, form fields, and infolist entries are all first-class Schema\Component descendants with a single lifecycle:

resolve → configure → render

This means custom columns you built by extending Filament\Tables\Columns\Column will need to be re-expressed as schema components. The old getStateUsing / formatStateUsing hooks still exist but are now implemented as pipeline taps on the shared component base, not column-specific overrides.

Practical impact: Any package or plugin that extends Column directly will break. Start auditing your custom columns now.

// v4 custom column (will break in v5)
class StatusBadgeColumn extends Column
{
    protected function setUp(): void
    {
        $this->formatStateUsing(fn ($state) => Str::upper($state));
    }
}

// v5 direction — extend the shared SchemaComponent base
class StatusBadgeColumn extends \Filament\Schemas\Components\Component
{
    protected string $view = 'columns.status-badge';

    public function setUp(): void
    {
        $this->tap(fn ($component) => $component->state(
            fn ($record) => Str::upper($record->status)
        ));
    }
}

Deferred Hydration and What It Means for State

Filament v5 introduces opt-in deferred hydration for heavy schema sections. You annotate a group as ->deferred() and Filament renders a lightweight skeleton on the initial page load, then streams the real component HTML via a follow-up Livewire request.

Section::make('Analytics')
    ->deferred()
    ->schema([
        StatsOverviewWidget::make(),
        RevenueChart::make(),
    ])

The catch: deferred sections cannot share reactive state with non-deferred siblings on the same form. If you have $set / $get calls crossing that boundary, they will silently no-op. Audit your inter-field dependencies before enabling this.


Alpine Decoupling

Filament v4 still ships Alpine directives baked into Blade components (x-data, x-show, x-on). In v5 the PHP layer emits only data attributes; a thin Filament JS layer handles DOM behaviour. This makes it possible to swap Alpine for another reactive micro-library, but it also means:

  • Any custom field that injects raw x-data into its view will need to be rewritten using the new FilamentJs::data() / FilamentJs::on() helpers.
  • The @entangle directive is replaced by a first-party wire:filament-bind attribute that the Filament JS layer intercepts.

How to Prepare Your v4 Codebase Today

1. Eliminate direct Alpine in custom views

Replace x-data="{ open: false }" patterns with Livewire-native state where possible. This makes the Alpine decoupling a non-event for you.

2. Audit every class that extends Column

Run a quick grep:

grep -rn 'extends Column' app/ packages/

Document each hit. These are your v5 migration targets.

3. Centralise formatStateUsing logic into plain callables

If your formatting logic lives in a closure passed to formatStateUsing, extract it to an invokable class. The invokable will survive the pipeline refactor unchanged.

// Before
->formatStateUsing(fn ($state) => Number::currency($state, 'GBP'))

// After — survives the v5 migration
->formatStateUsing(new FormatCurrency('GBP'))

4. Pin your Filament packages to ^4.0 now

Do not use * or @dev constraints in production. When v5 tags drop, a loose constraint will pull a breaking release.


Takeaways

  • Filament v5 unifies columns, fields, and entries under one SchemaComponent base — custom columns will break.
  • Deferred hydration is powerful but incompatible with cross-boundary reactive state.
  • Alpine is being decoupled from the PHP layer; raw x-data in custom views must be migrated.
  • Audit extends Column usages and extract formatting logic to invokables today.
  • Pin Filament to ^4.0 in composer.json until you have a tested upgrade path.

Found this useful?

Frequently Asked Questions

3 questions
Q01 Will Filament v4 custom fields automatically work in v5?
No. Fields that extend Filament's form component base are likely fine, but custom table columns that extend `Column` directly will need to be rewritten as SchemaComponent descendants due to the unified render pipeline.
Q02 Is deferred hydration safe to enable on all sections?
Only on sections whose fields have no reactive dependencies (`$set`/`$get`) crossing into non-deferred siblings. Cross-boundary reactivity silently breaks, so audit inter-field dependencies first.
Q03 Do I need to remove Alpine from my project entirely for v5?
No. Alpine can still be used in your own Blade views. The change is that Filament's own PHP layer will stop emitting Alpine directives; your custom views that inject raw `x-data` into Filament component slots will need updating.

Continue reading

More Articles

View all