navidcode/filament-page-builder

A visual page builder form field for Filament panels.

Maintainers

Package info

github.com/navidsafavi/filament-pagebuilder

pkg:composer/navidcode/filament-page-builder

Transparency log

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-08-12 06:02 UTC

This package is auto-updated.

Last update: 2026-08-12 06:04:47 UTC


README

A visual, extensible page builder form field for Filament 5 and Livewire 4.

Project origin

This package began as an extraction of the Page Builder functionality from Mksine, originally created by Miran Salehi. The Page Builder code was separated into this standalone Filament package so it can be maintained independently and reused outside the original project. Future development in this repository will continue from that foundation and may introduce new components, improvements, and features.

The original and current copyright notices are preserved in LICENSE.md.

Installation

composer require navidcode/filament-page-builder

The package registers its compiled CSS and JavaScript with Filament. Filament publishes these assets to the application's public directory when its filament:upgrade Composer hook runs during install or update. If Composer scripts are disabled, publish them manually:

php artisan filament:assets

Register the plugin on the Filament panel:

use NavidCode\PageBuilder\PageBuilderPlugin;

return $panel
    ->plugin(PageBuilderPlugin::make());

Use the field in a Filament schema:

use NavidCode\PageBuilder\Forms\PageBuilderField;

PageBuilderField::make('content')
    ->columnSpanFull();

The model attribute should use Laravel's array cast and be backed by a JSON column.

protected function casts(): array
{
    return [
        'content' => 'array',
    ];
}

Rendering on the frontend

The builder stores an array of blocks in the model attribute. Render every block through the package's dispatcher view, following the same pattern used by the original Mksine Page Builder:

<div class="page-builder-content">
    @foreach ($page->content ?? [] as $block)
        @include('filament-page-builder::render.block', ['block' => $block])
    @endforeach
</div>

The dispatcher selects the correct view for each block and recursively renders nested container blocks. Use it instead of including individual component views directly.

Filament loads the published CSS and JavaScript automatically inside panels. To use the package styles when rendering blocks outside Filament, include the published stylesheet in the public frontend layout:

<link
    rel="stylesheet"
    href="{{ asset('css/navidcode/filament-page-builder/page-builder.css') }}"
>

Tabs, sliders, and accordions use Alpine.js in their rendered markup. If the public layout does not already provide Alpine.js, load Alpine.js there; accordions also require the Alpine Collapse plugin.

Extending the builder

Builder component classes implement BuilderComponentInterface. Add components or templates to every builder in a panel while registering the plugin:

PageBuilderPlugin::make()
    ->components([
        CustomComponent::class,
    ])
    ->templates([
        'custom-landing' => CustomLandingTemplate::config(),
    ]);

To use a different set for one field, configure the field directly:

PageBuilderField::make('content')
    ->extendComponents([
        CustomComponent::class,
    ])
    ->excludeComponents([
        UnwantedComponent::class,
    ])
    ->templates([
        'custom-landing' => CustomLandingTemplate::config(),
    ]);

extendComponents() merges custom components with the plugin component set. If an extended component uses the same type as an existing component, the extended component replaces it for that field. excludeComponents() removes the listed component classes from the final field set.

Use components() only when the field should replace the complete plugin component set:

PageBuilderField::make('content')
    ->components([
        CustomComponent::class,
    ]);

The templates() method still replaces the plugin template set for that builder instance. Omit an override method to inherit its corresponding set from the panel plugin. Closures are also supported, so the field configuration can depend on the current Filament schema context.

Field-level component configuration controls the editor instance. Register field-only components separately for frontend rendering so the dispatcher can resolve their views without adding them to every editor:

PageBuilderPlugin::make()
    ->renderComponents([
        CustomComponent::class,
    ]);

The component class declares its output view:

public static function getRenderView(): string
{
    return 'page-builder.render.custom';
}

The custom Blade view receives $data, $blockId, and $children when the block contains children. For example, create resources/views/page-builder/render/custom.blade.php:

<section>
    {{ $data['content'] ?? '' }}
</section>

renderComponents() only registers frontend view resolution. Use extendComponents() or components() on the field to control which components appear in that editor.

Package development

npm install
npm run build
composer test

npm run build compiles resources/js and resources/css into the package's dist directory. When developing the package through a Composer path repository, run the following command from the host Laravel application after rebuilding:

php artisan filament:assets

This copies the compiled files into the host application's public/css/navidcode/filament-page-builder and public/js/navidcode/filament-page-builder directories.

Compiled assets in dist are committed so package consumers do not require Node.js.

License

The MIT License. See LICENSE.md.