Authoring

Actions and spans

Buttons, links and styled runs of text — the two inline components and the five span classes.

Two inline components make an email actionable: :button for the one thing the reader should do, and :link for everything else. Spans style a run of text with a small, fixed set of classes.

templates/payout.md
::actions
:button[View payout]{href="{{payout_url}}"} :link[See orders]{href="{{orders_url}}"}
::
The email gallery is not available
public/gallery/manifest.json was not found when the site was built. Run `pnpm gallery` in docs-site/ (it needs Go).

Add the primary button

:button[Label]{href="…"} renders a filled pill in the action colour, with a VML fallback so it stays a button in Outlook for Windows.

  • One per template. A second :button anywhere is more than one :button in the template. An email with two primary actions has none; make the others :link.
  • Only in an action row of a statement or an actions module. In a letter it is letter: :button is not allowed; use :link.
  • On its own. A :button in a paragraph with other text is :button must stand alone in its paragraph.

:link[Label]{href="…"} is a text link. How it renders depends on where it is:

  • In an action row, it is a bold link in the action colour with › appended, unless the label already ends with ›.
  • In running text, it is an ordinary underlined link with no arrow — the same as [Label](…).
templates/fees.md
We're lowering commission on services, as :link[the policy]{href="https://example.com/policies/fees"} explains.

:link[Read the full policy]{href="https://example.com/policies/fees"}

The first :link is inline; the second is alone in its paragraph, so it forms an action row and renders as "Read the full policy ›".

Write the label and href

Both components take exactly one attribute, href, and a label:

RuleApplies toError
href is required and not empty.every :button and :link:link: missing href
No other attributes.every :button and :link:button: unknown attribute "target"
The label is required.actions in an action row:button: missing label
The label is plain text and merge tags only — no emphasis, code or links.actions in an action row:link: label must be plain text

A :link inside running text is an ordinary link, so its label is inline Markdown like any link text (:link[**bold**]{href="…"} compiles), and an empty label is not checked.

href is text, so it can hold merge tags; how their values are escaped is in Know how URLs are escaped. At render time every URL must use https, http, mailto or tel, with a host (or an address), and no whitespace; anything else is a render error. Relative URLs are allowed only when Config.AllowRelativeURLs is set, for previews.

Build an action row

A paragraph made only of :button and :link components, separated by spaces or line breaks, is an action row. Its actions sit side by side; in a statement or actions module they stack, full width, on mobile.

WhereAllowed actions
statement:button and :link
actions (c1–c3):button and :link; the module is exactly one row
letter, including loose Markdown:link only
any other modulenone (notice: action row is not allowed here)

In the plain-text part, each action becomes its label with a colon, then its URL on the next line:

order.out_for_delivery.txt
Track delivery:
https://caribhubs.com/orders/CH-20417

Inside paragraphs, list items, table cells and notices, use ordinary Markdown links:

templates/reset.md
If you keep getting these, [secure your account]({{security_url}}).
Write to <help@example.com> or see <https://example.com/help>.
  • [text](url) — the destination can hold merge tags. A link title ([text](url "title")) is link titles are not supported.
  • <https://…> — an autolink shows the address as its text.
  • <name@example.com> — an email autolink becomes a mailto: link.
  • :link[text]{href="…"} in a sentence is the same as [text](…).

In the plain-text part a link is written text (url), or just the URL when the text is the URL, or just the address for an email autolink.

Style text with spans

[text]{.class …} wraps inline Markdown in a style. The classes combine:

ClassEffect
.mutedThe secondary text colour.
.tealThe action colour. Wins over .muted if both are set.
.monoThe theme's monospace font.
.smallSmaller type: 13px on an 18px line.
.boldBold weight.
templates/job.md
::breakdown
| Delivery fee | [**{{fee}}**]{.teal} |
| --- | ---: |
| [Payment]{.small .muted} | [Buyer paid in app]{.small .muted} |
::

Any other class is a compile error, unknown span class ".red", and a span accepts no #id or key=value (span: unknown attribute "#id"). The styles apply to the HTML part only; the plain-text part shows the text.

Spans are the only place a class may go. {.small} directly after a code span, a link or emphasis is attributes are only allowed on spans and inline components, so wrap the element in a span: [`{{reference}}`]{.small .muted}.

Next steps

Copyright © 2026