Filament form for products that uses Tabs with Variants and Related products, with pretty complex schema and optimized with the new Filament 5.8 feature of deferred schema loading.
One-time payment
Sign in with GitHub to buy
Sign in first, then complete your $9 checkout.
30-day money-back guarantee
This project demonstrates Filament's deferred schema loading, which lets any part of a form skip rendering until it actually becomes visible. It builds a realistic e-commerce product editor — eight tabs, a fifty-item variants repeater, and selects backed by thousands of records — and then defers almost all of it.
The key idea is that a component's schema() can accept a Schema object instead of a plain array, and that object can be marked with ->deferLoading(). Filament then renders a lightweight placeholder in its place. When the placeholder enters the viewport, an intersection observer triggers a Livewire partial render of just that one schema. Tabs the user never opens are never rendered at all — not on the client, and not on the server.
On the seeded showcase product, this takes the edit page from 2,869 KB of HTML down to 737 KB without changing a single field, a validation rule, or a line of business logic.
The repository contains the complete Laravel + Filament project to demonstrate the functionality, including a seeded catalogue of 5,000 products, an environment toggle to switch deferring on and off for comparison, and tests covering both states.
The Filament project is in the app/Filament folder.
Feel free to pick the parts that you actually need in your projects.
git clone.env.example file to .env and edit database credentials there (the default is SQLite)composer installphp artisan key:generatephp artisan storage:linkphp artisan migrate --seed/admin and log in with credentials [email protected] and passwordThe seeder prints the URL of the showcase product when it finishes — the one with fifty variants that makes the difference obvious.
The application is organized around a single Filament resource. The form is split into tabs, and each tab hands Filament a Schema object that knows whether it should render immediately or wait until the user actually looks at it.
The form is one Tabs component holding eight tabs, each built by its own private method. Splitting them this way keeps the deferring decision visible per tab rather than buried in one long array.
app/Filament/Resources/Products/Schemas/ProductForm.php
public static function configure(Schema $schema): Schema{ return $schema ->components([ Tabs::make('Product') ->persistTabInQueryString() ->columnSpanFull() ->tabs([ self::generalTab(), self::pricingTab(), self::inventoryTab(), self::variantsTab(), self::mediaTab(), self::shippingTab(), self::seoTab(), self::relatedProductsTab(), ]), ]);}
The General tab is deliberately left undeferred. It renders on every page load, which gives you a baseline to compare against — and reflects real practice, where the fields people edit most often are worth rendering up front.
The key points:
Schema object rather than an array, which is what makes deferring possible in the first placepersistTabInQueryString() keeps the active tab in the URL, and on reload Filament restores that tab — which also loads its schemadisplay: none rather than removed, so an inactive tab's deferred schema stays unloaded until the tab is actually selectedThe Inventory tab is the clearest example of the pattern. The whole tab body is...