Email & PDF Documents
Branded templates
Every transactional email and generated PDF (invoice, quote, receipt) shares a consistent brand shell, including an embedded logo (loaded once at startup, base64-encoded — no external CDN dependency at send time).
Recipient-based palette: templates are styled by who actually receives them, not by which module sent them.
- External / customer-facing (onboarding, invoices, quotes, receipts, reminders): a blue/white palette.
- Internal / staff-facing (OTP, password reset, staff notifications, admin security alerts): the CRM’s gold-on-navy palette.
Security: HTML escaping
Every value substituted into an email template is HTML-escaped by default —
a staff-entered customer name or note can’t inject markup into an email
rendered by a real mail client. The one deliberate exception is
server-generated URLs (e.g. a reset link), which must render as literal
href targets rather than escaped text.
Server-built HTML fragments that are meant to render as markup (not user input) — like the internal admin security-alert emails — go through a separate, explicitly-named method rather than being exempted by variable name, so the escaping rule can’t accidentally be bypassed for real user data later.
PDF rendering constraints
PDFs (invoice, quote, receipt) are rendered by a library that does not
support CSS flexbox — display: flex, align-items, and gap are silently
ignored, falling back to block stacking. This only affects the three PDF
templates; it’s not a constraint on regular transactional emails, which
render in real browsers/mail clients.