Sending transactional emails in Next.js should be incredibly simple. But if you are building an app for the European market, you quickly run into a wall: strict GDPR requirements, US-hosted servers, and sometimes overly complex APIs.
In this quick tutorial, I will show you how to send emails in a Next.js App Router project using Hisend (@hisend/sdk) β an EU-hosted email API designed specifically for developers who want a clean Developer Experience (DX) and native data compliance.
Letβs dive in.
Prerequisites
- A Next.js project (App Router)
- Node.js installed
Step 1: Set up your Hisend Account & Domain
Before we write any code, we need to make sure your emails actually reach the inbox and don't end up in spam.
- Sign up: Go to hisend.app and create a free account.
- Create a Project: Set up your first workspace/project.
-
Add your Domain: Enter the domain you want to send emails from (e.g.,
yourdomain.com). - Configure DNS: Hisend will generate specific DNS records (SPF, DKIM, and DMARC). Copy these and add them to your domain provider (like Cloudflare, Vercel, or Hetzner). This verifies your domain.
- Generate an API Key: Once your domain is verified, go to your project settings, create a new API Key, and copy it. You will need it in the next step.
Step 2: Install the Hisend SDK
Now, let's add the Hisend SDK to our Next.js project. Open your terminal and run:
npm install @hisend/sdk
# or yarn add @hisend/sdk
# or pnpm add @hisend/sdk
# or bun add @hisend/sdk
Next, add the API key you just generated to your .env.local file at the root of your project:
HISEND_API_KEY=your_api_key_here
Step 3: Create a Next.js Route Handler
In the Next.js App Router, the safest place to handle third-party API calls without exposing your secrets to the client is a Route Handler.
Create a new file under app/api/send/route.ts (or .js if you are not using TypeScript):
import { NextResponse } from 'next/server';
import { Hisend } from '@hisend/sdk';
// Initialize the SDK with your API Key
const hisend = new Hisend(process.env.HISEND_API_KEY);
export async function POST(request: Request) {
try {
const { email, name } = await request.json();
const data = await hisend.emails.send({
from: 'Acme Team <hello@yourdomain.com>', // Make sure this matches your verified domain!
to: [email],
subject: `Welcome to the app, ${name}!`,
html: `
<div>
<h1>Hi ${name},</h1>
<p>Thanks for signing up. We are thrilled to have you on board.</p>
<br />
<p>Cheers,<br>The Acme Team</p>
</div>
`,
});
return NextResponse.json({ success: true, data });
} catch (error) {
return NextResponse.json(
{ success: false, error: 'Failed to send email' },
{ status: 500 }
);
}
}
Step 4: Trigger the Email from your Frontend
Now, you can easily call this API route from any client-side component (like a signup form or a button click):
'use client';
export default function SignupButton() {
const sendWelcomeEmail = async () => {
await fetch('/api/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'user@example.com',
name: 'Alex',
}),
});
alert('Email sent successfully!');
};
return (
<button
onClick={sendWelcomeEmail}
className="bg-blue-600 text-white px-4 py-2 rounded-md"
>
Send Welcome Email
</button>
);
}
Why use Hisend instead of the usual suspects?
If you've used other email APIs, this syntax probably looks familiar. But here is why I actually built Hisend:
- GDPR Out-of-the-box: Hisend is hosted on bare metal at Hetzner (Nuremberg) and AWS (Frankfurt). Your data and logs never leave the EU.
- Receiving Emails doesn't suck: With Hisend, you don't have to chain three different API requests just to get the body, the sender name, and the attachments. You get everything in one single fetch.
- Native Threading: We support managing email conversations right from the API.
- Auto-Forwarding: Built right in, no weird workarounds needed.
You can check out the full documentation and start sending at hisend.app.
Happy coding! π
Top comments (0)