laravel-enso / mails
Central email layouts and components for Laravel Enso applications
Requires
- php: ^8.2
- laravel/framework: ^12.0|^13.0
Requires (Dev)
- orchestra/testbench: ^10.0|^11.0
- phpunit/phpunit: ^11.0|^12.0
README
Description
Laravel Enso Mails provides the central email design system for Laravel Enso applications. It ships modern Markdown mail layouts, reusable Blade mail components, brand tokens, and a preview catalog so framework packages and applications can migrate email templates incrementally without copying CSS or layout HTML into every mail.
The package uses MJML only at package build time. Consuming Laravel applications send compiled Blade Markdown mail views at runtime and do not need Node.js or MJML installed to send mail.
Installation
Install the package with Composer:
composer require laravel-enso/mails
The service provider is auto-discovered by Laravel. It registers the package views, configures the Laravel Markdown mail paths, registers the built-in preview catalog, and exposes the preview route and command.
Publish the config when an application needs brand overrides:
php artisan vendor:publish --tag=mails-config
This publishes:
config/enso/mails.php
View publishing is available for deliberate overrides only:
php artisan vendor:publish --tag=mails-views
::: warning Note
Do not publish views just to customize brand colors, logo, spacing, or font. Use config/enso/mails.php for those values so applications stay on the shared layout and component system.
:::
Features
- Central Markdown mail layouts for normal and wide email bodies.
- Compatibility aliases for
mail::message,mail::message-wide,mail::transactional,mail::action-required, andmail::report. - Reusable Blade components for titles, tags, buttons, boxes, alerts, quotes, panels, files, metrics, tables, schedules, dividers, signatures, headers, and footers.
- Brand tokens for logo, name, URL, colors, typography, spacing, radius, footer text, legal text, and footer links.
- MJML source layout compiled into runtime Blade views.
- Runtime mail sending without Node.js or MJML.
- Local preview catalog for browser review.
- Artisan preview command for listing and rendering static HTML previews.
- Built-in boilerplate previews for transactional, action-required, report, metrics, and the full component catalog.
- Preview sections for boilerplates, Enso package-owned mail, and app-specific mail.
Usage
After installation, existing Laravel Markdown mail templates can keep using Laravel's standard mail namespace:
@component('mail::message') @component('mail::title', ['subtitle' => 'Your account was updated successfully.']) Account updated @endcomponent Hi Jane, Your profile details were updated. No further action is needed. @component('mail::button', ['url' => $url]) Open settings @endcomponent @component('mail::signature') @endcomponent @endcomponent
Applications customize the layout through config/enso/mails.php:
'brand' => [ 'name' => 'Solarlink', 'url' => 'https://solarlink.ro', 'logo' => 'https://solarlink.ro/images/mail-logo.png', 'label' => 'solarlink.ro', ], 'text' => [ 'font_family' => 'Poppins, Avenir, Helvetica, Arial, sans-serif', ], 'colors' => [ 'primary' => '#4aac2a', 'accent' => '#eb3a16', 'link' => '#eb3a16', 'dark' => '#121933', ],
The package supports common Laravel Markdown button aliases:
@component('mail::button', ['url' => $url, 'color' => 'red']) Set your new password @endcomponent
The aliases map to configured Enso color variants:
red -> danger
blue -> info
green -> success
Preview Catalog
The preview route is enabled outside production by default:
'preview' => [ 'enabled' => env('ENSO_MAILS_PREVIEW', env('APP_ENV') !== 'production'), ],
Open the catalog in a browser:
/enso-mails-preview
Open a specific preview:
/enso-mails-preview/password-reset
/enso-mails-preview/data-import-done
/enso-mails-preview/components
The route is intended for local and staging review. It does not send email; it renders preview views with fake structured data.
Registering Package And Application Previews
Packages and applications can register their own previews through the registry. Package-owned mail previews should live in a dedicated MailServiceProvider and packages that use the shared mail layouts should require laravel-enso/mails directly in composer.json.
namespace App\Providers; use Illuminate\Support\ServiceProvider; use LaravelEnso\Mails\Preview\PreviewDefinition; use LaravelEnso\Mails\Preview\PreviewRegistry; class MailServiceProvider extends ServiceProvider { public function boot(PreviewRegistry $registry): void { $registry->register(new PreviewDefinition( key: 'reset-password', name: 'Reset Password', view: 'laravel-enso/core::emails.reset', data: [ 'name' => 'Jane Doe', 'url' => 'https://example.test/password/reset/token', ], section: PreviewDefinition::AppSpecific, )); } }
Preview data should be fake and structured. Framework previews should not hardcode application-specific brand names, colors, logos, or business logic.
Preview Command
List registered previews:
php artisan enso:mails:preview --list
Render one preview to stdout:
php artisan enso:mails:preview password-reset
Render every registered preview to static HTML files:
php artisan enso:mails:preview --output=/tmp/mail-previews
The command is useful for batch QA, static review, and screenshot workflows. Browser review during development usually happens through /enso-mails-preview.
Package Build Flow
MJML is a package development dependency. Maintainers edit:
resources/mjml/html/message.mjml.blade.php
Then compile the runtime Blade views:
npm run build
The compiler writes:
resources/views/vendor/mail/html/message.blade.php
resources/views/vendor/mail/html/message-wide.blade.php
resources/views/vendor/mail/html/transactional.blade.php
resources/views/vendor/mail/html/action-required.blade.php
resources/views/vendor/mail/html/report.blade.php
Before releasing, verify the compiled Blade views are current:
npm run build:check
Consuming applications do not run this build step at runtime.
API
Config
The config namespace is:
enso.mails
Important groups:
brand: name, URL, logo, and label.colors: primary, accent, link, semantic variants, dark, light, and white tokens.layout: width, wide width, background, surface, border, radius, card radius, gutter.text: font family, spacing, body, muted, and heading colors.components: button, box, file, tag, and table defaults.footer: footer text, legal text, and links.markdown: Markdown theme and path behavior.preview: preview route enablement.
Components
Reusable Markdown components:
mail::titlemail::tagmail::buttonmail::boxmail::alertmail::quotemail::panelmail::filemail::metricmail::tablemail::schedulemail::dividermail::signature
Layout and compatibility components:
mail::layoutmail::headermail::footermail::subcopymail::messagemail::message-widemail::transactionalmail::action-requiredmail::report
The components preview documents every reusable content component with a short description and a rendered example.
Preview Registry
LaravelEnso\Mails\Preview\PreviewRegistry stores preview definitions.
LaravelEnso\Mails\Preview\PreviewDefinition accepts:
key: route and command identifier.name: human-readable catalog label.view: Blade view name.data: fake data passed to the view.
Commands
php artisan enso:mails:preview
php artisan enso:mails:preview --list
php artisan enso:mails:preview {preview}
php artisan enso:mails:preview --output=/path/to/output
Depends On
- PHP
^8.2 - Laravel Framework
^12.0|^13.0 mjmlas a package development dependency for compiling source MJML into runtime Blade views.
Contributions
are welcome. Pull requests are great, but issues are good too.
Thank you to all the people who already contributed to Enso!