Summary
JSON-first rich text editor built on FilamentRichEditor / TipTap, with a FLEX interface, Hugeicons, content limits with live feedback, responsive images, optional Spatie Media Library, YouTube embeds, custom blocks, fullscreen, autosave, paste cleanup, and a keyboard-accessible toolbar.
The field inherits the document features and configuration of Filament Rich Editor. FLEX supplies the interface and its additional upload, rendering and editing options described below. Options introduced in newer Filament releases require that release in your application.
Quick start
makeFlexRichContentRenderer() (see Rendering HTML).
Filament configuration with the FLEX interface
Use the inherited configuration methods onFlexRichEditor; you do not need a second native editor. For example:
secondary has a subtle gray background, primary and soft use the field surface, and flat has a transparent surface. Tool buttons with visible labels expand to fit their text.
Merge tags and custom blocks
Enable merge tags to let authors insert placeholders:RichContentCustomBlock. Configure them on the same field; FLEX displays their picker in its own panel. In Filament versions that support grouped, searchable blocks, you can also use:
Configuration catalog (package API)
FlexRichEditor-specific options only. The field extends FilamentRichEditor; inherited Filament APIs are not duplicated here.
Shell & field chrome
Content limits & footer
Editor UX
Toolbar
Static helpers (presets):
getFlexDefaultToolbarButtons(), getFlexFullToolbarButtons(), getFlexDefaultFloatingToolbars(), getFlexExtraTools(), getNativeComparisonToolbarButtons().
To override button layout, use Filament’s toolbarButtons() / floatingToolbars() / tools() with these presets — see Filament Rich Editor.
File attachments & images (package layer)
Requires FilamentfileAttachments() / disk options to be enabled first. This table lists Flex processing and cleanup on top of that baseline.
HTML rendering
Built-in plugins (automatic): block images (always), YouTube (when
youtube()), paste cleanup (when pasteCleanup()).
Shell variants
primary
secondary (default)
soft
flat
Shell sizes
sm
md (default)
lg
Focus outline
Word count
JSON debug badge
Content limits
Soft limits (default) — warn in footer, validate on save
Hard limits — block typing past max
editor.commands.undo() when the user exceeds max characters or words.
Min characters only
Max characters only
Max words only
Reading time
config('filament-flex-fields.rich_editor.reading_time_words_per_minute').
Fullscreen
Distraction-free
Hides clearFormatting and clearContent in the toolbar while fullscreen is active.Autosave
Saves editor JSON tolocalStorage. On reload, prompts to restore if a newer draft exists.
{statePath}::{model:id|create}::user:{id}.
Paste cleanup
YouTube embeds
Requires->youtube(). Adds toolbar button + TipTap extension + paste handler for YouTube URLs.
youtube.com/watch?v=, youtu.be/, youtube.com/embed/, youtube.com/shorts/.
Rendered HTML preserves data-youtube-video iframes through FlexRichContentRenderer::toHtml() sanitization.
Block images (automatic)
FlexRichEditorBlockImagePlugin is always registered. Images inserted in the editor are block-level (not inline with paragraph text). No configuration required.
Image overlay (editor only)
When file attachments are enabled, selecting an image shows Edit and Delete controls (top-right overlay). Not included in frontend HTML output.- Edit → opens Filament
attachFilesaction (alt text, replace). - Delete → removes image from document.
Toolbar presets
Default Flex toolbar (no attachFiles)
Full toolbar (with attachments button)
Custom toolbar
Toolbar roles
Presets inconfig('filament-flex-fields.rich_editor.toolbar_roles').
Author
Editor
Admin
Custom role (after publishing config)
Disabled toolbar tools
flexFullscreen and plugin tools (youtube) use their tool names.
Floating toolbars
Default paragraph bubble (bold, italic, underline, strike, link). Hidden when an image is selected.Custom tools
Flex adds Hugeicons tools viaFlexRichEditor::getFlexExtraTools():
clearFormatting— clear nodes + marksclearContent— empty document
fullscreen() is enabled, flexFullscreen tool is appended automatically.
File attachments
Uploads use Filament’s attachment API (fileAttachments(), disk, directory, visibility). Flex adds scoped paths, optimization, variants, and orphan cleanup on top.
Attachments are enabled when fileAttachments(true) or the toolbar includes attachFiles and Filament resolves hasFileAttachments().
Visibility
Scoped attachment directories
scopedAttachmentDirectory('rich-editor') resolves:
{prefix}/{model}/{id}/when editing a record{prefix}/drafts/{userId}/on create forms
Images only
Restricts accepted MIME types to images (JPEG, PNG, GIF, WebP).Max attachment size
Single-pass image optimization
Without named variants — resizes/optimizes the master file on upload.Named image variants
The default disk uploader creates a WebP thumbnail with a maximum long edge of 250 px and a WebP master with a maximum long edge of 1500 px. Small images are not enlarged. The optimized master replaces the disk original only after all outputs and their manifest have been written successfully.photo.webp has a photo__thumb.webp thumbnail and a photo.webp.flex-variants.json manifest. Generation supports local and stream-capable remote disks, preserves visibility, and stages all variants privately before publication. Raster processing has limits of 64 MiB per input and 50 megapixels; inputs exceeding these limits fail instead of starting unbounded processing.
Array config
Fluent RichEditorImageVariant objects
max_long_edge, max_width, max_height, webp, master, optimize.
Automatic attachment cleanup
Native disk (default on)
.flex-variants.json manifests. Cleanup is limited to attachments removed from this document. Other files in the same directory are preserved.
Spatie Media Library
Disk pruner is skipped. Filament callsFileAttachmentProvider::cleanUpFileAttachments(exceptIds: [...]) on save.
Responsive images in HTML output
Lazy images on/off
Responsive srcset on/off
responsiveImages() defaults to on if not set explicitly.
Image sizes attribute
Rendering HTML
Always usemakeFlexRichContentRenderer() so disk, variants, plugins (YouTube), and lazy loading match the field.
From field instance (recommended)
In Filament infolist / table column
Standalone renderer
Example output
Blade view
Inertia / API controller
Alt text required
Accessibility
Built-in without extra configuration:Spatie Media Library (optional)
Spatie keeps ownership of originals, conversions and queued jobs. The uploader does not resize its original before passing it to Spatie. Register the desired conversions on your media model; field configuration alone does not register model conversions. Until a queued conversion exists, preview/rendering falls back to the original.1. Model — register conversions
large. On Spatie, master identifies the preferred display variant; it does not replace or delete the original. Omit queued: true for synchronous conversions.
2. Form
3. Render
Complete example: Filament Resource
Configuration recipes
Minimal blog post
Production article (native disk)
Author role (limited toolbar)
Package config
config/filament-flex-fields.php:
Translations
Package strings:filament-flex-fields::default.rich_editor.* in resources/lang/en/default.php and resources/lang/pl/default.php.
Toolbar labels reuse Filament: filament-forms::components.rich_editor.tools.*.
Publish translations
Key reference
Testing
PHP (package)
JavaScript unit tests
Playwright E2E (playground)
Playground
/admin/flex-fields/flex-rich-editor — see Playground.
Slug: flex-rich-editor
Includes:
- Full Article body demo (attachments, variants, limits, YouTube, fullscreen, autosave)
- Variant grid: compact / secondary / soft / flat
- Attachments-only and full-toolbar sections
Assets (CSS & JS)
Each field loads its own CSS bundle and Alpine component on demand (x-fff-load). Optional support scripts load only when configured.
Does it duplicate Filament’s rich editor?
FLEX owns the editor shell, toolbar and supporting modules. The shell lazily imports Filament’s registeredrich-editor runtime and awaits its initialization;
it does not bundle a second copy of the native runtime. Multiple FLEX editors
share that dependency. The playground contains only FLEX examples.
The scoped rich-editor-field.css stylesheet owns the FLEX chrome. Built-in
controls use Hugeicons with a consistent stroke width of 2; document content is
outside this chrome rule. The contenteditable uses aria-labelledby to reference
its visible field label rather than an invalid HTML label[for] association.
Performance notes
- Footer stats use
requestAnimationFramebatching (not per-keystroke DOM thrashing). - Image overlay sync runs on selection changes only.
- Attachment manifest reads are cached per request during HTML rendering.
- CI checks the emitted shell and shared dependency graph against the package bundle budgets. The Filament runtime remains a separately loaded dependency.
Requirements & optional packages
Filament RichEditor baseline
FlexRichEditor extends Filament\Forms\Components\RichEditor. Options not documented on this page behave as in Filament.
- Filament Rich Editor documentation
- JSON storage is enabled by default in
setUp()(json())