> ## 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.

# Nuxt.js Quickstart

> Learn how to send emails with SendPost in your Nuxt.js application using server routes, server utilities, and composables

## Prerequisites

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

* [**Create a SendPost Account**](https://app.sendpost.io/register)
* [**Nuxt.js 3+**](https://nuxt.com/)
* 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` file:

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

## 3. Create Server Utility

Create `server/utils/sendpost.ts`:

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

const emailApi = new sendpost.EmailApi();

export async function sendEmail({
  to,
  subject,
  htmlBody,
  textBody,
  from,
  groups,
  trackOpens = true,
  trackClicks = true,
  customFields,
}: {
  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;
  customFields?: Record<string, any>;
}) {
  try {
    const emailMessage = new sendpost.EmailMessage();
    
    emailMessage.from = from || {
      email: process.env.SENDPOST_FROM_EMAIL || 'hello@playwithsendpost.io',
      name: process.env.SENDPOST_FROM_NAME || 'SendPost',
    };

    // Handle single email or array of recipients
    if (typeof to === 'string') {
      emailMessage.to = [{ email: to }];
    } else {
      emailMessage.to = to.map(recipient => {
        if (typeof recipient === 'string') {
          return { email: recipient };
        }
        return {
          email: recipient.email,
          name: recipient.name,
          customFields: recipient.customFields || customFields,
        };
      });
    }

    emailMessage.subject = subject;
    emailMessage.htmlBody = htmlBody;
    emailMessage.textBody = textBody || htmlBody.replace(/<[^>]*>/g, '');
    emailMessage.trackOpens = trackOpens;
    emailMessage.trackClicks = trackClicks;
    
    if (groups) {
      emailMessage.groups = 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,
    };
  }
}
```

## 4. Send Your First Email

### Using Server API Route

Create `server/api/send-email.post.ts`:

```typescript TypeScript theme={null}
import { sendEmail } from '~/server/utils/sendpost';

export default defineEventHandler(async (event) => {
  try {
    const body = await readBody(event);
    const { to, subject, htmlBody, textBody } = body;

    if (!to || !subject || !htmlBody) {
      throw createError({
        statusCode: 400,
        statusMessage: 'Missing required fields: to, subject, htmlBody',
      });
    }

    const result = await sendEmail({
      to,
      subject,
      htmlBody,
      textBody,
    });

    if (result.success) {
      return {
        success: true,
        messageId: result.messageId,
      };
    } else {
      throw createError({
        statusCode: 500,
        statusMessage: result.error,
      });
    }
  } catch (error: any) {
    throw createError({
      statusCode: error.statusCode || 500,
      statusMessage: error.message || 'Failed to send email',
    });
  }
});
```

### Using Server Action

Create `server/actions/email.ts`:

```typescript TypeScript theme={null}
import { sendEmail } from '~/server/utils/sendpost';

export async function sendWelcomeEmail(email: string, firstName: string) {
  return await sendEmail({
    to: {
      email,
      name: firstName,
      customFields: { firstName },
    },
    subject: 'Welcome {{firstName}}!',
    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>
    `,
    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}}
    `,
    groups: ['welcome'],
  });
}
```

## 5. Common Use Cases

### Welcome Email API Route

Create `server/api/welcome-email.post.ts`:

```typescript TypeScript theme={null}
import { sendEmail } from '~/server/utils/sendpost';

export default defineEventHandler(async (event) => {
  try {
    const { email, firstName } = await readBody(event);

    if (!email || !firstName) {
      throw createError({
        statusCode: 400,
        statusMessage: 'Missing required fields: email, firstName',
      });
    }

    const result = await sendEmail({
      to: {
        email,
        name: firstName,
        customFields: { firstName },
      },
      subject: 'Welcome {{firstName}}!',
      htmlBody: `
        <h1>Welcome, {{firstName}}!</h1>
        <p>Thank you for joining us. We're excited to have you on board.</p>
        <p><a href="{{unsubscribe}}">Unsubscribe</a></p>
      `,
      groups: ['welcome'],
    });

    return {
      success: result.success,
      messageId: result.messageId,
    };
  } catch (error: any) {
    throw createError({
      statusCode: error.statusCode || 500,
      statusMessage: error.message,
    });
  }
});
```

