Newsletter Management Overview

The newsletter module lets you reach your confirmed subscriber list from the admin portal. This article covers the full workflow: understanding your subscriber list, composing a draft, previewing, scheduling or sending, and what happens after delivery.

Before you begin

  • The newsletter subscribe widget on your public site is configured. See Website Integration.
  • ADMIN_PORTAL_RESEND_API_KEY is set as a Worker secret so emails can be dispatched.
  • Your Resend sending domain is verified (SPF + DKIM in DNS).

How subscribers are managed

Subscribers arrive through the opt-in widget on your public site. The process:

  1. Visitor enters their email and submits.
  2. A pending record is created in the NEWSLETTER KV namespace under a SHA-256-hashed email key.
  3. A confirmation email with a unique link is sent via Resend.
  4. The visitor clicks the link; the record updates to confirmed.
  5. Only confirmed subscribers receive newsletter sends.

The plaintext email address is never stored as a KV key or in any log. The hash is one-way — you cannot recover the address from it. Email addresses are rendered in cleartext only in the authenticated portal view.

To view your subscriber list:

Navigate to Newsletter → Subscribers. Each row shows:

Column What it shows
Identifier Truncated hash of the subscriber’s email
Email Plaintext address (visible in the authenticated portal only)
Status Confirmed, Pending, or Unsubscribed
Confirmed at Date and time the subscriber clicked the confirmation link

Composing a newsletter

  1. Go to Newsletter → Compose.
  2. Enter a Subject line — this is the line subscribers see in their inbox before opening. Keep it concise and descriptive.
  3. Write the body in Markdown. Formatting supported: headings, bold, italic, links, unordered lists. Inline images are not supported at this time.
  4. Select Preview to see a rendered version of the email as it will appear to subscribers. Check that links work and formatting looks correct before proceeding.
  5. Select Save draft to return to the compose screen later, or continue to send or schedule.

Sending and scheduling

Newsletter send flow — compose, preview, send or schedule, Resend API, subscriber inboxes

Send now dispatches immediately to all confirmed subscribers. Use this when timing is not important or you want the newsletter to arrive as soon as possible.

Schedule queues the send for a specific date and time. The portal stores the scheduled send and dispatches it at the chosen time. Pick a time that accounts for your subscribers’ time zones — most audiences engage more with email received during their local morning.

Both options send via Resend, which tracks delivery per subscriber. Sent newsletters appear in Newsletter → Sent with:

  • Total recipients
  • Delivered count
  • Bounce count (permanent delivery failures)
  • Unsubscribe count triggered by this send

Unsubscribes

Every outbound newsletter includes two unsubscribe mechanisms:

In-body link — A plain-text “Unsubscribe” link at the bottom of every email. Clicking it posts to /api/newsletter/unsubscribe with the subscriber’s token. The record is set to unsubscribed immediately and the subscriber is excluded from all future sends.

List-Unsubscribe header — Every email includes a List-Unsubscribe header conforming to RFC 8058. Mail clients that support one-click unsubscribe (Gmail, Apple Mail, recent Outlook versions) show an Unsubscribe button in their interface — no email body link is needed. Clicking it posts to the unsubscribe endpoint automatically.

Unsubscribed records are retained in the KV namespace as unsubscribed status. This prevents a re-subscribe from accidentally reactivating someone who opted out.


Bounces

Hard bounces (permanent delivery failures — invalid address, domain does not exist) are reported by Resend and surfaced in the Sent newsletter report. Subscribers that hard-bounce are marked as bounced in the portal and excluded from future sends automatically.

Soft bounces (temporary failures — mailbox full, server unavailable) are retried by Resend and do not affect subscriber status unless they persist.


Next steps