04-Apr-2026 — Mobile-friendly templates, GDPR link fix, and data-driven override model #213
build 574 — commit 1368240
Emails now readable on mobile devices
- All Brevo email templates are now mobile-friendly. Emails that previously required rotating to landscape on a phone will now reflow to fit the screen in portrait mode.
- This applies to all email types: welcome emails, password resets, membership expiry notifications, campaigns, and more.
Broken GDPR link fixed
- The GDPR link in the "Unsubscribing" section of the welcome email pointed to eugdpr.org which has been returning 404 for some time.
- This now links to the ICO (Information Commissioner's Office) UK GDPR guidance page at https://ico.org.uk.
Site-specific image overrides for welcome email
- in order to see where this configuration is performed, navigate to Admin > Mail Settings.
- Site specific image overrides are demonstrated with reference to the "Welcome to the Group" Email Configuration 12 of 13 — which is the the first template where new Template Image Overrides section have been implemented.
- You can select this by choosing this value in the email configuration selector:

The original welcome email template contained placeholder text e.g.
<homepage-image-goes-here>where each group's webmaster should add screenshots of their site (walks programme, social events page, login prompts, etc).However, this was just a generic placeholder that required the Webmaster to know what to do in order to replace it within the Brevo editor. This was not discoverable, and also required images to be exported to Brevo, requiring extra effort and the need to save image data outside of the realm of the group's website.
Additionally, this approach could easily cause customisation to be overridden when NGX Ramblers releases affected email template content, causing data to be undesirably overwritten.
To resolve all of the above issues, these placeholders are now managed through the admin UI using the CMS Image Cropper And Resizer — webmasters upload/crop images through the standard CMS interface, no HTML knowledge needed.
Backend auto-wraps stored image URLs in responsive img tags at send time.
These images are preserved when the central base template is updated — your group's customisations will never be overwritten by a template push.
The Template Image Overrides panel when first opened — each slot shows not configured. Every override slot shown here is discovered automatically from
{{override.*}}markers in the template HTML.

- Opening a slot reveals the shared Image Actions → Add image dropdown. Selecting Add image launches the standard CMS image cropper, so there is no bespoke image-upload UI to learn.

- Once the screenshot has been cropped and saved, the slot header flips to configured and a preview is shown inline. The same Image Actions dropdown now offers edit, replace, and remove.
- Below is a real example of what an admin would see for the Walks Programme Image override — the live Walks Programme page from East Kent Walking Group.

- A screenshot of the final rendered welcome email, with the two configured overrides (Walks Programme page and site home page) embedded responsively alongside the template's own intro text is shown below:

Technical Details
Fully data-driven override discovery
Override definitions are NOT hardcoded in code. Instead, the
system scans template HTML for {{override.KEY}} markers at
runtime and dynamically generates override slots in the admin UI.
This is essential for rollout to 500+ groups — each group's admin
UI automatically reflects whatever markers exist in the current
template, with no code changes or deployments needed.
extractOverrideKeys()scans any template HTML for{{override.*}}patterns and returns unique keysoverrideKeyToLabel()auto-generates human-readable labels from keys (e.g.WALKS_PROGRAMME_IMAGE→ "Walks Programme Image")- Default placeholder content is generated dynamically (e.g. "[Walks Programme Image — to be added by your webmaster]")
- The server returns discovered override keys via the template
diff endpoint (
TemplateDiffResponse.overrideKeys) - The admin UI renders override slots from these server-discovered keys, not from any static registry
- Adding a new
{{override.XXX}}marker to a template and pushing it centrally is all that's needed — every group's admin UI immediately shows the new image upload slot Removed the hardcodedTEMPLATE_METADATAregistry,TemplateCategoryenum, andTemplateOverrideDefinitioninterface which were not scalable for multi-tenant rollout.
Responsive CSS — DRY injection
- Rather than duplicating responsive CSS across all 8 template HTML
files, a shared module (
responsive-email-styles.ts) defines the styles once. ThereadLocalTemplate()function inlocal-template-reader.tsauto-injects viewport meta, charset, and media query styles into any template that lacks them. Templates that already have responsive CSS (e.g.fully-automated-text-body) are left untouched. Template HTML files on disk remain clean.
Base vs override template model
NotificationConfigandEmailRequestgain an optionaltemplateOverrides: Record<string, string>field- MongoDB schema updated to persist overrides per notification config
- Welcome template image placeholders replaced with named markers
(
{{override.WALKS_PROGRAMME_IMAGE}}, etc — 6 unique keys, 7 occurrences) applyTemplateOverrides()inmessages.tsscans the template HTML for override markers and resolves them: site override image if configured, otherwise a styled default placeholder- Override substitution runs after HTML sanitisation but before
merge field substitution in
performTemplateSubstitution() createEmailRequest()inmail-messaging.service.tspassestemplateOverridesfrom the notification config through to the backend
Override discovery pipeline
- Admin selects a template in Email Configurations
- Frontend calls
templateDiffendpoint - Server fetches template HTML from Brevo, scans for
{{override.*}}markers viaextractOverrideKeys() - Returns discovered keys in
TemplateDiffResponse.overrideKeys - Frontend renders an image upload slot per key using
overrideKeyToLabel()for display labels - Webmaster uploads images via CMS ImageCropperAndResizerComponent
- Values stored in
NotificationConfig.templateOverrides(MongoDB) - At send time,
applyTemplateOverrides()replaces markers with img tags or default placeholders
Files changed
mail.model.ts— extractOverrideKeys(), overrideKeyToLabel(), overrideKeys on TemplateDiffResponse, templateOverrides on NotificationConfig and EmailRequest interfaces. Removed TEMPLATE_METADATA, TemplateCategory, TemplateOverrideDefinitionmail-notification-template-editor.ts— override slots driven by server-discovered keys via discoveredOverrideKeys array, labelForKey() for display labels, image upload via CMS ImageCropperAndResizerComponentmail-messaging.service.ts— pass templateOverrides in requestwelcome-to-the-group.html— GDPR link fix, override markersmessages.ts— data-driven applyTemplateOverrides() scans HTML for markers instead of using hardcoded registrytemplate-diff.ts— returns overrideKeys discovered from template HTMLlocal-template-reader.ts— responsive CSS injectionresponsive-email-styles.ts— shared responsive CSS module (new)notification-config.ts— templateOverrides in MongoDB schema Reported by Charlie Bigley (via Bolton Ramblers) — 2 Apr 2026
Follow-up fixes and polish
- Brevo editor URL corrected to
https://editor-app.brevo.com - Template sanitisation now collapses blank lines before push/diff operations
- Nested Brevo/API error extraction improved so the UI shows the real underlying error message
- Sensitive config redaction now preserves existing secrets on save when masked values are posted back
- Selected email configuration is reflected in the URL via
?configuration=... - Mail settings/template bindings were stabilised to remove the NG0103 change-detection loop on Email Configurations
- CMS image cropper now supports clipboard image paste, image URLs,
site-content/...paths, existing-image preload editing, and live unsaved preview updates - PNG/WebP uploads can now be cropped, and compression updates the generated output more reliably
- Template Image Overrides now render as collapsible accordion panels and use the shared Image Actions dropdown so existing images can be edited, replaced, or removed consistently with the inline image editor
- After pushing the default template, the local/default diff badge now updates immediately to show the matched state
- Merge field tokens inside HTML attribute values (e.g.
href="..."orsrc="...") are no longer wrapped in Brevo editor pill spans during template push, fixing a bug where broken<a href="<span>...</span>">markup was leaking into the Brevo rich text editor. Merge fields in visible text content are still wrapped as editable pills as intended.