amidesfahani/filament-tinyeditor
A TinyMCE rich text editor integration for Filament Admin and Forms. Supports Filament 5.x, 4.x, and 3.x, with configurable profiles, toolbars, RTL direction, image and file attachments, custom external plugins, and resizable editing.
Architecture fit
AmidEsfahani\FilamentTinyEditor\TinyEditor) that wraps TinyMCE, not a standalone Laravel package. That is the right shape for our stack: it slots into existing Form/Resource schemas alongside TextInput, RichEditor, and MarkdownEditor without new abstractions, controllers, or persistence layers.Field API, so required(), columnSpan(), reactive(), hidden(), validation, and Livewire binding come for free. From a TPM standpoint this materially reduces the integration surface: the team is learning one widget, not a subsystem.fileAttachmentsDisk, fileAttachmentsVisibility, fileAttachmentsDirectory), so storage policy stays in our existing filesystem config rather than a second upload path.Integration feasibility
| Package | Filament | Laravel | PHP |
|---|---|---|---|
| 5.x | 5.x | 12.x | 8.2+ |
| 4.x | 4.x | 11.x | 8.2+ |
| 3.x | 3.x | 10.x+ | 8.1+ |
default, simple, full, minimal) plus none and custom map well to role-based authoring: a minimal profile for short marketing blurbs, full for long-form pages. Custom profiles and pipe-separated tool groups let us cap editor surface area per content type rather than shipping one maximal toolbar to every user.->rtl() / ->direction('auto|rtl|ltr') plus the config direction key is a real differentiator if we have any MENA or Hebrew content roadmap. It is cheap to validate and hard to retrofit later, so confirm it in the spike.Technical risk
tiny.cloud hosted variant requires an API key (a license-key option was added in v2.0.1). Someone must own this determination before production, because it is a legal/commercial question, not a code question.external_plugins accepts remote JS URLs (the README example pulls from unpkg.com at @latest). That is a supply-chain and availability hazard: @latest is unpinned remote code executing in an authenticated admin session. Treat as banned-by-default in our standard.x-load renaming all appear as past fixes. Each was resolved, but it tells us the Livewire/Alpine integration is the fragile seam and must be regression-tested on every upgrade.Key questions for the maintainer / spike
tiny.cloud, or both? Which is the default, and what does the license key actually gate?FileUpload enforces?Stack fit
TextInput or Textarea is cheaper and safer.public for local, s3 in production) and a per-content-type upload directory, and keep visibility explicit rather than relying on defaults.Migration path
composer require the matching major, publish config, optionally publish views/assets, drop TinyEditor::make('content') into a schema.RichEditor (Tiptap-based): not a drop-in. Stored HTML is broadly compatible, but toolbar semantics, image embedding, and paste behavior differ. Expect a content-QA pass on existing records and a short editor-training note for authors. Recommend not migrating in-flight content; migrate per resource with a before/after sample review.profiles array.ax-load → x-load), which is the class of change that silently breaks init.Compatibility
"^5.0" with a committed composer.lock), and add a CI gate that fails on Filament major/minor drift outside the tested matrix.Sequencing
default and minimal profiles, RTL enabled, and a local disk upload.external_plugins (or pin an exact versioned URL if a plugin is truly required). Define the toolbar allowlist per content type.Maintenance
Support
repositories vcs entry) so it is a known path rather than an improvised one.Scaling
full profile's plugin set is a meaningful JS payload per admin page. Use minimal/simple profiles by default and reserve full for the few long-form resources. Serve assets via CDN with long-lived caching.longText), row size, and any full-text indexing strategy; avoid SELECT * patterns that hydrate editor HTML into list views.Failure modes
| Failure | Blast radius | Mitigation |
|---|---|---|
| Editor JS fails to init (Alpine/CSP/asset 404) | Authors cannot edit; form may submit empty | Synthetic monitor on an admin form; assert non-empty content on submit for required fields |
| Unsanitized HTML persisted and rendered | Stored XSS, potentially admin-session compromise | Server-side sanitization on write, strict render path, CSP |
| Content loss on Livewire re-render / reorder | Silent data loss, low detectability | E2E test on repeater reorder; dirty-state guard; autosave or beforeunload warning |
| Upload failure (filename encoding, MIME, size) | Broken images in published content | Allowlist + size caps + explicit error messaging; test non-ASCII names |
| External plugin CDN unavailable or compromised | Editor breaks or executes untrusted code | Ban @latest remote plugins; pin exact versions or vendor locally |
| Filament major upgrade blocks widget | Delayed platform upgrade | CI compatibility gate; pre-scoped fork option; upgrade sequencing in roadmap |
| Modal/z-index conflicts | Editor unusable inside modals | Explicit acceptance test; known historical issue area |
| TinyMCE licensing/key misconfiguration | Legal exposure or editor watermark/errors in production | Licensing owner assigned pre-production; key in secrets, not config committed to VCS |
Ramp-up
paste_webkit_styles-style configs are tuned. Budget a short author guide and one feedback cycle after pilot, and expect a follow-up config iteration.How can I help you explore Laravel packages today?