Email templates

Design your app's emails in gemmein/emails.

The emails Gemmein sends for your app can wear your own design. Write one HTML file per email in gemmein/emails/<name>.html with {{var}} placeholders, and the sign-in email's brand in gemmein/emails/sign-in.json. npx gemmein sync saves them in Development, and go-live and promote copy Development's templates into Live. npx gemmein dev uses the same files exactly as the cloud does and writes each email to gemmein/.data/mail. An email with no template sends in Gemmein's plain design.

FileUsed forVariables
sign-in.jsonThe sign-in code email. A brand config, not HTML: Gemmein renders the whole email in one fixed layout around its own code. The subject and plain text stay Gemmein'sKeys: logoUrl brandColour backgroundColour appName greeting
purchase.htmlThe purchase email{{app_name}} {{product}} {{library_url}}
notify.htmlEvery notify() and relay email_person, unless a more specific template exists{{app_name}} {{subject}} {{body}}
notify-account.html, notify-event.htmlnotify() of that kindAs notify
email-person.htmlA relay's email_personAs notify
inbox-reply.htmlYour Inbox replies and new conversations, around your message{{app_name}} {{subject}} {{content}}
  • The sign-in brand. logoUrl is an https: image. When you save, Gemmein fetches it once (PNG, JPEG, GIF or WebP, up to 200 KB), keeps its own copy in your app's storage, and the email shows that copy, never your address. Changing the image at your address changes nothing until you save a changed sign-in.json. brandColour and backgroundColour are #rrggbb; a brand colour too light to read the code on is refused. appName (60 characters) is the header label when there is no logo; the sentence beside the code and the logo's description always use your app's real name. appName and greeting (120) are one line of plain text with no digits or numerals and nothing that looks like a web address. Every key is optional.
  • What an HTML template may hold. Layout and text elements (tables, div, p, headings, links, images, lists) and CSS for colour, fonts, spacing, borders, sizes and alignment, as plain values. A <style> block is inlined onto your elements; @media rules stay when every selector names a class.
  • What Gemmein removes. Scripts, forms, frames, embeds, SVG, media, <link>, <meta>, <base>, comments, event handlers, CSS url(), @import, @font-face, calc() and other CSS maths, positioning, transforms and negative values. Links are https:, mailto: or #; images are https: only; an address with a user part (https://a@b) is removed. Sync prints what was removed.
  • Variables. Every value is HTML-escaped. {{body}} and {{content}} keep their line breaks. {{library_url}} is the only variable that can be a link's address.
  • The footer. Your template renders inside its own box, and Gemmein adds its footer after it: your app's name and sending domain, and why the person received the email. The plain-text part is built from the result. None of these emails is marketing, so none has an unsubscribe line.
  • Versions and limits. The cloud keeps each template's last 10 versions. Each app can save templates 60 times and preview them 120 times an hour (150 and 300 per account).
  • Preview and test. npx gemmein emails preview <name> renders your local file with sample data into a page you open. npx gemmein emails test <name> sends one test of the synced template to the address you are signed in with. Tests count toward Development sends.
Was this page helpful?

Last updated