Skip to content

No-Code Section Builder

Your users can design their own section types without touching PHP. They compose one from a palette of blocks, save it, and it lands in the Add section catalog next to the built-in sections — same live preview, same settings panel, same published output.

This is the no-code sibling of Custom Sections. That page is for you, the developer, writing a section class. This page is for the people using the editor.

The section builder with a block palette, live canvas, and section style inspector
The builder: block palette on the left, live canvas in the middle, settings for the current selection on the right.

When to reach for which

A section class is right when the section needs real logic — a database query, an API call, a cache strategy. The builder is right when the section is a composition of copy, images, and layout, and you don't want to ship a release every time marketing wants a new arrangement.

Turning it on

The builder is enabled by default. Publish the migrations and you're done:

bash
php artisan vendor:publish --tag=filamentcraft-migrations
php artisan migrate

Definitions live in filamentcraft_section_definitions, scoped per site — one tenant never sees another's sections.

php
// config/filamentcraft.php
'section_definitions' => [
    'enabled' => env('FILAMENTCRAFT_SECTION_DEFINITIONS', true),

    // Saved definitions allowed per site. Abandoned drafts are swept and never
    // counted, so a closed browser tab cannot use up an operator's allowance.
    'max_per_site' => 50,

    // Blocks allowed in one section's tree. Inserts past this are refused with a
    // notice rather than silently dropped at render time.
    'max_nodes' => 100,

    // Unlocks raw <script> output on the html block. A host-developer decision —
    // never expose this to tenants you don't trust.
    'allow_custom_code' => false,
],

Creating a section

Add section opens the catalog with a Create your own card above the built-ins.

The Add section catalog with a Create your own card at the top
Every catalog gets the create entry — no separate resource, no leaving the editor.

Start from a layout

Building from an empty canvas is slow, so the Layouts tab ships 24 complete arrangements — hero, split content, feature grid, pricing, FAQ, team, timeline, testimonial, and more. Each inserts as ordinary blocks you can then rearrange or delete. Nothing is locked.

The Layouts library listing 24 curated section arrangements
Layouts are a starting point, not a template — everything they insert is editable.

Or assemble from blocks

The Blocks tab holds 25 primitives in six groups:

GroupBlocks
TypographyHeading, Eyebrow, Text, Quote, List
ActionsButton, Badge, Accordion, Callout
MediaImage, Video, Person, Icon, Logo
Data & proofStatistic, Rating, Price, Progress, Timeline item
LayoutContainer, Card, Columns, Masonry grid, Spacer, Divider
AdvancedHTML
The Blocks tab listing 25 primitives grouped by Typography, Actions, Media, Data and proof, Layout, and Advanced
The block palette, searchable and grouped. Every one is a real storefront primitive, not a placeholder.

Click a block to append it, or drag it — onto the canvas to drop at a position, or into the structure tree to nest it. Container, Card, Column, and Masonry accept children, so layouts nest up to four levels deep.

Read the tree, not the types

The Structure tab lists every block by its own content, so a section with eight text blocks is still navigable. Drag a row to reorder or reparent; each row also carries move, duplicate, and remove.

The structure tree showing blocks labelled by their content
Rows read "Built for work that matters", not "Heading". The icon carries the type; hovering shows both.

Style what you selected

Selecting a block swaps the right rail to its controls — every one live, every one reflected in the canvas on the next round-trip. With nothing selected you get Section style: color scheme, padding, and content width for the whole section.

The inspector showing surface, border, radius, and shadow controls for a card block, with the block's hover toolbar on the canvas
Controls are per-block. Values come from your theme tokens, so a section can never drift off-brand.

Work straight on the canvas

Pointing at a block raises a small toolbar on it — drag to move, add space above or below, or duplicate — so the common edits never require a trip to the structure tree.

A feature card on the canvas with its hover toolbar showing drag, add space above, add space below, and duplicate
The toolbar follows the pointer, not the selection, so you can move or copy a block without selecting it first.

Dropping in a layout when the canvas already has content adds a spacer between the two, which is what you'd reach for next anyway.

Check it narrow

The device switcher renders the canvas at real desktop, tablet, and mobile widths — the same iframe your visitors get, reflowed.

The builder canvas at mobile width inside a phone frame
Responsive behaviour is real, not simulated — the preview is the storefront renderer.

Saving

Saving asks for a name and an icon. The name becomes the catalog label and the slug; the icon shows in the catalog and the page's section rail.

The save dialog with a name field and a searchable icon picker
The icon picker searches every registered set — Heroicons out of the box, plus whatever else you've registered.

From there, Add to page drops it straight into the page you came from, or Done just files it in the catalog for later.

What your users get back

A saved definition is a real section type. It appears under Custom sections in the catalog, and can be inserted as many times as you like — each instance holding its own content.

The Add section catalog showing a Custom sections group above the built-ins
Custom sections sort above the built-ins. Hovering a card reveals edit, duplicate, and delete.

The settings panel writes itself

This is the part worth understanding. Every editable prop the user bound while building — each heading's text, each card's copy, each icon — becomes a setting on the section, listed flat in document order and named after the block it edits. Nobody wrote that schema.

The editor settings panel listing a generated field for each editable block in a custom section
One field per editable prop, in the order the blocks appear. Rich text gets a rich editor, images get an upload, icons get the picker.

A block with several editable props prefixes each one, so a button reads Button · Label, Button · Link, Button · Icon.

So the person who builds the section and the person who fills it in don't have to be the same person — which is the whole point on a client site.

It publishes like anything else

A custom section rendered on the published storefront between built-in sections
On the live site, between two built-in sections. Same theme tokens, same fragment cache, same markup pipeline.

Custom sections are cacheable, respect color schemes and Brand Kit limits, and render per locale like everything else.

How it is stored

Two JSON columns per definition:

  • layout_json — the element tree the renderer walks. Every node's type is checked against an allow-list and every prop resolves through a match-with-default, so stored JSON never reaches markup unvalidated.
  • schema_json — the generated settings, serialised in the same shape Setting::toArray() produces.

Editing bumps a version counter, which folds into the theme-token hash and therefore into the fragment cache key — so a re-saved section invalidates its own cached HTML without you flushing anything.

Guardrails

The builder is used by people you may not fully trust, so it is deliberately fenced:

  • Per-site scoping. Definitions resolve only for their own site. A definition id from another tenant is refused, not just hidden.
  • Depth and node caps. Trees stop at four levels and max_nodes blocks; inserts past either are refused with a notice.
  • No raw markup by default. The HTML block's markup runs through the shared sanitizer, its CSS is rejected if it could break out of its <style>, and <script> output requires allow_custom_code.
  • Values validated at the boundary. Every control's value is checked against its declared option set or numeric bounds before it reaches the tree.
  • Deletion warns first. Deleting a definition that pages already place tells you how many, because those sections will render empty.

php artisan filamentcraft:doctor audits stored definitions and reports broken schemas or sites over the limit.

Styling caveat for host apps

If you inject your own Tailwind build into the storefront via filamentcraft.assets.vite_builds, note that both bundles emit the same utility class names. FilamentCraft's stylesheet declares an explicit cascade-layer order so its own responsive variants survive the collision, while any unlayered CSS of yours still overrides it. Write storefront overrides as plain, unlayered rules and they will win — see Styling & Tailwind.

Limits worth knowing

  • A section that has never been saved has no way back once discarded — the builder confirms before throwing that work away.
  • Deleting a definition blanks placed instances rather than removing them; clear them from the affected pages afterwards.
  • The HTML block is an escape hatch, not a supported extension point. Reach for a section class when you need behaviour.