> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sendpost.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Next.js Quickstart

> Learn how to send emails with SendPost in your Next.js application using API routes, Server Actions, and React components

## Prerequisites

To get the most out of this guide, you'll need to:

* [**Create a SendPost Account**](https://app.sendpost.io/register)
* [**Next.js 13+**](https://nextjs.org/docs) with App Router or Pages Router
* A **Sub-Account API Key** from your SendPost dashboard

<Info>
  You can find your API keys in your [SendPost Dashboard](https://app.sendpost.io). Make sure to use your Sub-Account API Key for sending emails.
</Info>

## 1. Install Dependencies

```shellscript npm theme={null}
npm install sendpost-js-sdk
```

## 2. Environment Setup

Create or update your `.env.local` file:

```env theme={null}
SENDPOST_API_KEY=your_sub_account_api_key
SENDPOST_FROM_EMAIL=hello@playwithsendpost.io
SENDPOST_FROM_NAME=SendPost
```

## 3. Send Your First Email

### Using API Routes (App Router)

Create `app/api/send-email/route.ts`:

```typescript TypeScript theme={null}
import { NextRequest, NextResponse } from 'next/server';
import sendpost from 'sendpost-js-sdk';

const emailApi = new sendpost.EmailApi();

export async function POST(request: NextRequest) {
  try {
    const { to, subject, htmlBody, textBody } = await request.json();
    
    const emailMessage = new sendpost.EmailMessage();
    emailMessage.from = { 
      email: process.env.SENDPOST_FROM_EMAIL!,
      name: process.env.SENDPOST_FROM_NAME 
    };
    emailMessage.to = [{ email: to }];
    emailMessage.subject = subject;
    emailMessage.htmlBody = htmlBody;
    emailMessage.textBody = textBody;
    emailMessage.trackOpens = true;
    emailMessage.trackClicks = true;

    const opts = {
      emailMessage: emailMessage,
    };

    const response = await emailApi.sendEmail(
      process.env.SENDPOST_API_KEY!,
      opts
    );

    return NextResponse.json({ 
      success: true, 
      messageId: response.messageId 
    });
  } catch (error: any) {
    console.error('SendPost error:', error);
    return NextResponse.json(
      { success: false, error: error.message },
      { status: 500 }
    );
  }
}
```

### Using Server Actions (App Router)

Create `app/actions/sendEmail.ts`:

```typescript TypeScript theme={null}
'use server';

import sendpost from 'sendpost-js-sdk';

const emailApi = new sendpost.EmailApi();

export async function sendEmail({
  to,
  subject,
  htmlBody,
  textBody,
}: {
  to: string;
  subject: string;
  htmlBody: string;
  textBody?: string;
}) {
  try {
    const emailMessage = new sendpost.EmailMessage();
    emailMessage.from = {
      email: process.env.SENDPOST_FROM_EMAIL!,
      name: process.env.SENDPOST_FROM_NAME,
    };
    emailMessage.to = [{ email: to }];
    emailMessage.subject = subject;
    emailMessage.htmlBody = htmlBody;
    emailMessage.textBody = textBody || htmlBody.replace(/<[^>]*>/g, '');
    emailMessage.trackOpens = true;
    emailMessage.trackClicks = true;

    const response = await emailApi.sendEmail(
      process.env.SENDPOST_API_KEY!,
      { emailMessage }
    );

    return { success: true, messageId: response.messageId };
  } catch (error: any) {
    console.error('SendPost error:', error);
    return { success: false, error: error.message };
  }
}
```

## 4. Common Use Cases

### Welcome Email

Create `app/actions/welcomeEmail.ts`:

```typescript TypeScript theme={null}
'use server';

import sendpost from 'sendpost-js-sdk';

const emailApi = new sendpost.EmailApi();

export async function sendWelcomeEmail({
  email,
  firstName,
}: {
  email: string;
  firstName: string;
}) {
  const emailMessage = new sendpost.EmailMessage();
  emailMessage.from = {
    email: process.env.SENDPOST_FROM_EMAIL!,
    name: process.env.SENDPOST_FROM_NAME,
  };
  emailMessage.to = [
    {
      email,
      name: firstName,
      customFields: {
        firstName,
      },
    },
  ];
  emailMessage.subject = 'Welcome to {{firstName}}!';
  emailMessage.htmlBody = `
    <h1>Welcome, {{firstName}}!</h1>
    <p>Thank you for joining us. We're excited to have you on board.</p>
    <p>Get started by exploring our features:</p>
    <ul>
      <li>Feature 1</li>
      <li>Feature 2</li>
      <li>Feature 3</li>
    </ul>
    <p>If you have any questions, just reply to this email.</p>
    <p><a href="{{unsubscribe}}">Unsubscribe</a></p>
  `;
  emailMessage.textBody = `
    Welcome, {{firstName}}!
    
    Thank you for joining us. We're excited to have you on board.
    
    Get started by exploring our features:
    - Feature 1
    - Feature 2
    - Feature 3
    
    If you have any questions, just reply to this email.
    
    Unsubscribe: {{unsubscribe}}
  `;
  emailMessage.trackOpens = true;
  emailMessage.trackClicks = true;
  emailMessage.groups = ['welcome'];

  try {
    const response = await emailApi.sendEmail(
      process.env.SENDPOST_API_KEY!,
      { emailMessage }
    );
    return { success: true, messageId: response.messageId };
  } catch (error: any) {
    return { success: false, error: error.message };
  }
}
```

### Password Reset Email

Create `app/actions/passwordReset.ts`:

```typescript TypeScript theme={null}
'use server';

import sendpost from 'sendpost-js-sdk';

const emailApi = new sendpost.EmailApi();

export async function sendPasswordResetEmail({
  email,
  resetToken,
  firstName,
}: {
  email: string;
  resetToken: string;
  firstName: string;
}) {
  const resetUrl = `${process.env.NEXT_PUBLIC_APP_URL}/reset-password?token=${resetToken}`;

  const emailMessage = new sendpost.EmailMessage();
  emailMessage.from = {
    email: process.env.SENDPOST_FROM_EMAIL!,
    name: process.env.SENDPOST_FROM_NAME,
  };
  emailMessage.to = [
    {
      email,
      name: firstName,
      customFields: {
        firstName,
        resetUrl,
      },
    },
  ];
  emailMessage.subject = 'Reset Your Password';
  emailMessage.htmlBody = `
    <h2>Hello {{firstName}},</h2>
    <p>We received a request to reset your password. Click the button below to create a new password:</p>
    <p>
      <a href="{{resetUrl}}" style="background-color: #5750EC; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px; display: inline-block;">
        Reset Password
      </a>
    </p>
    <p>Or copy and paste this link into your browser:</p>
    <p>{{resetUrl}}</p>
    <p>This link will expire in 1 hour.</p>
    <p>If you didn't request this, please ignore this email.</p>
  `;
  emailMessage.textBody = `
    Hello {{firstName}},
    
    We received a request to reset your password. Click the link below to create a new password:
    
    {{resetUrl}}
    
    This link will expire in 1 hour.
    
    If you didn't request this, please ignore this email.
  `;
  emailMessage.trackClicks = true;
  emailMessage.groups = ['password-reset'];

  try {
    const response = await emailApi.sendEmail(
      process.env.SENDPOST_API_KEY!,
      { emailMessage }
    );
    return { success: true, messageId: response.messageId };
  } catch (error: any) {
    return { success: false, error: error.message };
  }
}
```

### Order Confirmation Email

Create `app/actions/orderConfirmation.ts`:

```typescript TypeScript theme={null}
'use server';

import sendpost from 'sendpost-js-sdk';

const emailApi = new sendpost.EmailApi();

interface OrderItem {
  name: string;
  price: number;
  quantity: number;
}

export async function sendOrderConfirmation({
  email,
  firstName,
  orderId,
  items,
  total,
}: {
  email: string;
  firstName: string;
  orderId: string;
  items: OrderItem[];
  total: number;
}) {
  const emailMessage = new sendpost.EmailMessage();
  emailMessage.from = {
    email: process.env.SENDPOST_FROM_EMAIL!,
    name: process.env.SENDPOST_FROM_NAME,
  };
  emailMessage.to = [
    {
      email,
      name: firstName,
      customFields: {
        firstName,
        orderId,
        items,
        total: total.toFixed(2),
      },
    },
  ];
  emailMessage.subject = 'Order {{orderId}} Confirmed';
  emailMessage.htmlBody = `
    <h1>Thank you for your order, {{firstName}}!</h1>
    <p>Your order <strong>{{orderId}}</strong> has been confirmed.</p>
    
    <h2>Order Details</h2>
    <table style="width: 100%; border-collapse: collapse;">
      <thead>
        <tr style="background-color: #f5f5f5;">
          <th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Item</th>
          <th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Quantity</th>
          <th style="padding: 12px; text-align: right; border: 1px solid #ddd;">Price</th>
        </tr>
      </thead>
      <tbody>
        {{#each items}}
        <tr>
          <td style="padding: 12px; border: 1px solid #ddd;">{{name}}</td>
          <td style="padding: 12px; border: 1px solid #ddd;">{{quantity}}</td>
          <td style="padding: 12px; text-align: right; border: 1px solid #ddd;">${{price}}</td>
        </tr>
        {{/each}}
      </tbody>
      <tfoot>
        <tr>
          <td colspan="2" style="padding: 12px; text-align: right; border: 1px solid #ddd;"><strong>Total:</strong></td>
          <td style="padding: 12px; text-align: right; border: 1px solid #ddd;"><strong>${{total}}</strong></td>
        </tr>
      </tfoot>
    </table>
    
    <p>We'll send you a shipping confirmation once your order is on its way.</p>
    <p><a href="{{unsubscribe}}">Unsubscribe from order updates</a></p>
  `;
  emailMessage.trackOpens = true;
  emailMessage.trackClicks = true;
  emailMessage.groups = ['order-confirmation'];

  try {
    const response = await emailApi.sendEmail(
      process.env.SENDPOST_API_KEY!,
      { emailMessage }
    );
    return { success: true, messageId: response.messageId };
  } catch (error: any) {
    return { success: false, error: error.message };
  }
}
```

## 5. Using in React Components

### Contact Form Example

Create `app/components/ContactForm.tsx`:

```typescript TypeScript theme={null}
'use client';

import { useState } from 'react';
import { sendEmail } from '@/app/actions/sendEmail';

export default function ContactForm() {
  const [status, setStatus] = useState<'idle' | 'sending' | 'success' | 'error'>('idle');
  const [message, setMessage] = useState('');

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    setStatus('sending');
    setMessage('');

    const formData = new FormData(e.currentTarget);
    const result = await sendEmail({
      to: formData.get('email') as string,
      subject: `Contact from ${formData.get('name')}`,
      htmlBody: `
        <h2>New Contact Form Submission</h2>
        <p><strong>Name:</strong> ${formData.get('name')}</p>
        <p><strong>Email:</strong> ${formData.get('email')}</p>
        <p><strong>Message:</strong></p>
        <p>${formData.get('message')}</p>
      `,
    });

    if (result.success) {
      setStatus('success');
      setMessage('Email sent successfully!');
      e.currentTarget.reset();
    } else {
      setStatus('error');
      setMessage(result.error || 'Failed to send email');
    }
  }

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <div>
        <label htmlFor="name">Name</label>
        <input
          type="text"
          id="name"
          name="name"
          required
          className="w-full px-4 py-2 border rounded"
        />
      </div>
      <div>
        <label htmlFor="email">Email</label>
        <input
          type="email"
          id="email"
          name="email"
          required
          className="w-full px-4 py-2 border rounded"
        />
      </div>
      <div>
        <label htmlFor="message">Message</label>
        <textarea
          id="message"
          name="message"
          required
          rows={5}
          className="w-full px-4 py-2 border rounded"
        />
      </div>
      <button
        type="submit"
        disabled={status === 'sending'}
        className="px-6 py-2 bg-[#5750EC] text-white rounded disabled:opacity-50"
      >
        {status === 'sending' ? 'Sending...' : 'Send Message'}
      </button>
      {message && (
        <p className={status === 'success' ? 'text-green-600' : 'text-red-600'}>
          {message}
        </p>
      )}
    </form>
  );
}
```

## 6. Error Handling & Best Practices

### Create a Reusable Email Service

Create `lib/sendpost.ts`:

```typescript TypeScript theme={null}
import sendpost from 'sendpost-js-sdk';

const emailApi = new sendpost.EmailApi();

interface SendEmailOptions {
  to: string | Array<{ email: string; name?: string; customFields?: Record<string, any> }>;
  subject: string;
  htmlBody: string;
  textBody?: string;
  from?: { email: string; name?: string };
  groups?: string[];
  trackOpens?: boolean;
  trackClicks?: boolean;
}

export async function sendEmailWithSendPost(options: SendEmailOptions) {
  try {
    const emailMessage = new sendpost.EmailMessage();
    
    emailMessage.from = options.from || {
      email: process.env.SENDPOST_FROM_EMAIL!,
      name: process.env.SENDPOST_FROM_NAME,
    };

    // Handle single email or array of recipients
    emailMessage.to = Array.isArray(options.to)
      ? options.to
      : [{ email: options.to }];

    emailMessage.subject = options.subject;
    emailMessage.htmlBody = options.htmlBody;
    emailMessage.textBody = options.textBody || options.htmlBody.replace(/<[^>]*>/g, '');
    emailMessage.trackOpens = options.trackOpens ?? true;
    emailMessage.trackClicks = options.trackClicks ?? true;
    
    if (options.groups) {
      emailMessage.groups = options.groups;
    }

    const response = await emailApi.sendEmail(
      process.env.SENDPOST_API_KEY!,
      { emailMessage }
    );

    return {
      success: true,
      messageId: response.messageId,
      data: response,
    };
  } catch (error: any) {
    console.error('SendPost error:', error);
    return {
      success: false,
      error: error.message || 'Failed to send email',
      details: error,
    };
  }
}
```

<Warning>
  Make sure your sender email domain is verified in your SendPost account before sending emails.
</Warning>

## 7. Next Steps

Explore more examples and use cases:

<Columns cols={3}>
  <Card title="Next.js Documentation" icon="nextjs" href="https://nextjs.org/docs">
    Learn more about Next.js App Router and Server Actions
  </Card>

  <Card title="SendPost JavaScript SDK" icon="npm" href="https://www.npmjs.com/package/sendpost-js-sdk">
    View the official SDK package on npm
  </Card>

  <Card title="Quickstart Example" icon="github" href="https://github.com/sendpost/sendpost-nextjs-example">
    Complete working example from this quickstart guide
  </Card>
</Columns>
