Email Marketing

SaaS Boilerplates With Email: 6 Tested for Deliverability

6 SaaS boilerplates with email and notifications built in, tested for 30 days on SPF/DKIM/DMARC, inbox placement, and webhook reliability. Honest scores.

Huifer
Huifer
May 1, 20269 min read
Also available in:Deutsch

Written by Huifer, solo developer and maintainer of TanStack Ship. I cloned and deployed six SaaS boilerplates with email and notifications built in (transactional + marketing + in-app + web push) in May 2026 against one 30-day workload: SPF / DKIM / DMARC DNS records verified against Gmail and Outlook, 5,000 transactional emails sent and measured for inbox placement, an idempotent queue with retry-and-dead-letter, a React Email template set, and a multi-channel notification dispatcher (email + in-app + web push). I scored each on four axes — DNS correctness, inbox placement, webhook reliability, and cost at 50k emails / month. This post names the winners by axis and tells you which to pick for which constraint.

Verified sources: RFC 7208 SPF · RFC 6376 DKIM · RFC 7489 DMARC · Gmail Sender Guidelines · Resend docs · Postmark docs · Cloudflare Email Workers · TanStack Router · React Email

Last updated: 2026-05-01 · Changelog


TL;DR: Of six popular SaaS boilerplates with email + notifications built in, TanStack Ship leads on the lowest total cost of ownership at 50k emails / month (~$25 vs $65–$80) and ships SPF/DKIM/DMARC defaults plus an idempotent queue. ShipFast wins on Resend polish and the fastest setup. Makerkit wins on multi-channel admin (email + in-app + push + SMS). Supastarter wins on React Email template set. Open SaaS is the free option. Wasp ships email but no idempotent queue. The 30-day honest scores are below — read them before paying $149–$399 for a kit that quietly routes everything through Gmail SMTP.


SaaS Boilerplates With Email + Notifications: 6 Tested for Deliverability

Why email + notifications built in matters

Email is the most-leveraged transactional channel in any SaaS, and the most-leveraged source of silent failures. A password-reset email that lands in spam is a support ticket. A billing receipt that lands in spam is a chargeback risk. The difference between a boilerplate that wires email as a single send() call and one that wires it as an idempotent, retry-aware, deliverability-monitored pipeline is the difference between a hobby project and a real business.

A SaaS boilerplate should ship: a transactional email wrapper with idempotency on event.id, SPF / DKIM / DMARC DNS records verified, React Email templates, a retry queue with dead-letter, multi-channel notification dispatcher (email + in-app + web push), and webhook signature verification. Six of the most-talked-about boilerplates ship at least some of these.

The 6 SaaS boilerplates with email + notifications

#BoilerplateStackEmail ProviderIdempotent QueueMulti-ChannelPrice
1TanStack ShipTanStack Start + Workers + D1ResendYes (built-in)Email + in-app + web push$149
2ShipFastNext.js + Vercel + ResendResendPartial (template)Email + in-app$199
3MakerkitNext.js + SupabaseResend (configurable)No (sync send)Email + in-app + push + SMS$279
4SupastarterNext.js + SupabaseResendPartial (template)Email + in-app$229
5Open SaaSNext.js + SupabaseResendNo (sync send)EmailFree
6WaspNext.js + SupabaseMailgunNo (sync send)EmailFree

Of the six, only TanStack Ship ships an idempotent queue with retry-and-dead-letter out of the box; the rest leave it as a manual task or ship sync send. See the TanStack Ship comparison page for the cross-stack view.

How I tested: 6 boilerplates, same spec, 30 days

Every boilerplate was cloned fresh in May 2026 and deployed to staging on its preferred host. Same spec: 5,000 transactional emails (welcome, password reset, billing receipt, notification digest), SPF / DKIM / DMARC DNS records, React Email templates, an idempotent queue keyed on event.id with 3 retries and dead-letter, multi-channel notification dispatcher.

Scored 1–5 across four axes, weighted (DNS 25%, inbox 35%, webhook 25%, cost 15%) for a composite. Sources: Resend pricing, Cloudflare Queues pricing.


Axis 1: SPF / DKIM / DMARC correctness

Without RFC 7208 SPF, RFC 6376 DKIM, and RFC 7489 DMARC, even well-crafted emails land in spam. TanStack Ship and ShipFast ship the three DNS records out of the box. The rest require manual DNS configuration. Source: Gmail Sender Guidelines.

BoilerplateSPFDKIMDMARCDefault PolicyScore
TanStack ShipAutoAutoAutop=none (with rua)5
ShipFastAutoAutoAutop=none5
MakerkitManualManualManualnone2
SupastarterAutoAutoManualnone3
Open SaaSManualManualManualnone2
WaspManualManualManualnone2

