Skip to Content
Overview

Notifier

We got tired of every product app shipping its own email renderer, provider SDK, and template folder. Notifier is the shared notifications service we run instead: one HTTP API for templated email (React Email, MJML, HTML) and SMS (Termii), with Zeptomail or SES behind the scenes.

Your apps call POST /email/send or POST /sms/send. They never import React Email, MJML, or a mail/SMS SDK.

Private networks only. Do not put this on the public internet. Authenticate callers (API key or HMAC) and terminate TLS or mTLS at your ingress or mesh.

Why it exists

  • Copying Zeptomail/SES/Termii glue into every service means the same secrets handling, retries, and renderer deps everywhere.
  • Template and provider upgrades should ship with the notifications image, not force every consumer redeploy when @react-email or MJML moves.
  • Email and SMS share one auth story and one ops surface across products.

How you use it

  1. Run a notifier consumer: your config.yaml and templates baked into an image derived from the base notifier image. Start from examples/notifier-service.
  2. Give each product app the notifier URL and credentials. That is all they need.
  3. Send mail with POST /email/send (templateId + payload + recipients).
  4. Send SMS with POST /sms/send (to + body).
  5. Change a layout or add a template in the consumer repo, rebuild that image, redeploy. Apps keep calling the same HTTP API.

One shared service vs per-product images

The base image (ghcr.io/blockqueue/notifier) is the runtime: API, providers, compilers. A consumer image starts from that base and bakes in your config.yaml and /app/templates.

Most teams run one shared notifier on an internal network and give every product the same URL and credentials. Templates for all products can live in that one consumer image (ids must stay unique). You only need separate consumer images when templates, providers, or credentials must stay isolated between products or environments. Product apps never bake the notifier; they only HTTP-call it.

How it works (mechanics)

  1. You define accounts and auth in YAML.
  2. You add templates (template.yaml + index.tsx / index.mjml / index.html) and bake them into the consumer image.
  3. Apps POST /email/send or POST /sms/send with a signed or API-key request.
  4. Notifier validates the payload, renders (email), and calls the provider.

Guides

Source

github.com/blockqueue/notifier 

Last updated on