MyApp

Getting Started

IntroductionInstallationPull Updates
Architecture

Setup

IDEAI AgentsMCP ServersEnvironment Variables

Workflow

Git WorkflowBuild & DeployTroubleshooting

Authentication

OverviewSetup & ConfigurationUsage & IntegrationTroubleshooting

Payments

OverviewSetup & ConfigurationUsage & IntegrationTroubleshooting

Supabase

OverviewSetup & ConfigurationTroubleshooting

Database

Database SetupPrisma ORMUsage & IntegrationMigrationsTroubleshooting

Storage

OverviewSetup & ConfigurationUsage & IntegrationTroubleshooting

Emails

OverviewSetup and ConfigurationUsage and IntegrationTroubleshooting

SEO

OverviewConfiguration & Best PracticesCustomization & Optimization

UI

OverviewSetup and ConfigurationThemingTroubleshooting
MyApp

Usage and Integration

Send transactional emails with Resend and manage newsletter subscriptions with Mailchimp

Learn how to send transactional emails using Resend and manage newsletter subscriptions with Mailchimp.

Sending Transactional Emails

Basic Email

Send a simple transactional email:

lib/email/sendWelcomeEmail.ts
import { resend } from '@/lib/resend/resend';

export async function sendWelcomeEmail(to: string, name: string) {
  const { data, error } = await resend.emails.send({
    from: 'MyApp <hello@myapp.com>',
    to,
    subject: 'Welcome to MyApp!',
    html: `<p>Hello ${name},</p><p>Thank you for joining!</p>`,
  });

  if (error) throw new Error(error.message);
  return data;
}

React Email Templates

Create reusable email templates with React:

emails/WelcomeEmail.tsx
export interface IWelcomeEmailProps {
  name: string;
}

export default function WelcomeEmail({ name }: IWelcomeEmailProps) {
  return (
    <div>
      <h1>Welcome, {name}!</h1>
      <p>Thank you for joining MyApp.</p>
      <style jsx>{`
        div {
          font-family: Arial, sans-serif;
        }
        h1 {
          color: #333;
        }
      `}</style>
    </div>
  );
}

Use the template:

lib/email/sendWelcomeEmail.ts
import { resend } from '@/lib/resend/resend';
import WelcomeEmail from '@/emails/WelcomeEmail';

export async function sendWelcomeEmail(to: string, name: string) {
  const { data, error } = await resend.emails.send({
    from: 'MyApp <hello@myapp.com>',
    to,
    subject: 'Welcome to MyApp!',
    react: <WelcomeEmail name={name} />,
  });

  if (error) throw new Error(error.message);
  return data;
}

Using in API Routes

Call email functions from API routes:

app/api/auth/welcome/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { sendWelcomeEmail } from '@/lib/email/sendWelcomeEmail';

export async function POST(req: NextRequest) {
  try {
    const { email, name } = await req.json();
    
    await sendWelcomeEmail(email, name);
    
    return NextResponse.json({ success: true });
  } catch (error) {
    return NextResponse.json(
      { error: 'Failed to send email' },
      { status: 500 }
    );
  }
}

Newsletter Management

Subscribe Users

Use the provided addContact function to subscribe users:

lib/email/addContact.ts
import { env } from '@/env';

export async function addContact(email: string) {
  try {
    const res = await fetch(
      `${env.NEXT_PUBLIC_SITE_URL}/api/resend/newsletter`,
      {
        method: 'POST',
        next: { tags: ['resend/newsletter'] },
        body: JSON.stringify({ email }),
      }
    );

    const json = await res.json();

    if (!json.ok) {
      throw new Error(json?.message);
    }

    return res;
  } catch (error: any) {
    return error;
  }
}

Newsletter Form

Create a newsletter subscription form:

components/NewsletterForm.tsx
'use client';

import { useState } from 'react';
import { addContact } from '@/lib/email/addContact';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';

export function NewsletterForm() {
  const [email, setEmail] = useState('');
  const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setStatus('loading');

    try {
      await addContact(email);
      setStatus('success');
      setEmail('');
    } catch (error) {
      setStatus('error');
    }
  }

  return (
    <form onSubmit={handleSubmit} className="flex gap-2">
      <Input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Enter your email"
        required
      />
      <Button type="submit" disabled={status === 'loading'}>
        {status === 'loading' ? 'Subscribing...' : 'Subscribe'}
      </Button>
      {status === 'success' && <p className="text-green-600">Subscribed!</p>}
      {status === 'error' && <p className="text-red-600">Failed to subscribe</p>}
    </form>
  );
}

API Route Implementation

The newsletter API route handles Mailchimp integration:

app/api/resend/newsletter/route.ts
import { env } from '@/env';
import { NextRequest, NextResponse } from 'next/server';
import { newsletterSchema } from '@/validationSchemas/newsletterSchema';

export async function POST(req: NextRequest) {
  try {
    const body = await req.json();
    const validationResult = newsletterSchema.safeParse(body);

    if (!validationResult.success) {
      return NextResponse.json(
        { message: 'Invalid email address', ok: false },
        { status: 400 }
      );
    }

    const { email } = validationResult.data;

    const customUrl = `https://${env.MAILCHIMP_API_SERVER}.api.mailchimp.com/3.0/lists/${env.MAILCHIMP_AUDIENCE_ID}/members`;

    const response = await fetch(customUrl, {
      method: 'POST',
      headers: {
        Authorization: `Basic ${Buffer.from(`anystring:${env.MAILCHIMP_API_KEY}`).toString('base64')}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        email_address: email,
        status: 'subscribed',
      }),
    });

    if (!response.ok) {
      return NextResponse.json(
        { message: 'Failed to subscribe', ok: false },
        { status: response.status }
      );
    }

    return NextResponse.json(
      { message: 'Successfully subscribed!', ok: true },
      { status: 200 }
    );
  } catch (error) {
    return NextResponse.json(
      { message: 'An error occurred', ok: false },
      { status: 500 }
    );
  }
}

Best Practices

Email Sending

  • Use descriptive "from" names: MyApp <hello@myapp.com>
  • Keep subject lines under 50 characters
  • Test emails before sending to users
  • Handle errors gracefully with try-catch
  • Use React templates for consistent branding

Newsletter Management

  • Validate email addresses before subscribing
  • Implement rate limiting on signup endpoint
  • Provide unsubscribe links in emails
  • Handle duplicate subscriptions gracefully
  • Show clear success/error messages to users

Security

  • Never expose API keys in client-side code
  • Keep .env in .gitignore
  • Validate all email inputs with Zod schemas
  • Use rate limiting to prevent abuse
  • Log errors server-side only

Next Steps

  • Troubleshooting - Common issues and solutions

How is this guide ?

Last updated on

Setup and Configuration

Configure Resend and Mailchimp for transactional emails and newsletter management

Troubleshooting

Common email issues and solutions for Resend and Mailchimp integration

On this page

Sending Transactional Emails
Basic Email
React Email Templates
Using in API Routes
Newsletter Management
Subscribe Users
Newsletter Form
API Route Implementation
Best Practices
Email Sending
Newsletter Management
Security
Next Steps