Changelog
All notable changes to FilamentCraft are documented here.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
[Unreleased]
Added
Dual Filament 4 + 5 / Livewire 3 + 4 support.
composer.jsonconstraints broadened tofilament/filament: ^4.0|^5.0,livewire/livewire: ^3.0|^4.0,pestphp/pest: ^3.0|^4.0,pestphp/pest-plugin-laravel: ^3.0|^4.0andpestphp/pest-plugin-livewire: ^3.0|^4.0. Filament v5 ships zero API changes versus v4 (it only exists to allow Livewire 4); the editor's JS now uses the version-agnosticLivewire.hook('morph.updated', …)API alongside the legacydocument.addEventListener('livewire:morph.updated', …)listener so post-DOM-patch reboots fire on both Livewire 3 and 4.phpunit.xml.distsets a deterministicAPP_KEYso Laravel 12 + Pest 4 boots without an encryption-key error. CI matrix intests.ymlruns the full Pest suite against both Filament/Livewire pairs (withfilament/blueprintauto-removed on the v5 leg, since Blueprint v1.x capsfilament/supportat^4.0).Custom dynamic pages — four idiomatic doors, one shell. Host apps can now render any non-template page (cart, checkout, account, lesson player, search results, blog comments, gated downloads) inside the same theme + header region + footer region + fonts + tokens that FilamentCraft templates use. Each adopter picks the door that matches their style:
#[Storefront]Livewire attribute —FilamentCraft\Attributes\StorefrontextendsLivewire\Attributes\Layoutwith the layout name pre-set. Drop it on any full-page Livewire component for zero-ceremony shell wrapping. The raw#[Layout('filamentcraft::layout')]form also works.Route::filamentCraftStorefront(Owner::class, fn () => …)route macro — registers prefix + tenant middleware + Site binding for a whole group in one line. Reads the owner model fromfilamentcraft.tenancy.owner_modelwhen omitted.<x-filamentcraft::layout>Blade component — the explicit escape hatch with full prop control (:site,:title,:color-scheme,:mode,:locale). Aliasable viaBlade::component('your-name', Layout::class).- Laravel Folio integration —
php artisan filamentcraft:install --folioscaffolds a starterresources/views/storefront/cart.blade.phpand prints the FolioServiceProvider wiring. Zero PHP boilerplate per page after that.
ResolveSiteFromTenantmiddleware (aliasfilamentcraft.tenant) — resolves the current tenant from a route-param slug, sets it as the Filament tenant when a panel is bootable, and binds the matching liveSiteto the container. Config-driven so'filamentcraft.tenant'with no arguments works whenfilamentcraft.tenancy.owner_modelis set.TenantSiteResolver(src/Resolvers/) — singleton that centralises "owner-by-slug →Filament::setTenant()→ liveSite-by-morph" so the middleware and the Layout component's URL fallback share one implementation instead of duplicating ~30 lines each.Site::forOwner(Model $owner)local scope — polymorphic owner-match helper used by the resolver, replacing two raw->where('owner_type', …)->where('owner_id', …)chains.TemplateRenderer::buildShell()— extracted public method that returns the shell payload (tokens, header, footer, stylesheets, scripts, fonts, locale, dir, color scheme). BothrenderPayload()and the new Layout component funnel through it so there's a single source of truth for the document chrome.Auto-scroll preview on section selection. Opening a section in the editor sidebar (or visiting an editor URL with
?section=…) now smooth- scrolls the preview iframe to that section, using Livewire'smorph.updatedhook (version-agnostic) for post-patch reboots. Visibility-guard in the iframe handler suppresses the scroll if the section is already in the upper half of the viewport, so clicking a section inside the iframe doesn't snap-back. Consecutive same-id selections are deduped parent-side to skip the per-iframepostMessagefan-out.
Fixed
Editor sidebar resize stopped working after page morphs.
layout-resize.tskeyed split-grid instances on the body element only — when Livewire / Filament navigation morphed the page tree and replaced the[data-fc-layout-gutter]node, the resize handle silently lost itsmousedownlistener. Now tracks the gutter element identity in a parallelgutterByBodyWeakMap and rebinds when it changes.Route::filamentCraftTenant()shadowed Filament/admin/*routes. The defaulttenantPatternwas^(?!admin$)[A-Za-z0-9-]+. Because PHP regex$anchors to end-of-input (the whole URL path), the negative lookahead only blocked the literal segmentadmin— multi-segment URLs like/admin/acmepassed the lookahead, the FC tenant route capturedtenantSlug=admin+path=acme, and every Filament panel route at/admin/{tenant}/...404'd in real integrations. Default pattern is now^(?!admin\b)[A-Za-z0-9-]+(word boundary), which correctly rejects both the bareadminsegment andadmin/anything. Hosts that mount Filament at a non-default path should pass a customtenantPatternto the macro that excludes their panel prefix too — seedocs/guides/custom-dynamic-pages.md§Gotchas. New regression test intests/Feature/Routing/AdminRouteCoexistenceTest.php.
Changed
<title>infilamentcraft::renderer.layoutnow accepts an optional$titlevariable, falling back to$site->name(used by the new Layout component for per-page titles in dynamic pages). No behaviour change for existing template renders.PHPStan grew a
phpstan-bootstrap.phpthat registers thefilamentcraft::view namespace + theRoute::filamentCraftTenant()andRoute::filamentCraftStorefront()macros at analysis time, so namespaced view paths and macro calls resolve cleanly without per-file@phpstan-ignorenoise.
Known caveats
The v5 + Livewire 4 PHPStan leg is currently marked
continue-on-errorinstatic.yml. Pest 4 + Livewire 4 ship stricter generic stubs whose@template TComponentdoes not propagate through theLivewirefacade's@method static test()declaration, surfacing ~26 false-positive errors in test files (Unable to resolve template type,#[Computed]properties missing oninstance()). The Filament 4 + Livewire 3 leg remains the strict static-analysis gate. Tracking upstream: re-enable the v5 PHPStan gate oncelarastan/larastan-livewireships v4 support or the Livewire facade propagates the template parameter.The
--folioinstall flag scaffolds the starter file and prints the FolioServiceProvider snippet but does NOT auto-edit the host's service provider — Folio's path/uri/middleware wiring is currently a copy- paste step. Track for full automation once a Folio adopter asks.
Tests
- 719 / 3098 (was 692 / 3041 in 0.1.0). New coverage: layout component rendering + alias support + custom-title + colour-scheme,
ResolveSiteFromTenantmiddleware happy path + config defaults + not-found cases + invalid-owner errors,Route::filamentCraftStorefrontroute macro behaviour, URL-parameter fallback inside the Layout component with and without custom param names,#[Layout]and#[Storefront]attribute rendering through Livewire's full-page pipeline,--folioflag warning path. v4 leg PHPStan-clean, v5 leg test-clean.
[0.1.0] — 2026-05-12
First public release. Covers phases 0–6 of the master plan.
Added
- Scaffolding —
FilamentCraftServiceProvider,FilamentCraftPlugin, package config, install command, stubs. - Data layer + tenancy —
Site,Theme,Template,TemplateRevision,RegionEloquent models with circular FK split (templates ↔ revisions);TenancyResolverthat works without a tenancy package;SiteStatus,TemplateStatus,TemplateType,RegionName,Deviceenums. - Section DSL + registry + transformers —
AbstractSection,BladeSection,LivewireSection,Settingvalue object,Fielddescriptors,SectionRegistry, JSON ↔ runtime transformers, locale buckets. - Public renderer + fragment cache —
TemplateResolver(exact + dynamic routes),TemplateRendererwith per-section fragment caching,Regionrendering,PublicSiteController,SiteContextmiddleware. - Livewire editor shell —
EditorPage, plus Livewire componentsTopbar,SectionList,SettingsPanel,Canvas,AddSectionModal,PresetPicker;DraftStore,UndoStack,TemplateState,LocaleBucket,BroadcastPayloadBuilder,AutoSavePreference. - Iframe preview + postMessage bus + morphdom —
Editor/Protocol/Message+MessageType;resources/js/postmessage-bus.ts,iframe-injected.ts,editor.ts,keybindings.ts,layout-resize.ts,protocol.ts,tooltips.ts;AllowSameOriginIframeandInjectEditorScriptmiddleware;PreviewController,SectionRefreshController,TemplateRefreshController. - Filament resources —
SiteResource,TemplateResource,ThemeResource(each with List / Create / Edit pages), theFilamentCraftDashboardpage, and the form componentsColorSchemeTokensField,ColorSchemeGroupField,ColorSchemeGroupEditor,ColorSchemePicker,FontPickerField,IconPicker,TemplateUrlPicker. - Blueprints —
AbstractBlueprint,BlueprintRegistry,BlueprintSection,BlueprintSeeder,SeedResult,filamentcraft:seed-blueprintsartisan command, plugin-level registration API, locked / hidden section flags with sealed-list guards. - Theming —
ThemeRegistry,ThemeContract,filamentcraft:sync-themescommand, default token sets, font-picker integration with Bunny Fonts. - Multi-locale —
Localeshelper,LocaleAwareSectionsstate slice, empty-state UX (sidebar hint + canvas card), built-inHeadersection with locale switcher. - Built-in section catalog —
Headersection with mobile-safe wrapping classes. - Make commands —
filamentcraft:make-section,filamentcraft:make-theme. - Testing & gate — Orchestra Testbench base case, in-memory SQLite, 692 Pest unit + feature tests at 3043 assertions; Pint + PHPStan level 6
- Pest wired through
composer check; CI workflows for tests, static analysis, and committed JS/CSS dist parity.
- Pest wired through
- Demo app integration — end-to-end browser test suite running against
filamentcraft-demovia Pest 4 +pest-plugin-browser, covering the editor shell, save / publish, section CRUD, drag reorder at 3 viewports, device switcher, keyboard shortcuts, layout resize, breakpoints, file upload, public renderer, multi-tenant isolation, and locked / hidden Blueprint sections.
Notes
- This release ships without Anystack licence enforcement. The soft-degrade SDK + UX will land in 0.2.0. Until then the package is delivered as-is via the path repository in
filamentcraft-demofor internal verification. - Documentation (
filamentcraft.dev/docs) is not part of this release.
