DEV Community

Alex Spinov
Alex Spinov

Posted on

Resend Has a Free Email API — Here's How to Send Beautiful Transactional Emails in TypeScript

SendGrid is bloated. Mailgun is complex. Resend makes sending emails as simple as calling a function.

What is Resend?

Resend is a modern email API built for developers. Send transactional emails with React components as templates. Created by the team behind React Email.

Free Tier

  • 100 emails/day
  • 3,000 emails/month
  • 1 custom domain
  • Full API access

Quick Start

bun add resend
Enter fullscreen mode Exit fullscreen mode
import { Resend } from 'resend';

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

await resend.emails.send({
  from: 'hello@yourdomain.com',
  to: 'user@example.com',
  subject: 'Welcome to MyApp!',
  html: '<h1>Welcome!</h1><p>Thanks for signing up.</p>',
});
Enter fullscreen mode Exit fullscreen mode

React Email Templates

bun add @react-email/components
Enter fullscreen mode Exit fullscreen mode
// emails/welcome.tsx
import { Html, Head, Body, Container, Text, Button, Heading } from '@react-email/components';

export function WelcomeEmail({ name, loginUrl }: { name: string; loginUrl: string }) {
  return (
    <Html>
      <Head />
      <Body style={{ fontFamily: 'Arial, sans-serif', backgroundColor: '#f6f9fc' }}>
        <Container style={{ maxWidth: '560px', margin: '0 auto', padding: '20px' }}>
          <Heading>Welcome, {name}!</Heading>
          <Text>Thanks for joining. Click below to get started:</Text>
          <Button
            href={loginUrl}
            style={{
              backgroundColor: '#5469d4',
              color: '#fff',
              padding: '12px 20px',
              borderRadius: '5px',
              textDecoration: 'none',
            }}
          >
            Go to Dashboard
          </Button>
          <Text style={{ color: '#666', fontSize: '14px' }}>
            If you did not create this account, ignore this email.
          </Text>
        </Container>
      </Body>
    </Html>
  );
}
Enter fullscreen mode Exit fullscreen mode

Send with React Component

import { Resend } from 'resend';
import { WelcomeEmail } from './emails/welcome';

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

await resend.emails.send({
  from: 'MyApp <hello@myapp.com>',
  to: 'alice@example.com',
  subject: 'Welcome to MyApp!',
  react: WelcomeEmail({ name: 'Alice', loginUrl: 'https://myapp.com/login' }),
});
Enter fullscreen mode Exit fullscreen mode

Batch Sending

await resend.batch.send([
  {
    from: 'hello@myapp.com',
    to: 'user1@example.com',
    subject: 'Your weekly digest',
    react: DigestEmail({ userId: '1' }),
  },
  {
    from: 'hello@myapp.com',
    to: 'user2@example.com',
    subject: 'Your weekly digest',
    react: DigestEmail({ userId: '2' }),
  },
]);
Enter fullscreen mode Exit fullscreen mode

Webhooks

// Handle email events
app.post('/webhooks/resend', async (req, res) => {
  const event = req.body;

  switch (event.type) {
    case 'email.delivered':
      console.log('Email delivered to', event.data.to);
      break;
    case 'email.bounced':
      console.log('Email bounced:', event.data.to);
      await markEmailInvalid(event.data.to);
      break;
    case 'email.complained':
      await unsubscribeUser(event.data.to);
      break;
  }

  res.status(200).send('OK');
});
Enter fullscreen mode Exit fullscreen mode

Resend vs SendGrid vs Mailgun

Feature Resend SendGrid Mailgun
DX Excellent Good Good
React Templates Yes No No
Free Tier 3K/mo 100/day 5K/3mo
Setup Time 5 min 30 min 30 min
SDK Size Tiny Large Medium
Webhooks Yes Yes Yes

Need email notifications for scraping results? Check out my Apify actors — get notified when data changes. For custom solutions, email spinov001@gmail.com.

Top comments (0)