CerberusEmail
Cross-client-tested responsive email components for Phoenix, built on the Cerberus email framework.
Table-based layout with MSO/Outlook conditional comments and mobile stacking via media queries. Branding (product name, footer, colors, font) is passed as attrs — not hardcoded — so the same components work for any product.
Installation
def deps do
[
{:cerberus_email, "~> 0.1"}
]
end
Usage
<.email_layout brand_name="Acme" footer_text="Acme Inc" preview_text="Welcome!">
<.email_one_column_text_button
heading="Welcome to Acme"
button_text="Get Started"
button_url="https://acme.example.com/start"
>
<p style="margin: 0 0 10px;">Click below to get started.</p>
</.email_one_column_text_button>
</.email_layout>
Render to an HTML string for use with a mailer:
import CerberusEmail.Components
import Phoenix.Component
html =
~H"""
<.email_layout brand_name="Acme" footer_text="Acme Inc" preview_text="Welcome!">
<.email_one_column_text>
<p style="margin: 0;">Hello!</p>
</.email_one_column_text>
</.email_layout>
"""
|> Phoenix.HTML.Safe.to_iodata()
|> IO.iodata_to_binary()
Components
| Component | Description |
|---|---|
email_layout | Outer HTML shell with <head>, MSO comments, preview text, header, footer |
email_content_block | White-background content wrapper |
email_text_row | Text row with standard padding and typography |
email_button_row | Centered primary action button |
email_secondary_button_row | Outlined secondary button |
email_one_column_text_button | Combined heading + text + button block |
email_one_column_text | Text-only block |
email_spacer | Vertical spacer |
Branding attrs (email_layout)
| Attr | Default | Description |
|---|---|---|
brand_name | "App" | Shown in header and footer |
footer_text | falls back to brand_name | Footer line |
primary_color | "#3b82f6" | Button/accent color |
font_family | "'Inter', sans-serif" | Font stack |
preview_text | nil | Preview text shown in email clients |
show_header | true | Whether to render the brand name header |
License
MIT