### Password Reset Email

Create `server/api/password-reset.post.ts`:

```typescript TypeScript theme={null}
import { sendEmail } from '~/server/utils/sendpost';

export default defineEventHandler(async (event) => {
  try {
    const { email, resetToken, firstName } = await readBody(event);
    const config = useRuntimeConfig();
    const resetUrl = `${config.public.appUrl}/reset-password?token=${resetToken}`;

    const result = await sendEmail({
      to: {
        email,
        name: firstName || 'User',
        customFields: {
          firstName: firstName || 'User',
          resetUrl,
        },
      },
      subject: 'Reset Your Password',
      htmlBody: `
        <h2>Hello {{firstName}},</h2>
        <p>We received a request to reset your password. Click the button below:</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: {{resetUrl}}</p>
        <p>This link will expire in 1 hour.</p>
      `,
      groups: ['password-reset'],
      trackClicks: true,
    });

    return {
      success: result.success,
      messageId: result.messageId,
    };
  } catch (error: any) {
    throw createError({
      statusCode: error.statusCode || 500,
      statusMessage: error.message,
    });
  }
});
```

## 6. Using in Components

### Client-Side Form

Create `pages/contact.vue`:

```vue Vue theme={null}
<template>
  <form @submit.prevent="handleSubmit">
    <input v-model="form.email" type="email" placeholder="Email" required />
    <input v-model="form.name" type="text" placeholder="Name" required />
    <textarea v-model="form.message" placeholder="Message" required></textarea>
    <button type="submit" :disabled="loading">
      {{ loading ? 'Sending...' : 'Send' }}
    </button>
    <div v-if="message" :class="messageType">
      {{ message }}
    </div>
  </form>
</template>

<script setup lang="ts">
const form = reactive({
  email: '',
  name: '',
  message: '',
});

const loading = ref(false);
const message = ref('');
const messageType = ref('');

async function handleSubmit() {
  loading.value = true;
  message.value = '';

  try {
    const { data } = await $fetch('/api/send-email', {
      method: 'POST',
      body: {
        to: 'contact@yourdomain.com',
        subject: `Contact from ${form.name}`,
        htmlBody: `
          <h2>New Contact Form Submission</h2>
          <p><strong>Name:</strong> ${form.name}</p>
          <p><strong>Email:</strong> ${form.email}</p>
          <p><strong>Message:</strong></p>
          <p>${form.message.replace(/\n/g, '<br>')}</p>
        `,
      },
    });

    if (data.success) {
      message.value = 'Message sent successfully!';
      messageType.value = 'success';
      form.email = '';
      form.name = '';
      form.message = '';
    }
  } catch (error: any) {
    message.value = error.data?.message || 'Failed to send message';
    messageType.value = 'error';
  } finally {
    loading.value = false;
  }
}
</script>
```

## 7. Runtime Config

Add to `nuxt.config.ts`:

```typescript TypeScript theme={null}
export default defineNuxtConfig({
  runtimeConfig: {
    sendpostApiKey: process.env.SENDPOST_API_KEY,
    sendpostFromEmail: process.env.SENDPOST_FROM_EMAIL || 'hello@playwithsendpost.io',
    sendpostFromName: process.env.SENDPOST_FROM_NAME || 'SendPost',
    public: {
      appUrl: process.env.APP_URL || 'https://yourapp.com',
    },
  },
});
```

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

## 8. Next Steps

Explore more examples and use cases:

<Columns cols={3}>
  <Card title="Nuxt.js Documentation" icon="nuxt" href="https://nuxt.com/docs">
    Learn more about Nuxt.js framework
  </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="Personalization Guide" icon="book" href="/api-reference/common-use-cases/personalisation-within-emails">
    Learn how to personalize emails with Handlebars templates
  </Card>
</Columns>