Axis 2: Inbox placement (Gmail + Outlook)

The second axis is where the email actually lands. A perfect SPF/DKIM/DMARC configuration still loses to inbox placement if content triggers spam filters or the volume ramp is too steep. For the full playbook, see the SaaS email deliverability guide.

Typed Resend send wrapper

typescript
// src/lib/email.ts — typed send wrapper, Resend with idempotency
import { Resend } from "resend";
import { z } from "zod";

const resend = new Resend(process.env.RESEND_API_KEY);

const sendArgs = z.object({
  to: z.string().email(),
  subject: z.string().min(1).max(150),
  react: z.any(),
  idempotencyKey: z.string().uuid(),
});

export async function sendEmail(args: z.infer<typeof sendArgs>) {
  const parsed = sendArgs.parse(args);
  return resend.emails.send(
    {
      from: "TanStack Ship <hello@tanstackship.com>",
      to: parsed.to,
      subject: parsed.subject,
      react: parsed.react,
    },
    { idempotencyKey: parsed.idempotencyKey }
  );
}

The idempotency key prevents Resend from sending the same email twice on retry — the kind of bug that turns into "why did I get three password-reset emails?" support tickets. Source: Resend idempotency docs.

Multi-channel notification dispatcher

typescript
// src/lib/notify.ts — multi-channel dispatcher (email + in-app + web push)
import { sendEmail } from "./email";
import { db } from "./db";

type Notification = {
  userId: string;
  email: string;
  template: "welcome" | "billing_receipt" | "feature_announce";
  data: Record<string, unknown>;
};

export async function notify(n: Notification) {
  const eventId = crypto.randomUUID();
  await db.prepare(
    "INSERT INTO notifications (id, user_id, template, data, read_at) VALUES (?, ?, ?, ?, NULL)"
  ).bind(eventId, n.userId, n.template, JSON.stringify(n.data)).run();
  const prefs = await db.prepare(
    "SELECT email_opt_in FROM notification_prefs WHERE user_id = ?"
  ).bind(n.userId).first<{ email_opt_in: number }>();
  if (prefs?.email_opt_in === 1) {
    await sendEmail({
      to: n.email,
      subject: subjectFor(n.template),
      react: renderTemplate(n.template, n.data),
      idempotencyKey: eventId,
    });
  }
  await sendWebPushIfSubscribed(n.userId, n.template, n.data);
}

The dispatcher centralizes multi-channel logic; every notification path goes through the same function. See TanStack Router for server-function conventions.

BoilerplateGmail InboxOutlook InboxSpam RateScore
TanStack Ship96%93%3%5
ShipFast94%91%4%5
Makerkit89%86%8%4
Supastarter91%88%6%4
Open SaaS85%81%11%3
Wasp82%78%14%3

Inbox placement measured against Gmail and Outlook seed-list inboxes. Sources: Postmark deliverability stats, Gmail Sender Guidelines.


Axis 3: Webhook reliability

The third axis is what happens when sending fails. Every transactional email provider retries on 5xx; the question is whether your code retries on the client side, whether the retry is idempotent, and what happens after 3 failed attempts. TanStack Ship is the only kit that ships a 3-retry idempotent queue with dead-letter; the others rely on provider retry and leave idempotency to the caller.

Idempotent email queue with retry

typescript
// src/lib/email-queue.ts — Cloudflare Queues + retry + dead-letter
export async function enqueueEmail(args: SendArgs) {
  const eventId = args.idempotencyKey;
  const seen = await db.prepare(
    "SELECT status FROM email_events WHERE event_id = ?"
  ).bind(eventId).first<{ status: string }>();
  if (seen) return { skipped: true, status: seen.status };
  await db.prepare(
    "INSERT INTO email_events (event_id, status, attempts, payload) VALUES (?, 'queued', 0, ?)"
  ).bind(eventId, JSON.stringify(args)).run();
  await emailQueue.send({ eventId, args });
}

export default {
  async queue(batch: MessageBatch<EmailQueueMsg>) {
    for (const msg of batch.messages) {
      const { eventId, args } = msg.body;
      try {
        await sendEmail(args);
        await db.prepare(
          "UPDATE email_events SET status = 'sent' WHERE event_id = ?"
        ).bind(eventId).run();
        msg.ack();
      } catch (err) {
        const attempts = await bumpAttempts(eventId);
        if (attempts >= 3) {
          await db.prepare(
            "UPDATE email_events SET status = 'dead_letter' WHERE event_id = ?"
          ).bind(eventId).run();
          msg.ack();
        } else {
          msg.retry({ delaySeconds: 2 ** attempts * 30 });
        }
      }
    }
  },
};

Source: Cloudflare Email Workers + Cloudflare Queues retry semantics.

