PhoenixKit.Email.Branding (phoenix_kit v2.55.1)

Copy Markdown View Source

The site's branding as email variables: its logo and its accent colour.

PhoenixKit.Email.Content.resolve/5 binds both in every part of a message built from a file or a default — the body, _layout, _header and _footer — so a host's files and core's own layout read the same values.

placeholdervalue
{{logo_url}}an absolute URL of the project logo, or ""
{{accent_color}}the email_accent_color setting as #rrggbb, or #18181b

Both are read on every send, so a changed setting shows in the next email without a restart.

A caller may bind either variable itself; merge/2 keeps its value only when it is valid — a #rrggbb colour, an empty or http(s):// logo URL — and uses the site's otherwise, on every path a template can read it.

The logo is the one already set under Settings (Settings.get_logo_uuid/0: the project logo, else the site icon). Its URL carries the permanent signed token, so it keeps working in an email opened weeks later. A logo stored in a private library would need a time-window token that expires long before the email is read, so none is minted: logo_url is empty and core's header prints the site's name instead.

A logo in the trash, or one that no longer exists, gives no URL either.

The first finished one, in this order, that every email client shows — PNG, JPEG or GIF:

small  →  medium  →  large  →  original

A transparent logo's JPEG-configured sizes are written as PNG (VariantGenerator.output_format/3), or as WebP when the host sets config :phoenix_kit, :variant_alpha_format, "webp". Outlook for Windows shows no WebP, so a WebP size is passed over — usually for the original, when that is a PNG. A logo with no such file (an SVG with WebP sizes, or sizes still being made) gives no URL, and core's header prints the site's name. Sizes made before transparent images were written as PNG are JPEG, so such a logo arrives on a white background until its sizes are regenerated. The URL carries the file's version, so a mail client may cache it for good.

The accent colour

A six-digit hex colour (#1d4ed8), checked on every read: anything else — unset, red, #abc, a value with a ; in it — reads as the neutral default, so a bad value can never reach a style attribute.

Summary

Functions

The accent colour setting, normalised by normalize_color/1.

The settings key that holds the accent colour.

The accent colour setting as #rrggbb, or nil when it is unset or not a valid colour — the "has the site chosen a colour?" question core's layout asks before drawing its accent bar.

The accent colour used when none (or no valid one) is set.

An absolute URL of the project logo for an email, or "" when there is no logo, it is in the trash or no longer exists, it sits in a private library, it has no file every mail client shows (see "Which file of the logo"), or the lookup fails.

variables (string keys) with the branding variables added: a caller's own logo_url or accent_color is kept only when valid (see valid_color?/1 and valid_logo_url?/1), otherwise branding's value is used. A kept colour is normalised.

value as a lower-case #rrggbb colour, or the default accent colour when it is not a six-digit hex colour.

The text colour that reads on background (a colour as normalize_color/1 returns it): white on a dark colour, near-black on a light one — whichever contrasts more, by WCAG relative luminance.

Whether value is a six-digit hex colour (surrounding whitespace allowed).

Whether value can stand as a logo URL: empty (no logo), or an absolute http(s):// address.

Both branding variables, keyed as the templates read them.

Functions

accent_color()

@spec accent_color() :: String.t()

The accent colour setting, normalised by normalize_color/1.

accent_color_key()

@spec accent_color_key() :: String.t()

The settings key that holds the accent colour.

configured_accent_color()

@spec configured_accent_color() :: String.t() | nil

The accent colour setting as #rrggbb, or nil when it is unset or not a valid colour — the "has the site chosen a colour?" question core's layout asks before drawing its accent bar.

default_accent_color()

@spec default_accent_color() :: String.t()

The accent colour used when none (or no valid one) is set.

logo_url()

@spec logo_url() :: String.t()

An absolute URL of the project logo for an email, or "" when there is no logo, it is in the trash or no longer exists, it sits in a private library, it has no file every mail client shows (see "Which file of the logo"), or the lookup fails.

merge(variables, branding)

@spec merge(%{required(String.t()) => term()}, %{required(String.t()) => String.t()}) ::
  %{
    required(String.t()) => term()
  }

variables (string keys) with the branding variables added: a caller's own logo_url or accent_color is kept only when valid (see valid_color?/1 and valid_logo_url?/1), otherwise branding's value is used. A kept colour is normalised.

normalize_color(value)

@spec normalize_color(term()) :: String.t()

value as a lower-case #rrggbb colour, or the default accent colour when it is not a six-digit hex colour.

iex> PhoenixKit.Email.Branding.normalize_color(" #1D4ED8 ")
"#1d4ed8"

iex> PhoenixKit.Email.Branding.normalize_color("red;background:url(x)")
"#18181b"

text_color_on(background)

@spec text_color_on(String.t()) :: String.t()

The text colour that reads on background (a colour as normalize_color/1 returns it): white on a dark colour, near-black on a light one — whichever contrasts more, by WCAG relative luminance.

valid_color?(value)

@spec valid_color?(term()) :: boolean()

Whether value is a six-digit hex colour (surrounding whitespace allowed).

iex> PhoenixKit.Email.Branding.valid_color?("#1d4ed8")
true

iex> PhoenixKit.Email.Branding.valid_color?("#1d4ed8;x:y")
false

valid_logo_url?(value)

@spec valid_logo_url?(term()) :: boolean()

Whether value can stand as a logo URL: empty (no logo), or an absolute http(s):// address.

variables()

@spec variables() :: %{required(String.t()) => String.t()}

Both branding variables, keyed as the templates read them.