email brand hygiene #11

Merged
archvillainette merged 14 commits from email-brand-hygiene-spec into main 2026-06-27 08:02:15 +00:00
2 changed files with 114 additions and 0 deletions
Showing only changes of commit bf5c710c2b - Show all commits
+69
View File
@@ -0,0 +1,69 @@
# Build note: the email templates import `emails/partials/header.html` and `emails/partials/footer.html` through NodeBB's `emails/` view namespace.
# Email templates
HTML email templates for the Westgate theme. NodeBB renders these and mails
them to users on various events (password reset, digest, ban, etc.).
## How NodeBB uses them
- **Discovery.** NodeBB looks for email templates under a theme/plugin's
templates directory. Core ships them in `src/views/emails/*.tpl`; a theme
overrides one by shipping a file of the same name. The `email/` directory
here is built into NodeBB's `emails/` view namespace, so `email/reset.html`
overrides the core `reset` template. Run `./nodebb build` after editing so
the changes are compiled into `build/`.
- **Template engine.** [Benchpress](https://github.com/benchpressjs/benchpressjs),
the same engine as the rest of the theme's `.tpl` files. Syntax:
- `{var}` / `{obj.field}` — interpolate a value from the params object.
- `{{{ if cond }}} … {{{ else }}} … {{{ end }}}` — conditionals
(e.g. `{{{ if logo.src }}}`, `{{{ if showUnsubscribe }}}`, `{{{ if rtl }}}`).
- `[[namespace:key]]` — i18n translation key, resolved server-side after
render (e.g. `[[email:reset.cta]]`, `[[email:greeting-no-name]]`). Strings
live in NodeBB's language files, not here.
- **Send path.** `Emailer.send(template, uid, params)`
`sendToEmail``renderAndTranslate('emails/<name>', params)`. `<name>` is
the filename without extension (`reset.html` → template name `reset`).
- **Default params** available in every template: `url`, `site_title`,
`logo.{src,width,height}`, `uid`, `username`, `displayname`, `rtl`, plus
`showUnsubscribe` / `unsubUrl` for digest- and notification-type mails.
Each template also gets its own event-specific params (see table).
## Templates and what triggers them
| File | NodeBB event | Notable params |
|------|--------------|----------------|
| `welcome.html` | New registration needing email confirmation | confirmation link |
| `verify-email.html` | User adds/changes an email and must confirm it | confirmation link |
| `reset.html` | User requests a password reset | `{reset_link}` |
| `reset_notify.html` | Confirmation that the password was changed | — |
| `registration_accepted.html` | Admin approves a queued registration | — |
| `banned.html` | User is banned | ban reason / expiry |
| `invitation.html` | A user is invited to the forum | invite link |
| `notification.html` | Per-event notification (reply, mention, etc.); also post-queue items | `showUnsubscribe`, `unsubUrl` |
| `digest.html` | Scheduled activity digest (daily/weekly/monthly) | unread topics, `showUnsubscribe` |
| `test.html` | "Send test email" button in the ACP | — |
## Partials
`partials/` holds fragments included by the templates above:
- `header.html` — shared email head/header markup.
- `footer.html` — shared footer with the unsubscribe block
(`{{{ if showUnsubscribe }}}`).
- `post-queue-body.html` — renders a queued post (category, topic, author,
content) inside `notification.html` for post-queue notifications.
## Editing notes
- These are emails: inline CSS, table layout, MSO/Outlook conditional
comments. Keep that structure — don't refactor into modern CSS.
- Don't hardcode user-facing copy; add/replace `[[email:…]]` keys and define
them in the language files.
- Rebuild (`./nodebb build`) and use the ACP test-email button to verify.
## References
- [NodeBB themes](https://docs.nodebb.org/development/themes/)
- [NodeBB templating](https://docs.nodebb.org/development/themes/templates/)
- [Email templating discussion](https://community.nodebb.org/topic/1502/email-templating)
+45
View File
@@ -0,0 +1,45 @@
<!-- IMPORT emails/partials/header.html -->
<!-- preheader -->
<div style="display: none; max-height: 0; overflow: hidden; mso-hide: all;">[[email:reset.preheader]]</div>
<div style="display: none; max-height: 0; overflow: hidden; mso-hide: all;">&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;</div>
<!-- Email Body : BEGIN -->
<table role="presentation" cellspacing="0" cellpadding="0" border="0" align="center" width="100%" style="max-width: 600px;">
<tr>
<td bgcolor="#fbf7ef">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="padding: 40px 40px 6px 40px; font-family: Jost, system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif; font-size: 15px; line-height: 20px; color: #3a3340;">
<h1 style="margin: 0; font-family: Cinzel, Georgia, 'Times New Roman', serif; font-size: 24px; line-height: 27px; color: #1a1418; font-weight: normal;">[[email:greeting-no-name]]</h1>
</td>
</tr>
<tr>
<td style="padding: 0px 40px; font-family: Jost, system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif; font-size: 15px; line-height: 20px; color: #3a3340;">
<h1 style="margin: 0 0 10px 0; font-family: Cinzel, Georgia, 'Times New Roman', serif; font-size: 18px; line-height: 21px; color: #9a9086; font-weight: normal;">[[email:reset.text1]]</h1>
</td>
</tr>
<tr>
<td style="padding: 20px 40px; font-family: Jost, system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif; font-size: 15px; line-height: 20px; color: #3a3340;">
<p style="margin: 0">[[email:reset.text2]]</p>
</td>
</tr>
<tr>
<td style="padding: 32px 40px; font-family: Jost, system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif; font-size: 15px; line-height: 20px; color: #3a3340;">
<!-- Button : BEGIN -->
<table role="presentation" cellspacing="0" cellpadding="0" border="0" align="center" style="margin: auto">
<tr>
<td style="border-radius: 3px; background: #2a1222; text-align: center;" class="button-td">
<a href="{reset_link}" style="background: #2a1222; border: 15px solid #2a1222; border-color: #c2a35a; font-family: Jost, system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif; font-size: 13px; line-height: 1.1; text-align: center; text-decoration: none; display: block; border-radius: 3px; font-weight: bold;" class="button-a">
<span style="color: #f4ecd8" class="button-link">[[email:reset.cta]] &rarr;</span>
</a>
</td>
</tr>
</table>
<!-- Button : END -->
</td>
</tr>
</table>
</td>
</tr>
</table>
<!-- Email Body : END -->
<!-- IMPORT emails/partials/footer.html -->