Appearance
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]
[1.33.0]
Added
filamentcraft:customize-section. A guided command that searches the built-ins and generates an application-owned subclass — either an additive variant with its own slug, or an explicit application-wide replacement with--replace. The subclass inherits the built-in's settings, blocks, presets, defaults and behaviour, so only what you override changes.--copy-viewtakes ownership of the Blade markup too; leave it off and upstream view improvements keep applying.filamentcraft:doctorno longer warns about a slug override when the replacement is a subclass of the built-in — that is the supported shape.
Changed
- A section is only offered the look knobs its markup can answer to. All five knobs used to be appended to every section, so a stats row was asked for an image frame and a gallery for a card style even though those classes reach no element in that markup. Each built-in now declares its applicable set through the new
Section::lookKnobs(), and the editor's Look panel is the intersection — banner, footer and gallery show no Look panel at all. A custom section keeps all five unless it narrows them.- Arabic: the Look group read المظهر, the same label as every section's own style group, and is now الطابع; the image-frame knob reads نسبة الصورة, and the team section's style field no longer collides with the card-style knob.
[1.32.0]
Added
- The Locations section draws a real map. Give a location a latitude and longitude — pasted straight from Google Maps or OpenStreetMap, in either field, as a
48.8584, 2.2945pair, a place link, a#map=fragment or ageo:URI — and the section plots every one of them on a live slippy map with numbered pins that match the numbers on the cards. No API key, no account, no third-party JavaScript.- The server resolves the zoom that frames every pin, the tiles that cover the canvas and where each pin lands, then emits them as percentages. The map is correct with JavaScript switched off and never shifts layout; the site bundle then re-tiles at the element's real pixel width and adds drag-to-pan, zoom buttons, Ctrl/⌘ + scroll and double-click zoom. Plain scrolling always scrolls the page.
- Clicking a card's pin number centres the map on that location.
- A location with coordinates and no directions link gets one built from them.
map_tonere-skins the raster from the section's own palette:muted,tinted(duotoned into the scheme's primary and accent) ornight.map_sourceisautoby default and falls back coordinates → embed URL → image, so a site that only ever set an embed URL renders exactly as before.- The map now also renders in the cards-only layout, not just the split one.
filamentcraft.mapsconfig:tile_url,attribution,attribution_urlandmax_zoom. The default is OpenStreetMap because it needs no setup, but its tile policy is best-effort with no SLA and warns that commercial access may be withdrawn — so the URL template is config, not a constant, and understands{z},{x},{y},{s}and{r}for Stadia, MapTiler, Thunderforest or a self-hosted renderer. Settile_urlto an empty string and coordinates fall back to OpenStreetMap's own embed, still interactive, one marker.
[1.31.0]
Fixed
- The theme's color scheme is finally global. The "Default scheme" picker sits in the editor's global settings next to fonts, buttons and spacing — but it was the only value there that persisted onto the page you happened to have open, so picking a scheme restyled that one template and nothing else. It now lives on
Site.settings_json['color_scheme']alongside every other global setting, and every template, region and host-rendered shell page renders on it. Per-page variation stays where it belongs: a section's ownschemesetting. An idempotent upgrade migration promotes the scheme a live site already chose (its home page's, else the first page that carries one) onto the site row, so existing sites keep their look. - Host shell pages inherit the site scheme.
<x-filamentcraft::layout>andRendersInSiteShellreadSite.settings_json['color_scheme']— a key nothing wrote until now, so cart, checkout and account pages always rendered on the package default no matter what the operator picked. Passing:color-schemestill pins one page to something else. - The header / footer region editor previews on the site's scheme instead of a hardcoded default, so chrome is no longer authored against the wrong palette.
- The editor canvas repaints on a scheme change. A canvas refresh morphs
<body>only, so the scheme attributes on<html>kept their initial value — the same gapdir/langwere already patched for. All four attributes now sync from the refreshed document.
Added
filamentcraft:doctorwarns about stranded per-page color schemes — a site whose pages still ask for a scheme its own row doesn't carry never ran the promotion migration, so it is silently rendering on the package default. The warning names the site, the page and the scheme it wanted.SiteColorSchemes::activeFor()/::setActive()for reading and writing a site's global scheme from migrations, seeds, and host code.
Upgrading
Package migrations are published, not auto-loaded, so run this once to promote the scheme your sites already chose:
bash
php artisan vendor:publish --tag=filamentcraft-migrations && php artisan migratefilamentcraft:doctor tells you whether you need it.
[1.30.0]
Added
- Hover-inspector toggle in the editor topbar. Switches the whole canvas overlay layer off — hover outlines, the selected outline, both toolbars and click-to-select — so the preview reads as a plain page. The choice persists per browser and is re-sent on every iframe handshake, so a preview reload keeps it.
- Delete on sidebar section rows. A trash action on row hover, with a confirmation naming the section. Hidden rows keep their actions visible; locked rows get none.
Fixed
- The desktop canvas fills the available width instead of sitting in a fixed 1440px box between gutters. A window wider than the device width previews at its own width; a narrower one still lays out natively and scales down.
- Dark mode persists across pages inside the editor. The canvas now stores the visitor scheme override under an
:editor-suffixedsessionStoragekey, so the choice survives a page or region hop without ever touching the visitor's ownlocalStoragekey. - A republished preview bundle no longer serves stale JavaScript. The injected iframe script was versioned by package version while the parent editor script used file mtime, so republishing assets without an upgrade left the two halves of the bus at different vintages — a working feature read as completely dead in an open tab. It is now cache-busted by mtime.
- Repository prose (reports, docs) no longer leaks class names into the shipped
site.css; Tailwind's auto-detected sources are scoped to real render surfaces.
[1.29.0]
Added
- Per-section look variants. Five knobs on every section — card style, image frame, arrangement, corners and button weight — each emitting one class on the section wrapper so the built-in primitives re-skin from CSS alone. Two sites on the same section library can now look nothing alike. Every knob defaults to "Theme default", so nothing changes appearance until you pick one. Turn the panel off with
sections.look_variants => false; a section can also declare its own subset with theHasLookSettingsconcern. - Mobile filters on product listings. The filter rail becomes a sticky column on desktop and a bottom sheet on phones, with a Filters trigger carrying the active-filter count, a live result count, and clear-filters in both. Previously a phone visitor could not filter a catalogue at all. The sheet opens from a checkbox, so it works with JavaScript disabled; JavaScript adds the scroll lock,
Escape, focus trap and keyboard activation. - Optional mobile bottom navigation on the header.
show_mobile_nav(default off) renders the header's first four nav links as a fixed bottom tab bar on phones, respectingenv(safe-area-inset-bottom). It publishes a--fc-bottom-chromevariable that the watermark and toast host read so nothing stacks on top of it. - Cart event and toast bus.
FilamentCraft\Commerce\CartEventsowns the browser event names, so a host section and a built-in header can finally talk to each other.CartServicedispatches aCartUpdatedevent on every change, any[data-fc-cart-count]updates itself, and<x-filamentcraft::toast-host />ships the announcement region. RendersInSiteShellfor host-owned Livewire pages. Applies the same locale rule the public renderer uses (honour?locale=only when the site has that locale, never the browser's) and pins it across Livewire updates, so a visitor mid-checkout is no longer dropped back onto the site default.- Whole-card click affordance.
.fc-card--clickable+.fc-card__hit-area: a card clickable as a whole that still contains its own buttons, without nesting interactive elements in an anchor or faking it in JavaScript. SectionData::currentRecordKey()— what record the page is about. The product carousel now drops it by default, so a "related" row on a product page no longer leads with the product you are already looking at.--fc-card-media-ratio,--fc-cat-ratioand--fc-gallery-ratioso card and gallery frames can be re-themed by inheritance instead of inline styles..fc-tag--inlinefor reusing the pill as an ordinary in-flow chip.FILAMENTCRAFT_SOFT_DEGRADEenv switch for the attribution link.
Fixed
- Livewire sections now repaint in the editor preview. A
wire:idroot was skipped wholesale by the canvas morph, so everyLivewireSectionignored colour scheme, preset and setting changes until the iframe was reloaded by hand. The canvas now adopts the server's freshly rendered node and re-registers the component, and leaves it alone when only Livewire's own bookkeeping differs. - Dark mode survives a
wire:navigatehop. The pre-paint restore ran once and never again, so the first internal link dropped the visitor's choice back to light. It now re-applies onlivewire:navigated— and clears the override when nothing is stored, so a page can get back to light too. - Two scrollbars in the editor's settings rail. Filament renders toggle-button radios as
position: absoluteinside a static wrapper, so their containing block fell through to the rail, which then never clipped them and grew a second scrollbar next to the panel's own as soon as a settings group was expanded. - Card badges survive a hidden image frame. "Sale" / "New" / "Sold out" are anchored to the card instead of the media frame, so a card variant with no photography keeps its badge.
- Header icon controls meet the 44px touch target both platform vendors ask for, without changing their painted size.
[1.28.4]
Fixed
- Preview iframe now truly clips to the phone's rounded corners. The device shell is CSS-scaled, and under a transformed ancestor Chromium promotes the iframe to its own layer that ignores
border-radiusclipping — so the bottom bar still spilled over the bezel. The frame now usesclip-path, which clips the composited iframe layer reliably. Supersedes the 1.28.3 attempt.
[1.28.3]
Fixed
- Mobile/tablet preview no longer spills past the phone's rounded corners. Browsers don't clip an
<iframe>to its parent'sborder-radius, so the site's bottom bar and buttons overflowed the device mockup's rounded chin. The preview iframe now carries its own bottom corner radius.
[1.28.2]
Fixed
- Carousel arrows now point the right way in RTL. The prev/next chevrons were hard-coded left/right, so on Arabic and other RTL sites they contradicted the (already RTL-aware) scroll direction. The icons now mirror in RTL.
[1.28.1]
Fixed
- Tier reporting now works on installs that published the config file.
filamentcraft:installpublishesconfig/filamentcraft.php, and a file published before 1.28.0 has nopublic_keyentry — which shadowed the package default and left every key reading as untiered. The signing key now lives in code, with config as an override for anyone self-signing.
[1.28.0]
Added
- Your license key now tells you which tier it is. Keys issued from today carry their tier, signed so it cannot be edited, and
php artisan filamentcraft:doctorreports it —License allowance (Studio — 2 of 5 sites). Verification happens locally against a key shipped in the package; nothing contacts a server, as before. - Doctor warns when an install holds more sites than its tier covers, so an agency can see at a glance whether a project needs its own license.
Notes
- Nothing is enforced from this and nothing is blocked. Project counts are license terms. The count is per install, so it cannot see sites a license runs elsewhere — a ceiling would penalise a single multi-tenant install while missing an install-per-client setup entirely.
- Keys issued before this release carry no tier and report no ceiling. They keep working exactly as they did, forever; there is no need to reissue.
[1.26.1]
Added
- Edit a block straight on the canvas. Pointing at a block raises a small toolbar on it — drag to move, add space above or below, duplicate — each labelled on hover, so the common edits no longer need a trip to the structure tree.
- Dropping a layout onto a canvas that already has content adds a spacer between them, instead of stacking the two flush as one run-on section.
Fixed
- A custom section's settings are listed flat. Each block used to get its own collapsible group, so editing a three-card feature section meant opening nine cards to reach nine fields. Fields now sit in document order with the block's name on the field itself —
Heading, orButton · Labelfor a block with several editable props. Existing sections pick this up the next time they are saved. - An image uploaded in the builder now shows in the preview. Livewire reports a finished upload at its nested state path, which no control owned, so the file was discarded before it reached the draft — the section only picked the image up once it had been saved and placed on a page.
- The canvas drag handle sits on the block it drags. It is fixed-positioned but was offset from its static flow position, so it parked near the foot of the document no matter which block was selected.
- A custom section's hover label drops the type namespace — the canvas toolbar read
Custom::Get Startedwhere the section is just "Get Started".
[1.26.0]
Added
- No-code section builder. Editor users can now design their own section types in the browser — no PHP, no release. They compose one from 25 block primitives (or start from one of 24 curated layouts), arrange it on a live canvas or in a structure tree, style each block from theme tokens, and save it. The result lands in the Add section catalog beside the built-ins and can be placed as many times as you like, each instance holding its own content.
- The settings panel writes itself. Every editable prop bound while building becomes a setting on the saved section, grouped by the block it came from, so the person who builds a section and the person who fills it in do not have to be the same person. Rich text gets a rich editor, images an upload, icons the picker.
- Custom sections behave like built-ins. They are cacheable, honour colour schemes and Brand Kit limits, render per locale, and re-saving one bumps a version counter that folds into the fragment-cache key — so a section invalidates its own cached HTML without a manual flush.
- Fenced for untrusted operators. Definitions resolve only within their own site, trees stop at four levels and a configurable node cap, the HTML block's markup runs through the shared sanitizer with
<script>behind an opt-inallow_custom_code, and every control value is validated against its declared option set or numeric bounds before it reaches the tree. Deleting a definition that pages already place tells you how many first. - New docs page at
/guide/section-builder, withfilamentcraft:doctorauditing stored definitions.
Fixed
- Storefront layouts no longer collapse when the host ships its own Tailwind build. Both bundles emit the same utility names, and unlayered, a host's
.grid-cols-1landed after ourlg:grid-cols-4at equal specificity and won on source order — flattening every responsive section to a single column. The stylesheet now declares an explicit cascade-layer order, so our utilities beat a host's layered output while any unlayered host CSS still overrides us and deliberate storefront overrides keep working. - Abandoned builder drafts no longer consume a site's section allowance. A closed browser tab used to leave a draft row that counted against the limit forever; only saved sections count now, and stale drafts are swept.
- Uploading a file into a setting that cannot hold one no longer 500s with
Serialization of 'TemporaryUploadedFile' is not allowed. Draft values are sanitized through one shared path for both the builder and the settings panel. - An off-shape section icon can no longer take the editor down. The icon renders in the section rail on every load, so an unresolvable name is coerced back to the default rather than trusted.
- Closing a saved section from the builder no longer discards it. The back control is non-destructive once a section has been saved, and confirms only when there is unsaved work to lose.
[1.25.0]
Fixed
- The preview stays where you are working. Reordering, moving, hiding, or restyling a section no longer snaps the canvas back to the top of the page — the preview re-anchors to the section you are editing after every refresh.
- Auto-save is now off by default, with a longer debounce when you turn it on, so an editing session no longer writes a draft on every keystroke.
[1.24.0]
Added
- Per-locale headers, footers, and announcement bars. Regions are now locale-bucketed exactly like page content: each locale of a multi-locale site gets its own header/footer/announcement, editable independently through the same locale switcher, copy-from-locale, and empty-locale states the page editor already has. A locale you have not translated yet falls back to the default locale's region on the public site, so nothing renders blank.
Fixed
- Existing regions upgrade in place. A shipped migration wraps every stored region's current content into its site's default-locale bucket, so live sites keep rendering unchanged and pick up per-locale editing without data loss. The renderer also tolerates an un-migrated region, so a host that updates the package but delays
php artisan migratenever 500s.filamentcraft:doctornow flags any region still on the legacy shape.
[1.23.0]
Added
- Gate who can open the builder. A new
canAccessUsing()plugin setter takes a closure — passed the authenticated user — that decides whether the builder is reachable. When it returnsfalsethe dashboard, the editor, and the advanced resources all drop out of navigation and return403on direct URL access, so a plan/licence/Gate check has a single wiring point with no bypass. Omitting it leaves the builder open to every panel user, as before.
Fixed
- A missing
filamentcraft_sitestable no longer 500s the whole panel. On a host that registered the plugin but had not yet runfilamentcraft:install, navigation rendering resolved a site on every page and threw an uncaughtQueryException, taking down every panel route — not just the builder. Site resolution now probes the table first and degrades to "no site" instead.
[1.22.0]
Added
- In-editor preview link navigation. Clicking a storefront link in the editor canvas — a product card, a category tile, or a Shop / Cart / Checkout button — now switches the editor to the page that renders it and previews the clicked record, instead of the click being swallowed. The destination page is resolved from the sections each page contains (a Product Detail section marks the product page, Cart the cart page, Product Listing the shop/category page), so it needs no configuration; product and category links carry the clicked slug so the destination previews that exact record, and the topbar page dropdown re-syncs automatically.
[1.20.1]
Fixed
- Doctor's primary-domain warning was misleading. It claimed an empty
filamentcraft.domain.primarydegrades "subdomain resolution". Inbound subdomain matching readsAPP_URL's host and never touches that key —domain.primaryonly affects generated public URLs. The warning now says so. install --foliooverstated what it does. Its help text and console output claimed it wires Folio routing; it scaffoldsresources/views/storefront/and prints theFolio::path(...)line for you to register yourself. Text corrected — behaviour unchanged.- Stale docblocks on
SiteThemeSettings(reserved keys) andFontCatalog(font count).
Documentation
- Audited every docs page against source and fixed 35 false or misleading claims. The material ones: the install guide promised Templates/Editor sidebar entries that need
->showAdvancedResources()(off by default); the public-routing guide told you to setdomain.primaryfor wildcard subdomains, which silently resolves the wrong tenant whenAPP_URLdiffers; the cache reference had taggable stores backwards (arraycaches,file— Laravel's default — does not); the editor guide documented a right settings column and "New page"/"Manage" controls that don't exist; andonly([...]),FontCatalog::flush(), andRange::unit()were documented with signatures that throw or don't reach CSS.
[1.20.0]
Added
- SEO & GEO pack. Server-rendered SEO and AI-search optimisation as a first-class feature:
/sitemap.xml(honest lastmod + hreflang alternates),/robots.txtwith a per-site AI-crawler policy,/llms.txt, and IndexNow submission on publish — all registered only whenpublic_routesis on and each toggleable underfilamentcraft.seo. Per-page SEO lives in the editor (Search engine + Social tabs with live SERP/share-card previews, canonical override, indexing toggle) and is stored per locale ontemplates.seo_json. Site defaults (title suffix, description, share image, organisation profiles, staging noindex) live in Site settings → Search & AI. All head output flows through oneSeoResolverchokepoint (Open Graph, Twitter card, hreflang, JSON-LD). Renaming a slug offers a chain-collapsing 301 redirect. Answer bots are never blocked — only training bots are toggleable. - Doctor overhaul.
filamentcraft:doctornow runs ~35 grouped checks (Environment / Database / Panel / Configuration / Themes / Sections / Content / SEO / Assets / License) with--jsonfor CI and--strictto fail on warnings. New diagnostics include: upgrade-migration columns, wrong-typed config values (quoted.envbooleans), tenancy wiring (mode / owner model /single_site_id), cache store existence + tag support, uploads disk + php.ini upload limits, published pages and regions referencing unregistered section types, legacy payloads, published templates without a revision, commerce sections without aStorefrontbinding, stale published assets after an update, missing Vite manifests, and the SEO gaps above. Doctor also boots each panel's plugin so console runs see the same section/theme registries as browser requests. Color::allowAlpha()now works. The modifier switches the compiledColorPickertorgbaformat so end users can set an opacity; the color transformer readsrgba(…)/rgb(…)strings back into aColorValue(with->alpha). It was previously a no-op.RichText::inline()now works. An inline rich-text setting compiles to aRichEditorwith a reduced toolbar (bold, italic, underline, strike, link) and no block-level tools — for short fields like an eyebrow or caption. It was previously indistinguishable from the full editor.
Fixed
- Host section shadows are now stable across panel and public boots. A host section sharing a builtin slug used to win on public routes but lose on panel routes (the editor rendered a different class than the live site), because panel boot blindly re-registered every builtin. Builtins now register only when the slug is free, and disabling them only forgets slugs the builtin itself still holds.
- A misconfigured
filamentcraft.cache.storename degrades to uncached rendering instead of erroring on every cached section render. Doctor reports the bad store name. - An unknown public path now 404s instead of falling back to the home template, so a typo'd URL can never be indexed as duplicate homepage content.
Removed
- Dead
enable_dark_mode_togglesetting on the Studio theme. The checkbox affected nothing — the visitor scheme toggle is gated by each section'sshow_scheme_toggle— so it and its translations were removed.
[1.19.1]
Fixed
- No per-request log noise for valid configurations. The v1.19.0 runtime warnings for unregistered theme slugs and section slug overrides fired on every render for legitimate setups (token-only Theme rows, intentional built-in shadowing). Both diagnostics now live in
php artisan filamentcraft:doctorinstead: orphan theme rows keep their WARN (with a note that token-only rows are fine), and the section registry records slug overrides that doctor reports with both class names.
[1.19.0]
Added
php artisan filamentcraft:doctor. One command that diagnoses the whole installation — migrations, panel plugin wiring, registered themes vs. Theme DB rows, orphaned theme slugs, live sites (and published homepages whenpublic_routesis on), the storage symlink, and published editor assets — printing a remediation hint under every failed check.php artisan aboutintegration. The Laravel about screen now reports the installed FilamentCraft version, registered theme/section counts, tenancy mode, public-routes state, and whether a license key is set.- Enum options for
SelectandRadio.->options(MyEnum::class)now works the way Filament's own fields do — values come from the backed enum, labels fromHasLabel(falling back to headlined case names). ->helperText()on every setting as a Filament-familiar alias of->info().- Interactive example seed. A bare interactive
filamentcraft:installnow offers to seed the example site so first-time users land on a working page.
Changed
- A broken section can no longer take down the whole page. If a registered section throws while rendering (missing Blade view, bad code), the editor preview shows a "failed to render" card naming the error; published pages report the exception and skip the section. Intentional
abort()s still propagate. - Silent failures now speak. Unknown theme slugs log a warning naming
filamentcraft:sync-themes; section slug collisions log both class names; the public 404s explain what to publish/create;Setting/Blockid validation errors describe the rule in plain language with an example. - Install and make-commands guide the next step. Install names the exact panel-provider file to register the plugin in, points to
filamentcraft:starteranddoctor, and skips DB-dependent steps when migrations are declined;make:filamentcraft-sectiononly claims auto-discovery when the class actually lands inapp/Sections;make:filamentcraft-themeprints the requiredsync-themesfollow-up. - Config cleanup. Removed five dead keys (
prefix,route_prefix,routes.public_locale_fallback,assets.dist,themes.paths) and documentededitor.enabled,cache.ttl/tag_prefix, anddomain.primary. - Complete IDE autocomplete. The
FilamentCraftfacade docblock now covers the navigation setters, blueprint registration, advanced-resources toggle, and the correctviteBuild()signature.
Fixed
Section::defaults()implementations that omit thesettingsorblockskey no longer crash the Add-section modal or blueprint seeding.LivewireSectionwithout a$viewnow fails with the same descriptiveLogicExceptionasBladeSectioninstead of a framework error.
[1.18.0]
Added
- Host locale URL strategies (
localeUrlsUsing). Hosts that resolve the visitor locale from their own routing (locale-prefixed paths, sub-domains) can now register a closure —FilamentCraftPlugin::localeUrlsUsing(fn (Site $site, string $locale, bool $isDefault): ?string)— and the built-in header language switcher plus everyLocaleAlternateconsumer (hreflang tags, the<x-filamentcraft::locale-switcher>component) emit those URLs instead of the default?locale=xxquery strategy. The header section turns fragment caching off while a resolver is registered, since host URLs are path-dependent.
Fixed
- Sections now render (and cache) in the requested locale.
__()calls in section views that omitted the explicit locale argument resolved against the app locale, so a?locale=frpage rendered — and per-locale fragment caching then froze — English strings ("Most popular", "Learn more", nav aria labels).SectionRenderersets the app locale for the duration of every section render and restores it afterwards. - Header locale dropdown closes on outside click and Escape instead of staying open until the trigger is clicked again.
- Checkout shipping fee can no longer be tampered with. The shipping fee / free-shipping threshold the checkout section posts as hidden inputs are now HMAC-signed (
ShippingSignature); a devtools edit that zeroes the fee (or strips the fields) rejects the order instead of placing it with free shipping. - Checkout re-validates the cart against the live catalog. Lines whose product disappeared after add-to-cart no longer reach the host's
placeOrder()(previously they could crash checkout or place mismatched orders), and a line that has gone out of stock since being added rejects the order — mirroring the guardaddalready enforced. - Checkout form field ids are namespaced per section instance (
fc-co-name-{sectionId}), so two checkout sections on one page keep valid label associations. - A paused site's custom domain fails closed.
DomainResolverno longer falls through to the subdomain lookup when a non-live site claims the exact domain — previously an unrelated live site with a matching subdomain could be served under the paused site's host. - In-flight setting edits survive editor navigation. A settings-field edit still inside its 400 ms commit debounce was lost when the next click switched the locale, page, or site; pending commits now flush on pointerdown before any navigation handler runs.
[1.17.1]
Fixed
- Checkout success page 500 on newer Blade compilers. The checkout view mixed
@php(...)inline directives with@php … @endphpblocks; on recent Laravel versions two consecutive inline directives after a block mis-compile into aParseError. All inline@php(...)in the checkout view now use the block form.
[1.17.0]
Added
- Visitor dark-mode toggle. The Header and Footer sections gained an opt-in sun/moon switcher (
show_scheme_toggle) with inline or floating-button placement. Clicking it flips adata-fc-scheme-overrideattribute on<html>—DesignTokenCompilernow pre-renders a pure-CSS override layer for every scheme, so the whole page (pinned sections included) re-tokens to the dark scheme with no framework JS. The choice persists inlocalStorageand a pre-paint script in the layout head restores it before first paint (no light flash). Accessible (aria-pressed, focus ring), RTL/safe-area-aware floating variant, reduced-motion-friendly transitions, translated in all seven locales, and documented in the Color Schemes guide. The persisted choice is scoped per site, the editor canvas ignores it (authors always see the authored scheme), and floating buttons reparent to<body>so a sticky header'sbackdrop-filtercan't trap them.
[1.16.2]
Fixed
- Banner/announcement section wrapped awkwardly on narrow screens. The icon broke onto its own line above the text and the floating pill's
rounded-fulldeformed once the copy wrapped. The icon now stays inline with the (centered) text, and the floating card hugs its content with a softer radius on small screens (rounded-2xl→rounded-fullfromsm:).
[1.16.1]
Fixed
- Mobile/tablet preview squashed on short screens. The device mockup was sized with
min(100%, …), so a small viewport height shortened the phone and distorted its aspect ratio. The mockup now renders at its native size and CSS-scales down uniformly to fit the canvas (the same transform approach the desktop shell uses), with a small gutter for its drop shadow. Tall screens still cap at the device's native size.
[1.16.0]
Added
- Canvas section hover toolbar. Hovering a section in the editor preview now draws a teal outline with a floating toolbar — section name chip plus edit, move up/down, duplicate, hide, and delete — so sections can be managed directly on the canvas without the sidebar. Move buttons disable at the first/last position, locked sections expose only the name and edit, and the selected section keeps a persistent outline + toolbar (the editor now sends
section:selectto the iframe; its handler previously never received it). section:toggle-hiddenprotocol message and adata-fc-section-lockedwrapper attribute backing the new toolbar.
Changed
- Sidebar section rows slimmed down. The per-row hover actions (hide, move, duplicate, delete) moved to the canvas toolbar; rows show just the drag handle and label. Hidden sections don't render in the canvas, so their row keeps an always-visible "show" toggle as the way back.
Fixed
- Settings panel crashed for image settings stored as URL strings. Stored image values support a plain URL string or a
{path, alt}map, but both reached Filament'sFileUploadraw state unwrapped and fataled inBaseFileUpload::getUploadedFiles()(foreachon a string). Image-typed values — in section settings and repeater blocks — are now coerced to the file-list shape on hydration, with regression tests for both shapes.
[1.15.0]
Fixed
- Cart quantity update crashed with a
TypeError. The storefront cart's quantity stepper postsqtyas a string;CartController::update()passed it straight intoCartService::setQty(int $qty), and underdeclare(strict_types=1)PHP refused the coercion. Quantities now cast at the boundary (matchingadd()andcheckout()), with regression tests covering both the increment and the quantity-zero-removes-the-line paths.
Improved
- Every built-in section now honours every setting it exposes. A full audit of all 32 sections closed the gaps where a control was declared but did not change the render: the four
shapevalues (clean / contained / layered / wireframe) now render four visibly distinct treatments in every section and are independent ofsurface_style/surface/media_placement; product-listingcolumnshonours its4option; the logo wall'stoneapplies to text logos, not only images;densitynow scales card padding on mobile, not just desktop; and several other option values that previously rendered identically are now differentiated. - Cleaner empty states. Clearing a heading, label, or announcement no longer leaves a broken empty element — primary text nodes across the pack collapse gracefully, matching the established
data-fc-hide-emptypattern. - Contrast, accessibility, and polish. Removed hardcoded hex colours in favour of theme tokens (contact, store-hero, video); the store-hero banner stays legible when no image is set; product galleries show an active-thumbnail state; disabled buttons no longer animate on hover; the eyebrow hairline is RTL-correct; and imageless media tiles share one refined monogram placeholder instead of a faint icon. The site header CTA now uses the primary-button primitive, and a sticky header respects surface shapes.
[1.14.0]
Added
- Eleven new built-in sections — the most-used blocks from every major builder.Team (profile cards / large portraits / minimal list, socials, initials fallback), Gallery (grid / masonry / carousel, ratio + caption controls), Timeline (horizontal steps / vertical rail / alternating sides, number / icon / dot markers), Video (YouTube / Vimeo / file; privacy-friendly
youtube-nocookieembeds, lazy-loaded, with a JS-freesrcdoccover facade), Articles (card grid or featured + list), Portfolio (grid or featured case study, result-metric badges), Tabs (underline / pills / boxed, top or side placement, full W3C APG tablist semantics with a stacked no-JS fallback), Comparison (semantic 2–3 column table, highlightable "us" column, yes/no/free-text cells), Countdown (live-ticking tiles, expired state, cache-exempt), Locations (map embed with a strict URL allowlist + location cards), and Announcement Bar (full-width bar or floating pill, brand / surface tones, dismissible with per-section persistence). Every section ships Content / Layout / Style controls, four family presets (modern/editorial/bold/elegant), believable defaults, and names translated into all seven bundled languages. - Reusable carousel primitive.
<x-filamentcraft::carousel>+<x-filamentcraft::carousel.slide>wrap any section content in the same accessible, dependency-free scroll-snap carousel the product carousel uses: W3C APG region/slide semantics, arrow controls, new dot pagination (grouped-button pattern), keyboard-scrollable track,scroll-snap-stop, RTL-aware navigation, and reduced-motion support. Slides-per-view and gap are per-instance CSS variables. - Carousel layouts for existing sections. Testimonials and Logo Cloud gained a
Carousellayout option, and the Team, Gallery, and Product Carousel sections ride the same primitive. - Storefront JS modules (all progressive enhancement, zero dependencies): APG tabs (roving tabindex, RTL-aware arrow keys, Home/End), countdown ticker, and banner dismissal backed by
localStorage.
Changed
- Style-control parity for commerce and form sections. Cart, Checkout, Contact, Newsletter, Category Grid, Product Listing, Product Carousel, and Product Page now expose the same
Densitycontrol as the content sections (their vertical rhythm was previously hardcoded), and the Contact textarea now uses the.fc-inputprimitive. - Stats
Bandlayout is now a real band — a single shared surface with divided, centered figures — instead of rendering identically to the grid. - Carousel slides upgraded to APG semantics (
role="group"+aria-roledescription="slide", labelled track) and the track is keyboard-focusable. - Leaner settings-panel helper text. Field hints now appear only where the behaviour is non-obvious (magic values, constraints, hidden interactions) and are kept to one short line, instead of restating the label. Trimmed or removed across Hero, Store hero, Video, Cart, Gallery, Banner, Comparison, and Locations.
- Stronger defaults for the new sections. Gallery blocks that carry a caption but no image now render as designed gradient tiles on the live site (fully empty blocks are still skipped; the dashed upload hint remains editor-only), gallery ships six starter tiles, and Tabs panels default to the contained card frame with the tab's icon leading image-less panels.
Fixed
- Locations split layout no longer overflows the section. Cards in the map + cards layout stretched to the full grid-row height and painted over whatever came after the section; full-height cards now apply only in the cards-only grid.
Removed
- The hero's
Custom paddingcontrol. Vertical rhythm is owned by theHeightpresets (compact / comfortable / airy) like every other section; a per-section free-form padding override fought the page rhythm and the theme's section-spacing token. Stored values from existing sites are ignored harmlessly. (TheSpacingsetting type itself is unchanged and remains available to custom sections.)
[1.13.1]
Added
- Accessible product-carousel controls. The product carousel now ships keyboard- and screen-reader-friendly previous/next controls (labelled, focus-managed,
aria-wired and translated into all seven bundled languages), with a config toggle and the supporting CSS/JS.
[1.13.0]
Added
- E-commerce section pack — turn any FilamentCraft site into a storefront. Seven new built-in sections: Store hero, Category grid, Product carousel, Product listing (with server-side category / price / sort / search filters), Product page, Cart, and Checkout. They are fully data-driven — you choose what to show (a collection, a category, a limit), never the product data itself.
Storefrontcontract + DTOs (ProductData,CategoryData,CatalogQuery,OrderResult,CustomerDetails). Bind your own implementation over your Eloquent models to feed the sections; the package shipsNullStorefrontas the default so the sections degrade to a tidy "connect your catalog" empty state until a store is wired.- JS-free session cart + cash-on-delivery checkout.
CartService(session, namespaced per site) stores only product references — prices always resolve server-side from theStorefront, never the client. Plain form-POST cart routes (filamentcraft/cart/{add,update,remove,checkout}) work with no client runtime and never trip Livewire's stateless-update 419. Checkout places the order viaStorefront::placeOrder(). - Commerce CSS primitives in
site.css(fc-product-card,fc-price,fc-tag,fc-ratingstars,fc-qty,fc-option/swatch, CSS-onlyfc-gallery,fc-filter,fc-chip,fc-summary,fc-cartbar,fc-pay,fc-steps) — token-driven, RTL-safe, reduced-motion aware, no hover-scale. Images degrade to a designed gradient placeholder. - Storefront UI strings (
commerce.*) translated across all seven locales.
Added (core)
Section::cacheable()(defaulttrue). The renderer skips the fragment cache for sections whose output depends on the request (filters), the session (cart), or a fresh CSRF token (forms) — the listing, product, cart and checkout sections opt out.
[1.12.2]
Changed
- The
elegantstarter family now has a simple header and richer content. The header is a single-row split layout (brand left, nav + one CTA right) instead of a tall stacked centered block; the capabilities section is six considered editorial cards instead of three sparse tiles; and the testimonials section shows three quotes instead of one. Only the elegant family changes.
[1.12.1]
Fixed
- The
elegantstarter family read as sparse and empty. It now uses comfortable (not airy) density, contained section shapes (real card structure instead of borderless surfaces), and a cards features layout — so the minimal premium aesthetic looks intentional rather than unfinished. The other three families are unchanged.
[1.12.0]
Added
- Preset-driven starter sites in four style families. Every built-in section now ships four aligned presets —
modern,editorial,bold,elegant— sharing slugs across all sections, so picking one family yields a cohesive, on-brand site. A new parametricStarterSiteBlueprint::seed(StarterFamily::Modern, $owner)provisions a complete, published seven-section homepage (hero → logo cloud → features → stats → testimonials → pricing → CTA) plus matching header and footer regions in a single line — the one-liner DX for a tenant-created hook. StarterFamilyenum (value doubles as the shared preset slug; ships label/color/icon contracts and::options()for Filament selects), thefilamentcraft:startercommand, the idempotentStarterSiteSeeder, and thefilamentcraft.starter.familyconfig key.BlueprintSection::fromPreset()andPreset::findIn()— fill a blueprint section from a section's own family preset; the editor's preset picker reuses the same lookup.- Multilingual storefront primitives. New
<x-filamentcraft::hreflang>(emitsrel="alternate"+x-defaultSEO tags) and<x-filamentcraft::locale-switcher>(a visitor-facing, RTL-aware, theme-token-styled language switcher with native labels), backed by theFilamentCraft\Support\LocaleAlternatevalue object / builder andLocales::nativeLabel(). Both render nothing for single-locale sites and support custom URL strategies via anurlForclosure (path-prefix, query-param, sub-domain). - Reworked editor language switcher. Full keyboard accessibility (Arrow/Home/End, type-ahead, Escape-returns-focus, roving
tabindex,role="menu"),aria-currenton the active locale, live translation-status (an Empty tag on untranslated locales, an "N of M translated" header, an amber pip on the trigger), an RTL badge, an unsaved-changes confirmation before switching, a copy-content-from-any-language modal, and a Manage-languages shortcut. - Localization & RTL guide in the docs, plus a multilingual feature card and differentiator keywords on the docs home page.
Changed
- The six bundled translation files (
fr,es,de,pt,ja,ar) are back to full key parity with English (they had drifted ~46% behind, rendering raw translation keys in the editor for non-English admins). A new parity test guards against future drift. - Active-locale resolution is centralised in a shared
InteractsWithLocaleeditor concern, removing the same logic that was duplicated across six Livewire components.
Security
- The editor active locale (
?locale=) is now re-clamped to a site-opted-in code on every request, not just on mount — closing a vector where a tampered locale could persist an unsupported locale bucket into a template'ssections_json. Copy-source locales are validated against the site's configured languages as well.
[1.10.2]
Added
- Configurable editor control density. A new
filamentcraft.editor.control_sizeconfig (compact|comfortable|spacious, defaultcomfortable) sizes the settings-panel enum/toggle-button controls. The value is projected onto the editor root asdata-fc-control-sizeand drives--fc-ctl-*CSS tokens.
Changed
- Settings-panel enum buttons are more compact by default. Filament's full-size toggle buttons made a 4-option enum (e.g. section Shape) dominate the narrow rail; the comfortable default is tighter while staying readable, and
control_sizelets you go smaller or larger.
Fixed
- Save / Publish actions were pushed off the right edge. Below 1100px the editor topbar reserved ~6.75rem of right padding for the fixed focus-exit button — but the topbar is
display:nonein immersive mode (the only state where that button shows), so the reservation just left the Discard/Save/Publish buttons floating ~100px short of the edge. They now sit flush at the end at every width.
Fixed
- Single-site dashboard empty state rendered a full-screen icon. The Website Builder dashboard's "set up your first site" empty state styled its heroicon with Tailwind utility classes (
h-7 w-7, etc.). Filament v4 ships precompiled CSS and does not run Tailwind over a plugin's published Blade views, so in a consuming app those classes no-op'd and the icon (an SVG with no intrinsic size) filled the viewport. The dashboard view is now self-contained with inline styles (and Filament's primary CSS vars), so it renders correctly without the host compiling the plugin's Tailwind. Multi-tenant panels were unaffected because a tenant always resolves a site.
[1.10.0]
Added
- Premium section design layer. A reusable, token-driven set of
fc-*primitives now powers a master-grade default look across every built-in section: premium card surfaces with a hairline ring and soft hover lift, tinted icon tiles, badge-style eyebrows, gradient stat numbers, a gradient-ring "most popular" pricing card, decorative radial/mesh/dot-grid backgrounds and aura glows, premium primary/secondary buttons with a focus ring, a pure-CSS logo marquee, and load-in reveal animations. Every effect derives from the--fc-color-*theme tokens (so it tracks any palette and per-section color scheme), is pure CSS (the storefront ships no JS), is gated behindprefers-reduced-motion, uses no hoverscale(), is RTL-safe, and defaults to a light/modern look. - Logo-cloud "Marquee (auto-scroll)" layout — an infinite, seamless, hover-pausing logo strip with edge fade, alongside the existing grid and single-row layouts.
Changed
- Every built-in section redesigned to a master-grade default. Hero (aura glow, badge eyebrow, premium CTA, refined split-media frame), Features (icon tiles, hover-lift cards, staggered reveal), Stats (gradient numerals, tabular figures), Logo cloud (correct monochrome→color hover + marquee), Pricing (elevated gradient-ring "popular" card, bottom-aligned CTAs, tinted check rows), Testimonials (quote-mark accent, avatar ring), FAQ (refined accordion with open-state highlight and a progressive
::details-contentheight animation), CTA (glow + gradient-ring card), Image-Text (premium media frame), Newsletter/Contact (glow card, focus-ring fields), Rich-text and Footer polish.
Fixed
- Emoji / short-glyph section icons now render. The icon component called
svg()for every value and silently dropped anything that wasn't a registered icon name, so emoji-based icons (e.g. ⚙️) in built-in section defaults rendered as empty boxes. Short non-icon glyphs now fall back to a centered text glyph; longer unresolved names still render nothing (to avoid printing a mistyped icon name). - Focus mode no longer squashes tablet/mobile previews. Entering full-page focus mode hides the editor topbar via
display: none, which dropped it as a grid item and let the canvas body auto-flow into theautorow and collapse to content height — shrinking tablet/mobile device frames (whose height resolves frommin(100%, …)) to the iframe's intrinsic ~150px. The outer-grid children are now pinned to their rows so the body always fills the1frtrack. Desktop was unaffected.
[1.9.3]
Changed
- Command palette polish. Typing now jumps the highlight back to the best match (so Enter runs the right command), recently-used commands surface at the top when the search is empty, Tab / Shift+Tab move the selection, long labels truncate instead of wrapping, and the panel sizes down on small screens.
Accessibility
- The command palette is now a proper combobox/listbox (
aria-activedescendant), so the highlighted command is announced as you arrow through it; its results list has an accessible name. The editor settings slide-over's Page/Site groups are wired to their labels (role="group"+aria-labelledby). Fixed a brief sun-icon flash on the color-scheme toggle during light-mode loads.
[1.9.2]
Changed
- The ⌘K command palette now shows a per-command icon next to each entry, making it quicker to scan.
[1.9.1]
Added
- The ⌘K command palette is now discoverable. A search button in the editor toolbar opens it (with a
⌘Ktooltip), and the keyboard-shortcuts help panel (?) now lists it.
[1.9.0]
Added
- A ⌘K / Ctrl+K command palette in the editor. Press ⌘K to fuzzy-search and run any of the editor's actions from one place — add a section, change theme, page/site settings, new/duplicate/ delete page, new site, all pages, open live, save, publish, undo/redo, switch device, toggle auto-save. Full keyboard control (↑/↓ to move, Enter to run, Esc to close), focus-trapped, and styled in the builder's own dark UI. Built on the existing actions — no new server behaviour.
[1.8.0]
Changed
- The builder-native dialog skin now covers the editor's toasts and dialog section cards too. Filament notifications (save/publish/auto-save toasts) and the section cards inside action dialogs now use the builder's panel tokens, so nothing in the editor's chrome falls back to default Filament styling. Still scoped to the editor only and light/dark-aware.
Accessibility
- The ⚙ settings slide-over now traps focus while open (focus moves into the panel and stays there until you close it), matching expected dialog behaviour for keyboard and screen-reader users.
[1.7.0]
Changed
- The editor toolbar's page/site actions are consolidated behind one ⚙ Settings control. The separate "New page" (
+) and "Manage" (⋯) buttons are replaced by a single gear that opens a builder-native slide-over grouping every page and site action (page settings, new/duplicate/delete page, all pages, site settings, change theme, new site). Save, Discard, and Publish stay as labelled buttons. - Action dialogs now match the builder. Filament's modals and slide-overs opened from inside the editor are skinned with the builder's own design tokens (scoped to the editor only, so the rest of the panel is untouched), so changing a theme or editing site settings no longer drops you into a differently-styled dialog. The skin tracks the editor's light/dark scheme.
Changed
- The "Website builder" nav item now opens the editor directly on the site's homepage. The builder already owns page/site/theme management, so the intermediate list page is no longer the landing —
getNavigationUrl()routes to the homepage template's editor, falling back to the dashboard for first-run (no homepage yet). The list remains reachable from the editor's Manage (⋯) → All pages. - The editor's "Open live page" control is now icon-only to reclaim toolbar space; the destination URL is shown on hover (tooltip +
aria-label) instead of as always-on text.
Added
- Change theme and All pages in the editor's Manage (⋯) menu — switch the site's theme (reloads the canvas) and jump to the page-management list without leaving the builder.
- Editor toolbar polish: equal square hit-areas for the icon-only URL controls, a pressed/open state on the New-page and Manage menu triggers, a subtle press feedback and a unified focus-visible ring across all toolbar icon buttons, and a hover cue on the live-page icon. The disabled (unpublished) live link keeps its explanatory tooltip. The view-controls toolbar group gained an accessible name.
Accessibility
- Newsletter + Contact sections: form errors are now programmatically associated with their inputs (
aria-invalid/aria-describedby), success messages are announced viarole="status"live regions, the submit button keeps a stable accessible name while loading, and inputs carryautocomplete/inputmodehints.
Developer experience
- Section stubs (
make:filamentcraft-section) now ship commentedcategory()/description()/blocks()/presets()examples so those features are discoverable from the generated file. - The testing reference gains a concrete
Event::fake()assertion snippet for the shipped section events.
[1.5.0]
Fixed
LivewireSectionwire actions now hydrate on the published storefront instead of failing with a 419 "page expired". ALivewireSectionrenders viaLivewire::mount(), which stamps the snapshot with the component's conventional (FQCN-derived) name — but that name was not resolvable back to the class on the stateless/livewire/updaterequest, so the firstwire:click/wire:submitreturned 419 and the section appeared frozen on the live site. The section registry now registers everyLivewireSectionunder a stable Livewire alias (filamentcraft-section.{slug}) at registration time (which runs on every request), so mount and update agree and the round-trip hydrates. Affects any interactive section, built-in or host-app.
Added
- Two shipped interactive sections — Newsletter (
newsletter) and Contact form (contact). FilamentCraft previously shipped only staticBladeSections; these are the first built-inLivewireSections. Both validate their input, show a success state, and are enabled by default in the Add Section catalog (honoring thebuiltin_sections_enabledopt-out). They double as the canonical copyable reference for building your own interactive sections. - Event extension points for the interactive sections. On submit, Newsletter dispatches
FilamentCraft\Events\NewsletterSubscribedand Contact form dispatchesFilamentCraft\Events\ContactFormSubmitted. With no listener they are harmless no-ops (the visitor still sees the success message); add a listener to persist the subscriber, send mail, or forward to a CRM. Each event carries the submitted values, the resolvedSite(if any), and the section id. SectionDataFactory::test()testing helper. Builds theSectionDataand mounts aLivewireSectionas a LivewireTestablein one call, so consumers can drive a section's wire actions without the explicitLivewire::test(..., ['section' => ...])wiring. Throws for static sections (usemake()there). Documented in the testing reference.
[1.4.0]
Fixed
- The storefront shell now ships Livewire's frontend runtime when a page needs it. Published pages render through a plain
view()->render()(not a full-page Livewire response), so Livewire's automatic asset injection never fired — aLivewireSection(or aBladeSectionthat embeds a Livewire component) painted its initial HTML but had nolivewire.js/Alpine to hydrate it, leavingwire:click,wire:loading, andwire:modeldead on the live site. The renderer now detects interactivity (wire:orx-data) in the assembled header/body/footer and conditionally emits@livewireStyles@livewireScripts(Alpine ships inside the Livewire bundle, so Alpine-only sections work too). Purely static marketing pages stay JS-free. Manual injection also suppresses Livewire's auto-injection, so there is no double-load.
Added
<x-filamentcraft::layout>injects the Livewire/Alpine runtime by default. Custom dynamic pages mounted in the shell (cart, checkout, account, full-page Livewire components) are interactive by nature, so the component defaults to injecting the runtime. Pass:livewire="false"to opt a purely static custom page out.
[1.3.0]
Fixed
- Interactive
LivewireSections now round-trip. A section extendingLivewireSectioncould render its first paint but threw "Property type not supported in Livewire" on the first wire action, because the injectedSectionData(and its nestedRenderContext) was not Livewire-serializable. Both now implementLivewire\Wireable:SectionDatadehydrates to a primitive payload and rebuilds throughSectionData::fromArray()(re-resolving the section class,Site, settings, blocks, locale, and color scheme), andRenderContextround-trips route-model bindings as a morph alias + key.wire:click/wire:submitactions on aLivewireSectionnow work, with$sectionintact after every request.
Added
- Docs + test coverage for interactive sections. New Interactive sections (Livewire) guide (including the Livewire/Alpine asset story) and a testing recipe that drives a wire action with
Livewire::test(), plus suite coverage that exercises aLivewireSectionround-trip and the newWireableserializers.
[1.2.1]
Changed
- Spacing input — faithful to the Bagisto Visual spec. The four-sided control now infers its link state from the data when no link flag is stored (all sides equal ⇒ linked), so a plain
{top, right, bottom, left}map (the Bagisto storage shape) imports without silently re-syncing asymmetric values. Negative values are fully supported for margin controls (Spacing::make('margin')->min(-80)), andSpacingValueexposes each side as a rawfloatproperty ($pad->top) alongside the unit-suffixed->top()method and->css()shorthand.
[1.2.0]
Added
- Self-contained editor — in-editor page & store management. The editor topbar gains a New page button and a Manage menu to create, edit, duplicate, and delete pages and edit store settings without leaving for the Sites/Templates resources. Built on Filament action modals wired into the topbar (
<x-filament-actions::modals/>), with a safe delete that reassigns the homepage pointer, refuses to remove the last page, and redirects to a sibling. - Spacing setting type. Four-sided padding/margin control with per-side inputs, a link/lock toggle, and min/max/unit options; renders to a CSS shorthand value.
- Gradient setting type. Linear/radial gradient editor with a live preview, angle dial, and color stops. Stop colours are restricted to hex or
var(--fc-color-*)token references so a gradient can track the active scheme. - Hero now exposes a background gradient and custom section padding, and its accent override genuinely recolours the eyebrow and call-to-action.
Fixed
- Settings panel could discard a sibling's structural change. It now reloads the shared draft before persisting a setting/block/page-style edit, so a just-added/removed/reordered section is never clobbered.
- Dashboard cross-tenant write. The resolved site is now
#[Locked]and re-verified through the tenancy resolver before any create/theme write. - Tenancy resolution no longer throws in panel-less contexts (console, queue, tests).
- Keyboard-shortcut help no longer opened-then-closed on a single keypress, and Escape now closes the help overlay.
- Discard now asks for confirmation when there are unsaved changes, and several hardcoded editor strings (add-section clear, iframe title) are now translatable.
[1.1.0]
Added
- Light Northline-brand presets across all 12 built-in sections, so a fresh site can be assembled entirely from light-scheme presets.
- Light/dark editor switcher at the bottom of the editor icon rail.
Fixed
- Auto-save never fired. The scheduler checked the server-side
hasUnsavedcomputed property through the JS$wireproxy, where it does not exist. Dirtiness is now tracked client-side in Alpine state (fed bydraft-synced/fc:live-edit) and armed on load when a dirty draft already exists. - Public catch-all route shadowed host and Livewire routes. The
GET /{path?}public route is now registered viaRoute::fallback(), so host-app routes and Livewire 4's frontend asset route always win. - Guaranteed 404 after a minimal (no-tenancy) install.
templateBelongsToCurrentTenantnow authorises unowned template sites when the host has no tenancy configured, fixing "Open in Editor" out of the box. - Dist archive was missing runtime JS fallbacks.
.gitattributesexport-ignored all ofresources/js, so consumer installs failed infilament:upgrade(copy(): No such file or directory). Only the TypeScript sources are excluded from the archive now.
Docs
- Legal pages (terms, privacy, refund policy), regions and blueprints guides, fresh editor screenshots,
APP_URL+ fallback-routing notes.
[1.0.0]
First commercial release. Sold at filamentcraft.dev (Paddle checkout), installed from the private Composer registry at packages.filamentcraft.dev.
Added
Soft-degrade licensing.
FilamentCraft\Licensing\LicensereadsFILAMENTCRAFT_LICENSE_KEY; unlicensed installs keep every feature and render a small "Built with FilamentCraft" link on public pages (both the template renderer and the<x-filamentcraft::layout>shell). Nothing is ever blocked, no network calls are made — install-time enforcement happens at the private Composer registry.softLicense(false)/license.soft_degrade => falsedisables the attribution link. The unusedlicense.cache_ttlconfig key was removed.Site blueprints + tenant provisioning.
SiteBlueprint(theme, pages, regions, locales, publish, site settings) +BlueprintRegion+SiteProvisionercreate a complete live site in one transaction —MyBlueprint::provision($owner)from a model observer is the whole tenant-onboarding story.make:filamentcraft-blueprint {name} [--site]scaffolds page and site blueprints. Documented in the "Seeding & Blueprints" guide.Release pipeline.
release.ymlnow gates av*tag (dist parity +composer check) and creates a GitHub release; the distribution hub imports new tags automatically..gitattributesexport-ignores were extended so customer dist archives stay lean (~590 KB).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]
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 —
make:filamentcraft-section,make:filamentcraft-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.
