Footer Badges — a row of images under the signature

Featurekamo-internal
Shipped
September 3, 2026 at 10:57 PM UTC
Author
Kamo
Commit
3e18601

The Content tab's 'Footer Image' was one picture chosen from three fixed sources and sized by a percentage. It is now 'Footer Badges': the same three plus anything the organization uploads, ticked and ordered per source, drawn at one shared height with one gap between them. The library is org-wide and the selection is per source, so an image uploaded while editing the individual signature is offered under all three and printed only where it is ticked. What is stored is IDS; the URL and label are resolved against the library on every render, because the picture behind member-avatar is the SENDER's and a URL saved beside the id would be the stale copy. An id the library no longer has is dropped rather than rendered, so a badge deleted in another tab never becomes a broken glyph in a footer. A percentage was right for one image and is wrong for a row: differing intrinsic sizes never line up. So the scale slider became a HEIGHT, every badge keeps its own aspect ratio, and where the stored size is known the img carries an explicit width too — Outlook ignores width:auto and stretches to the cell. The gap is left padding on every cell but the first, so a single badge gets none: a lone image nudged 15px right of everything above it reads as a misalignment, and the spacing control is hidden in that case for the same reason. Uploads are downscaled to 150px tall before they are sent, through the new resize-height endpoint that keeps the file's format and transparency — the existing resize-bg re-encodes to lossy WebP, which half the mail clients in use cannot display at all. Badges are addressed at api.<apex> of the apex being browsed, so a white-label tenant's mail carries its own host and the page CSP (img-src … https://*.<apex>) does not silently refuse the preview. Dirty-state now compares a FINGERPRINT rather than raw JSON. headerImageUrl, signatureImageUrl and each badge's url/label are looked up after load, on their own schedule, and the badge library is a separate request — so comparing raw JSON lit the Save button on page load with nothing touched, and put the unsaved- changes dialog in front of anyone who then switched source.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing