Comparisons

Resend vs EmailsDone

Resend and EmailsDone are both built for developers, but they solve different problems.

Resend is a modern email API for developers who want a clean way to build and send emails.

EmailsDone is a template-first transactional email API for developers who do not want email to become another project.

That difference matters.

If someone says:

I just use Resend.

That is fair.

Resend is a strong choice if you want a flexible email API and you are happy creating your own templates.

EmailsDone is for the developer who looks at password reset, verification, welcome, login code, notification and billing emails and thinks:

Why am I building all of this again?

The short version

Use Resend if you want:

  • a flexible developer-first email API
  • custom HTML emails
  • React Email-style workflows
  • control over every email
  • your own templates and layouts
  • a blank canvas for product or brand-specific email

Use EmailsDone if you want:

  • common app emails already packaged
  • no HTML templates to build
  • no template system to maintain
  • simple app-event SDK calls
  • Firebase/backend-friendly integration
  • a constrained product that removes email decisions

The simple distinction is:

Resend helps developers send email.
EmailsDone helps developers avoid building the boring emails.

Quick comparison

Area Resend EmailsDone
Core idea Email API for developers App emails for developers who do not want email faff
Best fit Developers who want flexibility and control Developers who want common app emails already done
API style Send an email Send an app event
Templates You build or bring your own Built-in transactional templates
HTML support Strong fit Not the core model
Flexibility High Lower by design
Setup mindset Build your email layer Use the app email layer
Firebase use You wire it into your backend Designed for backend and prompt-first integration
Best phrase Better blank canvas Better shortcut

Neither product is universally better.

They are built around different assumptions.

What Resend is good at

Resend is good when you want a clean developer experience for sending email.

It makes sense if you already know what your email should look like and you want a nice API for sending it.

A Resend-style workflow usually looks like this:

Decide the email
↓
Build the template
↓
Create the HTML or React email
↓
Call the email API
↓
Maintain the template over time

That is a good model if email design and control matter to your app.

For example, if your product has custom onboarding journeys, heavily branded customer emails, bespoke layouts, or a team that wants to own the email design system, a flexible provider makes sense.

Resend is a blank canvas for developers.

That is its strength.

What EmailsDone is good at

EmailsDone starts from a different assumption:

Most app emails are boring and should already exist.

A lot of apps need the same basic transactional emails:

  • welcome
  • verify email
  • password reset
  • login code
  • magic link
  • notification
  • payment failed
  • trial ending
  • invoice
  • export ready

These emails need to be clear, reliable and consistent.

They usually do not need to be unique works of design.

With EmailsDone, the workflow looks more like this:

Choose the app email
↓
Pass the required data
↓
Send it from backend code

For example:

await emailsDone
  .authentication()
  .passwordReset(resetUrl)
  .send("user@example.com");

Or:

await emailsDone
  .authentication()
  .verifyEmail(verificationUrl)
  .send("user@example.com");

Or:

await emailsDone
  .authentication()
  .welcome(actionUrl)
  .send("user@example.com");

The point is not that sending an email is impossible with other tools.

The point is that the email itself is already a product feature.

Blank canvas vs finished app emails

This is the real comparison.

Resend gives you a better blank canvas.

EmailsDone gives you a better shortcut.

With a blank canvas, you get freedom:

  • custom HTML
  • custom layouts
  • custom components
  • custom rendering
  • custom templates
  • custom everything

That is powerful.

But freedom also means decisions.

You need to decide what the password reset email says. You need to decide how the button looks. You need to decide how the email renders on mobile. You need to decide where the template lives. You need to maintain it when your app changes.

EmailsDone removes many of those decisions by being template-first.

That makes it less flexible.

That is deliberate.

The password reset example

Take a password reset email.

With a flexible provider, you usually need to create the email:

await emailProvider.send({
  to: "user@example.com",
  subject: "Reset your password",
  html: `
    <h1>Reset your password</h1>
    <p>Click the button below to choose a new password.</p>
    <a href="${resetUrl}">Reset password</a>
    <p>If you did not request this, you can ignore this email.</p>
  `
});

That works.

But now you own it.

You own the layout, wording, fallback links, mobile rendering, dark mode, text version, button style and future changes.

With EmailsDone, the app expresses the intent:

await emailsDone
  .authentication()
  .passwordReset(resetUrl)
  .send("user@example.com");

Most apps do not need a unique password reset layout.

They need a clear, safe, production-ready password reset email that works.

Template ownership

This is where the products feel most different.

With Resend, you own the template layer.

That can be exactly what you want.

You can design every email, control every component, use your preferred rendering approach, and make the emails match your product exactly.

With EmailsDone, common transactional templates are included.

That means your app does not start from:

What should this email look like?

It starts from:

Which app event do I need to send?

That is a much smaller question.

For developers building side projects, SaaS apps, Firebase apps or agent-generated apps, that smaller question can save a lot of time.

Developer experience

Both products care about developer experience, but in different ways.

Resend improves the experience of sending custom email.

EmailsDone reduces how much custom email you need to create.

A Resend-style integration might feel like:

Create template
Render template
Send email
Maintain template

An EmailsDone-style integration feels like:

Call template
Move on

That is the product difference.

EmailsDone is not trying to be the most flexible email API.

It is trying to be the least annoying way to add the standard emails every app ends up needing.

Firebase and backend apps

If you are building with Firebase, both products should be called from trusted backend code.

You should not put email provider API keys in frontend code.

A safe Firebase shape usually looks like this:

Frontend app
↓
Firebase Function
↓
Email service
↓
Recipient inbox

With Resend, the Firebase Function calls Resend and provides the email content.

With EmailsDone, the Firebase Function calls an app email template.

For example:

import { onCall, HttpsError } from "firebase-functions/v2/https";
import { defineSecret } from "firebase-functions/params";
import { EmailsDone } from "emailsdone";

const emailsDoneApiKey = defineSecret("EMAILSDONE_API_KEY");

export const sendWelcomeEmail = onCall(
  {
    secrets: [emailsDoneApiKey],
    enforceAppCheck: true,
  },
  async (request) => {
    if (!request.auth?.token.email) {
      throw new HttpsError("unauthenticated", "You must be signed in.");
    }

    const emailsDone = EmailsDone.fromApiKey(emailsDoneApiKey.value());

    await emailsDone
      .authentication()
      .welcome("https://app.example.com/get-started")
      .send(request.auth.token.email);

    return { queued: true };
  }
);

The Firebase Function still handles the trusted backend concerns:

  • authentication
  • App Check
  • validation
  • secrets
  • deciding whether the email should be sent

EmailsDone handles the app email template.

Agentic coding and prompt-first setup

A lot of modern apps are now built with Claude Code, Cursor, Codex, Replit and other coding agents.

That changes the email problem slightly.

A flexible email API gives the agent a lot of freedom. The agent can create templates, write HTML, decide wording, choose structure and scatter provider calls through the app if the prompt is not careful.

That can work.

But it can also burn tokens and create messy email code.

EmailsDone is intentionally constrained, which makes it easier to instruct an agent:

Use the built-in password reset template.
Use the built-in welcome template.
Use the built-in verification template.
Create one EmailService helper.
Keep the API key server-side.
Do not write custom HTML emails.

That is the kind of constraint coding agents benefit from.

The agent does not need to invent the email.

It only needs to wire the app event to the correct template.

Why EmailsDone does not start with custom HTML

Many email APIs start with:

subject + html + recipient

That is flexible, but it also pushes the template problem back onto the developer.

EmailsDone starts with app events instead:

authentication.passwordReset
authentication.verifyEmail
authentication.welcome
notifications.notification
billing.paymentFailed

That is less flexible, but it is the whole point.

For common transactional emails, the structure is already known. The app usually needs to supply the important data, not design a unique email from scratch.

This constraint also helps with:

  • faster onboarding
  • fewer templates to maintain
  • less HTML to debug
  • more consistent app emails
  • safer generated implementations
  • less room for spammy or abusive content

If you need complete creative control, use a flexible provider.

If you want the standard app emails already done, use EmailsDone.

When Resend is better

Use Resend if:

  • you want a modern developer email API
  • you need custom HTML emails
  • you want to use React Email or your own templates
  • you have strong brand/design requirements
  • you want full control over the email content
  • you are building an email-heavy product
  • you have the time or team to maintain the email layer

Resend is a strong choice when you want to build the email experience yourself.

When EmailsDone is better

Use EmailsDone if:

  • you want common transactional emails working quickly
  • you do not want to build email templates
  • you are tired of creating the same password reset and welcome emails again
  • you are using Firebase or backend code and want a simple integration
  • you want app-event SDK calls instead of blank HTML sends
  • you want a constrained product that removes decisions
  • email is necessary, but not the product

EmailsDone is a strong choice when you want email to be done.

The honest recommendation

Use Resend if you want a flexible developer-first email platform.

It is a good blank canvas.

Use EmailsDone if you want the boring app emails already packaged.

It is a good shortcut.

The difference is not:

Which API can send an email?

Both can send email.

The difference is:

Who is building the email layer?

With Resend, you build it.

With EmailsDone, the common app emails are already there.

That is the reason EmailsDone exists.