1. Shared Utility (`lib/resend.ts`)
```typescript
import { Resend } from "resend";
export const resend = new Resend(process.env.RESEND_API_KEY);
const SEGMENT_NEWSLETTER = process.env.RESEND_SEGMENT_NEWSLETTER;
const SEGMENT_LEADS = process.env.RESEND_SEGMENT_LEADS;
const TOPIC_NEWSLETTER = process.env.RESEND_TOPIC_NEWSLETTER;
type ContactSource = "newsletter" | "booking" | "contact";
interface CreateContactOptions {
email: string;
firstName?: string;
lastName?: string;
company?: string;
source: ContactSource;
subscribeToNewsletter?: boolean;
}
export async function createContact({
email,
firstName,
lastName,
company,
source,
subscribeToNewsletter = false,
}: CreateContactOptions) {
const segments: { id: string }[] = [];
if (source === "newsletter" && SEGMENT_NEWSLETTER) {
segments.push({ id: SEGMENT_NEWSLETTER });
} else if ((source === "booking" || source === "contact") && SEGMENT_LEADS) {
segments.push({ id: SEGMENT_LEADS });
}
const topics: { id: string; subscription: "opt_in" | "opt_out" }[] = [];
if (subscribeToNewsletter && TOPIC_NEWSLETTER) {
topics.push({ id: TOPIC_NEWSLETTER, subscription: "opt_in" });
}
const properties: Record = {
domain: "YOUR_DOMAIN.com", // Replace with actual domain
source,
};
if (company) properties.company = company;
const { data, error } = await resend.contacts.create({
email,
firstName: firstName || undefined,
lastName: lastName || undefined,
unsubscribed: false,
...(Object.keys(properties).length > 0 && { properties }),
...(segments.length > 0 && { segments }),
...(topics.length > 0 && { topics }),
});
if (error?.message?.includes("already exists")) {
return { exists: true, error: null };
}
return { data, exists: false, error };
}
export async function contactExists(email: string): Promise {
try {
const { data } = await resend.contacts.get({ email });
return !!data;
} catch {
return false;
}
}
```
2. Newsletter Route (`/api/newsletter`)
```typescript
import { NextResponse } from "next/server";
import { resend, createContact, contactExists } from "@/lib/resend";
export async function POST(request: Request) {
const { email } = await request.json();
if (!email) {
return NextResponse.json({ error: "Email is required" }, { status: 400 });
}
// Duplicate check
if (await contactExists(email)) {
return NextResponse.json(
{ error: "already_subscribed", message: "You're already subscribed!" },
{ status: 409 },
);
}
const { error } = await createContact({
email,
source: "newsletter",
subscribeToNewsletter: true,
});
if (error) {
// Return actual error, not generic 500
const message = typeof error === "object" && "message" in error
? (error as { message: string }).message
: "Failed to subscribe";
const statusCode = typeof error === "object" && "statusCode" in error
? (error as { statusCode: number }).statusCode
: 500;
return NextResponse.json({ error: message }, { status: statusCode });
}
// Send welcome email
await resend.emails.send({
from: "Company ",
to: [email],
subject: "Welcome to our Newsletter",
html: Thanks for subscribing!
...,
});
return NextResponse.json({ success: true });
}
```
3. Frontend Duplicate Handling
```typescript
const response = await fetch("/api/newsletter", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email }),
});
const data = await response.json();
if (response.status === 409) {
toast.info("You're already subscribed!");
return;
}
if (!response.ok) {
throw new Error(data.error);
}
toast.success("Thanks for subscribing!");
```
4. Booking/Contact Form (Create Lead)
Add contact creation without blocking the main flow:
```typescript
// In booking or contact form API route
createContact({
email,
firstName,
lastName,
company,
source: "booking", // or "contact"
}).catch((err) => console.error("Failed to create contact:", err));
```
5. Inbound Email Forwarding
For receiving emails via subdomain (e.g., mail.example.com):
Webhook handler (/api/webhooks/resend):
```typescript
case "email.received":
const forwardTo = process.env.EMAIL_FORWARD_TO?.split(",").map(e => e.trim());
if (!forwardTo?.length) return;
await resend.emails.send({
from: "Forwarded ",
to: forwardTo,
replyTo: event.data.from,
subject: [Fwd] ${event.data.subject},
html: `
From: ${event.data.from}
To: ${event.data.to?.join(", ")}
${event.data.html || event.data.text}
`,
attachments: event.data.attachments,
});
break;
```