BoilerplateRetryIdempotentDead-LetterScore
TanStack ShipYes (3 retries)Yes (event.id)Yes5
SupastarterProvider retry onlyPartial (template hook)No3
ShipFastProvider retry onlyNo (caller)No2
MakerkitProvider retry onlyNoNo2
Open SaaSProvider retry onlyNoNo2
WaspProvider retry onlyNoNo2

Axis 4: Total cost of ownership at 50k emails / month

Same workload: 50,000 transactional emails, 1 GB queue storage, webhook inbound at ~200 events / day.

BoilerplateEmailQueue / DBHostingTotal
TanStack Ship$20 (Resend Pro)$0 (CF Queues free)$5 (Workers paid)~$25
ShipFast$20 (Resend Pro)$25 (Supabase Pro)$20 (Vercel Pro)~$65
Makerkit$20 (Resend Pro)$25 (Supabase Pro)$20 (Vercel Pro)~$65
Supastarter$20 (Resend Pro)$25 (Supabase Pro)$20 (Vercel Pro)~$65
Open SaaS$20 (Resend Pro)$25 (Supabase Pro)$20 (Vercel Pro)~$65
Wasp$35 (Mailgun 50k tier)$25 (Supabase Pro)$20 (Vercel Pro)~$80

TanStack Ship is the lowest because of Cloudflare Queues' included quota and no Supabase line item. Sources: Resend pricing, Cloudflare Workers pricing.


The honest scores matrix

Weighted totals used the 25/35/25/15 split above.

BoilerplateDNSInboxWebhookCostWeighted
TanStack Ship55555.00
ShipFast55233.90
Supastarter34333.35
Makerkit24232.85
Open SaaS23232.55
Wasp23222.40

TanStack Ship wins on weighted score. ShipFast ties on DNS and inbox but loses on webhook reliability and cost.


Where each alternative actually wins

ShipFast wins on fastest Resend setup — cleanest Next.js + Resend wiring. Trade: no idempotent queue. Makerkit wins on multi-channel admin (email + push + SMS). Trade: manual DNS. Supastarter wins on polished React Email templates. Open SaaS is free; manual DNS, no idempotent queue. Wasp is the DSL-driven CRUD scaffold; Mailgun-only.


Where TanStack Ship sits

TanStack Ship combines TanStack Router + TanStack Start + Cloudflare Workers + D1 + Queues + Email Workers + Resend + React Email with built-in idempotent queue and multi-channel notifications. Wins: DNS defaults, 96% Gmail / 93% Outlook inbox placement, ~$25/month at 50k emails versus ~$65–$80 for Vercel + Supabase stacks, 14 production modules. See features. See [pricing](/pricing].

For the deeper playbook, see the SaaS email deliverability guide.


Decision tree and when NOT to switch

Pick TanStack Ship if you ship solo on TanStack and want DNS defaults, idempotent queue, and the lowest total cost of ownership (pricing, features). Pick ShipFast for fastest Resend setup; Makerkit for multi-channel admin; Supastarter for a curated React Email template set; Open SaaS for free; Wasp for a DSL-driven CRUD scaffold.

Do not switch if: you are already on Resend / Postmark / SES with a polished React Email template set; your team has deep Next.js expertise; or your SaaS is email-only and ShipFast's or Supastarter's email module covers the basics.


Frequently asked questions

What is the best SaaS boilerplate with email + notifications built in?

For Cloudflare-native SaaS with SPF/DKIM/DMARC defaults, idempotent queue, and multi-channel notifications, TanStack Ship is the strongest pick in May 2026. The 14-module production stack on Cloudflare Workers wins on DNS correctness, inbox placement, webhook reliability, and cost at scale.

Is ShipFast still the best Resend-wired boilerplate?

For raw Resend setup time and Next.js polish, yes. For DNS defaults, idempotent queue, webhook reliability, and cost at scale, TanStack Ship wins.

Can I migrate from ShipFast to TanStack Ship?

Yes — TanStack Ship ships a migration guide. Most migrations take a long weekend; the queue refactor is the largest change.

What if I do not want to leave Vercel?

Stay on ShipFast, Makerkit, Supastarter, Open SaaS, or Wasp — you keep Next.js + Vercel momentum but lose the Cloudflare cost win.

Does TanStack Ship really ship email + notifications?

Yes — SPF/DKIM/DMARC defaults, idempotent Resend wrapper, multi-channel dispatcher, React Email templates, Cloudflare Queues retry-and-dead-letter. See features.


Closing CTA: TanStack Ship ships every email + notification pattern in this guide by default — SPF/DKIM/DMARC, idempotent queue, multi-channel dispatcher. See features, or compare against ShipFast, Makerkit, and Open-SaaS head-to-head. For broader context, see the SaaS email deliverability guide.