Appearance
Customizing the template
Three levels, in the order you should reach for them: change the configuration, use the components, publish the views.
1. Configuration
Most installations never need more than this.
php
// config/laraspring-mail.php
'brand' => [
'name' => env('LARASPRING_MAIL_PRODUCT_NAME'), // falls back to app.name
'logo' => env('LARASPRING_MAIL_LOGO_URL'), // absolute URL, or null for the name
'primary_color' => env('LARASPRING_MAIL_PRIMARY_COLOR', '#171717'),
'footer_lines' => [env('LARASPRING_MAIL_ADDRESS', '...')],
'unsubscribe_url' => env('LARASPRING_MAIL_UNSUBSCRIBE_URL'),
],primary_color reaches the button, the links and the rule across the top of the card. logo has to be an absolute URL served without authentication: an email client fetches it from the open internet with no session, so a relative path or a signed URL renders as a broken image.
The footer is a legal surface
footer_lines is drawn under the copyright line, one <p> per entry, and the default is a placeholder you are expected to replace. A physical postal address is not optional for anything a recipient could call marketing: CAN-SPAM requires it in the United States and several other jurisdictions ask for the equivalent.
unsubscribe_url is a placeholder too, and drawn only when you set it. It is deliberately not a working endpoint: an unsubscribe link that does nothing is worse than no link at all, and which emails a preference should silence is a product decision this package cannot make for you. Transactional mail, a sign-in link or an invitation, does not need one; a newsletter does.
2. Components
Inside a markdown mail, the mail:: namespace has the components Laravel ships plus three of ours. They are ordinary Blade, and they exist only while laraspring/mail is installed:
blade
<x-mail::button :url="$url">Sign in</x-mail::button>
<x-mail::code>ABC-123-XYZ</x-mail::code>
<x-mail::divider />
<x-mail::paragraph class="sub">Fine print.</x-mail::paragraph>
<x-mail::panel>Quoted aside, with the brand colour down its left edge.</x-mail::panel>code is for a short string the recipient has to read and retype: a one-time code, a recovery code, or the sign-in URL behind a button their client stripped. It is monospaced and letter-spaced so an 8 and a B are not the same glyph.
Every component has a plain-text counterpart, so using one never leaves the text part of the message half-built.
A package that uses a component depends on laraspring/mail
mail::code does not exist without this package. That is why the notifications in laraspring/auth and laraspring/organizations use none of them and stay on plain MailMessage lines and actions. Reach for a component in an email your edition owns, or in a package that already requires laraspring/mail.
3. Publishing the views
When the template itself is wrong for you:
bash
php artisan vendor:publish --tag=laraspring-mail-views
php artisan vendor:publish --tag=laraspring-mail-configThe views land in resources/views/vendor/mail, which is already first in mail.markdown.paths and therefore wins over the package's copies with no further wiring. Delete any file you did not want to change and it falls back through laraspring/mail to Laravel.
What is in there:
| File | Draws |
|---|---|
html/message.blade.php | the wrapper: header slot, body, subcopy, footer slot |
html/layout.blade.php | the document, the responsive rules, the card |
html/header.blade.php | logo or product name, linked to app.url |
html/footer.blade.php | copyright, footer lines, unsubscribe |
html/themes/laraspring.blade.php | the stylesheet, inlined into the message |
text/message.blade.php | the same, as plain text |
The theme is a .blade.php file rather than the usual .css because the brand colour has to reach it. Laravel resolves a theme through the view finder, which prefers .blade.php, so it is found and compiled like any other view.
Keep the selectors flat. Everything in the theme is inlined into style attributes before the message is sent, because a fair number of clients drop <style> blocks; descendant selectors survive inlining, pseudo-classes and media queries do not. The two media queries the layout needs are written into the layout's own <style> block instead.
Rewriting the words
Wording is not template work. Every string in the kit's notifications goes through __(), so a translation file changes them without touching a view:
php
// lang/en.json
{
"Use the button below to sign in. No password needed.": "Tap below and you're in."
}Replacing an email wholesale is a matter of listening for the event that sends it, MemberInvited for an invitation, and sending your own notification instead.