bambamboole / filament-pages
A Filament plugin for managing hierarchical, block-based content pages with a drag-and-drop page tree, SEO integration, and live preview
Fund package maintenance!
:vendor_name
Installs: 5
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 1
pkg:composer/bambamboole/filament-pages
Requires
- php: ^8.3
- bambamboole/filament-menu: ^0.2
- filament/filament: ^5.0
- filament/spatie-laravel-media-library-plugin: ^5.3
- league/commonmark: ^2.7
- nette/php-generator: ^4.2
- pboivin/filament-peek: ^4.0
- ralphjsmit/laravel-filament-seo: ^2.1
- ralphjsmit/laravel-seo: ^1.7
- spatie/laravel-package-tools: ^1.15.0
Requires (Dev)
- larastan/larastan: ^3.2
- laravel/pint: ^1.0
- orchestra/testbench: ^9.0|^10.0
- pestphp/pest: ^3.7|^4.0
- pestphp/pest-plugin-arch: ^3.0|^4.0
- pestphp/pest-plugin-laravel: ^3.0|^4.0
- pestphp/pest-plugin-livewire: ^3.0|^4.0
- rector/rector: ^2.3
- spatie/browsershot: ^5.2
- spatie/laravel-ray: ^1.26
Suggests
- ryangjchandler/commonmark-blade-block: Required for Blade block support in markdown (^1.1)
- spatie/browsershot: Required for automatic OG image generation (^5.0)
- torchlight/torchlight-commonmark: Required for Torchlight syntax highlighting in markdown (^0.6)
README
A Filament plugin for managing hierarchical, block-based content pages. Features a drag-and-drop page tree, extensible block system (Markdown, Image out of the box), nested pages with automatic slug path computation, multi-locale support, SEO integration, and live preview.
Features
- Page Tree — Interactive drag-and-drop tree for reordering and nesting pages
- Block Builder — Flexible content composition with an extensible block system
- Markdown Block — Rich editor with table of contents, heading permalinks, GFM support, and optional Torchlight syntax highlighting
- Image Block — Spatie Media Library integration with responsive images and an image editor
- Custom Blocks & Layouts — Artisan generators for scaffolding your own blocks and layouts
- Multi-Locale — Locale-scoped page trees with automatic route prefixing and browser language detection
- SEO — Built-in SEO metadata tab with extensible fields and optional OG image generation via Browsershot
- Live Preview — Instant page preview powered by Filament Peek
- Publishing Workflow — Draft, published, and scheduled states with
published_atdatetime - Authorization — Laravel policy support for
create,update,delete, andreorderabilities - Frontend Routing — Catch-all route registration that resolves pages by slug path and locale
- Hierarchical Slugs — Automatic slug path computation based on the page tree hierarchy
Screenshots
| Page Editor | SEO Tab |
|---|---|
![]() |
![]() |
Installation
composer require bambamboole/filament-pages
Publish and run the migrations:
php artisan vendor:publish --tag="filament-pages-migrations"
php artisan migrate
Optionally publish the config:
php artisan vendor:publish --tag="filament-pages-config"
Register the plugin in your Filament panel provider:
use Bambamboole\FilamentPages\FilamentPagesPlugin; public function panel(Panel $panel): Panel { return $panel ->plugins([ FilamentPagesPlugin::make(), ]); }
Add the plugin views to your Tailwind CSS content paths:
@source '../../../../vendor/bambamboole/filament-pages/resources/**/*.blade.php';
Configuration
The plugin is configured through the fluent API on FilamentPagesPlugin and the published config file.
FilamentPagesPlugin::make() ->seoForm(fn () => [ TextInput::make('canonical_url'), ]) ->treeItemActions(fn (ManagePages $page) => [ Action::make('duplicate')->action(fn (array $arguments) => /* ... */), ]) ->previewView('my-custom-preview-view')
Blocks and layouts are configured in the config/filament-pages.php config file:
// config/filament-pages.php 'blocks' => [ \Bambamboole\FilamentPages\Blocks\MarkdownBlock::class, \Bambamboole\FilamentPages\Blocks\ImageBlock::class, \App\Blocks\MyCustomBlock::class, ], 'layouts' => [ \Bambamboole\FilamentPages\Layouts\DefaultLayout::class, \App\Layouts\LandingPageLayout::class, ],
Blocks
Register block types in the blocks config array. Each block must extend Bambamboole\FilamentPages\Blocks\PageBlock.
Two blocks ship out of the box:
- MarkdownBlock — Rich markdown editor with optional table of contents (top/left/right positioning), front matter parsing, and Torchlight syntax highlighting.
- ImageBlock — Spatie Media Library file upload with responsive images and an image editor.
Layouts
Layouts control how pages render on the frontend. Each layout implements Bambamboole\FilamentPages\Layouts\PageLayout. Register them in the layouts config array.
Multi-Locale
Enable multi-language content by configuring locales in the config file:
// config/filament-pages.php 'routing' => [ 'prefix' => '', 'locales' => ['en' => 'English', 'de' => 'Deutsch'], ],
When locales are enabled, the page tree filters by locale and frontend routes include a {locale} prefix.
SEO
SEO is always enabled. Every page form includes an SEO tab (powered by ralphjsmit/laravel-filament-seo).
Extend the SEO form with custom fields:
->seoForm(fn () => [ TextInput::make('canonical_url'), ])
Preview
Live preview is always enabled (powered by pboivin/filament-peek). To use a custom preview view:
->previewView('my-custom-preview-view')
Creating Custom Blocks
Generate a block stub with the Artisan command:
php artisan filament-pages:make-block MyCustomBlock
A custom block extends PageBlock and defines a name, a Filament form schema, and optionally a mutateData() method to transform data before rendering:
use Bambamboole\FilamentPages\Blocks\PageBlock; use Filament\Forms\Components\Builder\Block; use Filament\Forms\Components\TextInput; class CallToActionBlock extends PageBlock { public static function name(): string { return 'call-to-action'; } public static function make(): Block { return Block::make(static::name()) ->label('Call to Action') ->schema([ TextInput::make('heading')->required(), TextInput::make('button_text')->required(), TextInput::make('button_url')->url()->required(), ]); } public static function viewName(): string { return 'blocks.call-to-action'; } }
Creating Custom Layouts
Generate a layout stub:
php artisan filament-pages:make-layout LandingPageLayout
A layout implements PageLayout and returns a view:
use Bambamboole\FilamentPages\Layouts\PageLayout; class LandingPageLayout implements PageLayout { public static function name(): string { return 'landing'; } public static function label(): string { return 'Landing Page'; } public function render(Request $request, Page $page): View { return view('layouts.landing', ['page' => $page]); } }
Include @filamentPagesStyles in your layout's <head> to load the frontend CSS:
<head> @filamentPagesStyles </head>
Route Registration
Register the frontend page routes in your routes/web.php:
use Bambamboole\FilamentPages\Facades\FilamentPages; FilamentPages::routes();
This registers catch-all routes that resolve pages by their slug path. You can pass a prefix:
FilamentPages::routes('pages'); // all pages under /pages/*
When locales are configured, routes are automatically prefixed with {locale}.
Frontend Rendering
Pages are rendered through their assigned layout using {!! $page->renderBlocks() !!}.
You can also render blocks programmatically:
$page = Page::where('slug_path', '/about')->first(); echo $page->renderBlocks();
Page Tree
The plugin provides an interactive page tree at /pages in your Filament panel. You can:
- Drag and drop to reorder and nest pages
- Create, edit, and delete pages via slide-over modals
- Publish/unpublish with datetime scheduling
- Switch between locales
- Preview pages before publishing
Custom actions can be added to tree items:
FilamentPagesPlugin::make() ->treeItemActions(fn (ManagePages $page) => [ Action::make('duplicate')->action(fn (array $arguments) => /* ... */), ])
Authorization
The package supports Laravel policies for access control. Create a policy for your page model to restrict actions:
php artisan make:policy PagePolicy --model=Page
Supported abilities: create, update, delete, reorder.
The package is permissive by default — when no policy is registered, all actions are allowed. Once a policy exists, only explicitly allowed abilities are permitted.
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Credits
License
The MIT License (MIT). Please see License File for more information.

