Email components

Write content in ordinary HTML and use email components only where a client needs table layout, button fallbacks, or required alt text.

Import Email, Section, Columns, Column, Button, Spacer, Divider, Image, Link, IssueContent, IssueTitle and IssueDate from @samva/markup/email.

Write content in ordinary HTML: headings, paragraphs, lists, links, and tables. Components exist for email-client layout and the issue slots:

ComponentWhy it exists
EmailThe document shell: <head>, reset styles, dark-mode meta, and the preheader slot
SectionA full-width band, emitted as a table so Outlook keeps it
Columns, ColumnSide-by-side layout as table cells, stacking on mobile
ButtonA link styled as a button, with an Outlook fallback shape
ImageRequired alt, fixed dimensions, and a dark-mode source
Spacer, DividerVertical rhythm and rules that survive clients that strip margins
LinkA text link that opens outside the client
IssueContentThe slot where a Markdown issue supplies the layout's content
IssueTitle, IssueDateThe issue's frontmatter title and date, as text in an issue layout

The brand components BrandLogo and BrandFooter come from samva:brand; see Brands.

  • A Button needs a string label and a height for the classic Outlook fallback. Without them the check warns with button-outlook-fallback.
  • Scripts, event handlers, and unsafe URL schemes are rejected. Strings are escaped text, never markup.
  • General flex and grid layouts are not converted to email tables. Use Columns for side-by-side content.
  • subject and preheader live on the email channel of the definition. <Email> does not take a preheader.

See Authoring in TSX for a complete template.

Issue content slot

An issue layout is an email-only defineTemplate with one <IssueContent /> from @samva/markup/email. Place it where the compiled Markdown body belongs. It takes no props or children and must appear unconditionally, outside loops and conditions. Compiling the layout as an issue replaces the slot with that issue's content; it is not an ordinary content component.

<IssueTitle /> and <IssueDate /> print the issue's frontmatter title and date as text, under the same placement rules. IssueDate formats the YYYY-MM-DD date at compile time like fmt.date (Oct 28, 2026 by default, in UTC); literal style and locale props change that. An issue without a date prints nothing.

layout.tsx
import { defineTemplate } from "@samva/markup";
import { Email, IssueContent, IssueDate, IssueTitle, Section } from "@samva/markup/email";
import { jsonSchema } from "@samva/markup/input-schema";

export default defineTemplate({
  id: "newsletter-layout",
  schema: jsonSchema({ type: "object", properties: {}, additionalProperties: false }),
  fixtures: { default: {} },
  email: {
    subject: () => "Newsletter",
    body: () => (
      <Email>
        <Section>
          <h1><IssueTitle /></h1>
          <p><IssueDate /></p>
          <IssueContent />
        </Section>
      </Email>
    ),
  },
});

Preview · Available to selected organizations.

Author and send newsletter issues describes creating Markdown, previewing it in a layout, and saving the commit a campaign sends.

Related documentation

On this page