jeffersongoncalves/filament-mail-editor
Filament Mail Editor adds a visual email template editor to Filament admin panels, letting you create, edit, and preview mail templates with a rich-text or code editor, Blade variable support, and seamless integration with Laravel mailables.
This is now a two-package split. jeffersongoncalves/filament-mail-editor 1.1.0 is only the Filament layer (resources, drag-and-drop builder, metrics widget, block forms). All models, enums, events, support classes, config, migrations and translations live in jeffersongoncalves/laravel-mail-editor, which is pulled in automatically as a dependency.
laravel-mail-editor to your own composer.json unless you need to pin its version:composer require jeffersongoncalves/filament-mail-editor
mail-editor tag prefix, not filament-mail-editor):php artisan vendor:publish --tag="mail-editor-migrations"
php artisan vendor:publish --tag="mail-editor-config"
php artisan vendor:publish --tag="mail-editor-translations" # only if you override copy
php artisan migrate
Read config/mail-editor.php first — it drives routes, models, mail/queue behaviour and the builder defaults. There is no config/filament-mail-editor.php any more.
Register the plugin on the panel that should host the editor:
use JeffersonGoncalves\FilamentMailEditor\FilamentMailEditorPlugin;
public function panel(Panel $panel): Panel
{
return $panel->plugin(FilamentMailEditorPlugin::make());
}
mail-editor.preview route), then wire the template to a mailable and send through your queue.If you are coming from 1.0.x, treat this as a major upgrade despite the version number — see the migration checklist under Implementation Patterns.
Upgrade checklist for 1.0 → 1.1. Do these in order; several failures are silent rather than fatal.
composer update jeffersongoncalves/filament-mail-editor -W
php artisan vendor:publish --tag="mail-editor-config"
php artisan migrate
php artisan optimize:clear # config + route + view caches
Then grep your codebase for the four rename surfaces:
grep -rn "FilamentMailEditor" app/ config/ database/ resources/ routes/ tests/
grep -rn "filament-mail-editor" app/ config/ database/ resources/ routes/ tests/ lang/
grep -rn "filament-mail-editor-migrations\|filament-mail-editor-config" .
grep -rn "filament-mail-editor\." app/ resources/ routes/
Namespace migration. Every non-Filament class moved to the core namespace. The Filament layer (resources, builder, widget, block form components) stays in JeffersonGoncalves\FilamentMailEditor\….
| 1.0 | 1.1 |
|---|---|
JeffersonGoncalves\FilamentMailEditor\Models\* |
JeffersonGoncalves\MailEditor\Models\* |
…\FilamentMailEditor\Enums\* |
…\MailEditor\Enums\* |
…\FilamentMailEditor\Events\* |
…\MailEditor\Events\* |
…\FilamentMailEditor\Support\* |
…\MailEditor\Support\* |
…\FilamentMailEditor\Database\Seeders\* |
…\MailEditor\Database\Seeders\* |
Keep a single use per model in your app and let IDE/rector handle the sweep — models referenced in relations, factories, policies, observers, $model overrides in config/mail-editor.php, and Filament resource $model properties all break together.
Config references. config('filament-mail-editor.x') now returns null without error. That is the most dangerous part of this release — a queue name or a disk silently becomes null and the editor still boots. Search for the string and replace with config('mail-editor.x'); add a boot-time assertion in your own service provider if this config is load-bearing:
abort_if(config('mail-editor.models.template') === null, 500, 'mail-editor config not published');
Routes. Preview and countdown now live at /mail-editor/preview and /mail-editor/countdown under the names mail-editor.preview / mail-editor.countdown. Use route() everywhere — any hardcoded /filament-mail-editor/... string, or a Blade url() copied into an email template, becomes a 404. Signed preview URLs minted before the deploy are invalidated by the path change, so treat any in-flight preview links as expired.
Translations. The language namespace moved with the rest of the core, so overrides that used to live under lang/vendor/filament-mail-editor are now orphaned. Re-publish with the mail-editor tag (same prefix pattern as config and migrations) and move any customised strings across — otherwise the UI silently reverts to package defaults. Keep label overrides out of the Filament layer; the core owns them now.
Custom blocks with a Filament form. Implement HasPropsSchema on your block class to get a real Filament form in the block library instead of a blind props editor:
use JeffersonGoncalves\MailEditor\Contracts\HasPropsSchema;
class CtaBlock implements HasPropsSchema
{
public function getPropsSchema(): array
{
return [
TextInput::make('label')->required(),
TextInput::make('url')->url()->required(),
Select::make('align')->options(['left' => 'Left', 'center' => 'Center']),
];
}
}
Implement the contract from the core namespace — a class importing the old Filament-layer contract will not be recognised and the block silently falls back to raw props editing.
Import/export between environments. JSON exports now carry the mail-editor format id, and files exported with filament-mail-editor still import. That is one-way: a template exported from 1.1 cannot be re-imported into a 1.0 install. Keep the version of the receiving environment in mind when promoting templates from staging to production, and sequence the upgrade before importing anything.
Metrics widget. Register it on the panel alongside the plugin; it reads from the core models, so any custom $model overrides in config/mail-editor.php must be applied before the widget will show non-zero stats.
Testing. 1.1.0 ships smoke tests for every resource page and custom table action — mirror that shape in your own suite rather than testing the builder internals:
it('renders the template resource', function () {
$this->actingAs(User::factory()->create())
->get(TemplateResource::getUrl('index'))
->assertSuccessful();
});
Add one assertion per route name you depend on so the next rename fails loudly:
expect(Route::has('mail-editor.preview'))->toBeTrue();
laravel-mail-editor was ever required explicitly at an older version, Composer may resolve a core version that predates the 1.1 Filament layer. Run composer why jeffersongoncalves/laravel-mail-editor and remove the direct requirement unless you're deliberately pinning.config/filament-mail-editor.php does nothing but mislead the next developer. Delete it; the single source of truth is config/mail-editor.php.mail-editor-migrations into a database/migrations folder that already contains the old filament-mail-editor migrations will attempt to re-create tables. Keep the published core migrations and drop the old files, or rely on the package's own migrations.null config. The config key rename is the single most likely cause of "the editor works but emails don't send / land on the wrong disk". Anywhere you read config('filament-mail-editor.*'), replace and re-test — there is no deprecation shim.lang/vendor/filament-mail-editor are no longer loaded. The editor will look untranslated with no error; re-publish or move the files to the mail-editor namespace.route:cache holds the old /filament-mail-editor/* paths until php artisan optimize:clear. Symptom: previews 404 in production only, works locally.config/mail-editor.php for the middleware stack and confirm whether signed URLs are required before exposing templates to untrusted traffic.mail-editor format id is not readable by 1.0 installs. If you run a blue/green or canary deploy, hold imports until all nodes are on 1.1.HasPropsSchema exists in the core package. An implements that resolves to a stale class name compiles but is ignored at runtime — no exception, just a missing form. Verify with php artisan about / composer show that the core version matches the Filament layer.RefreshDatabase will fail before any assertion runs. It is now JeffersonGoncalves\MailEditor\Database\Seeders\….php artisan event:list after the upgrade and confirm your mail-editor listeners appear.How can I help you explore Laravel packages today?