Why LANGR for Next.js?
Next.js is the most popular React framework, but it doesn't include email functionality. You need an external API. LANGR provides transactional email alongside SMS, auth, and payments — all from the same SDK.
This tutorial shows three patterns: Server Actions, API Routes, and Edge Functions.
Setup
npm install @langr/sdk
Add your API key to .env.local:
LANGR_API_KEY=lk_live_...
Create a shared client:
// lib/langr.ts
import { LangrClient } from "@langr/sdk";export const langr = new LangrClient({
apiKey: process.env.LANGR_API_KEY!,
});
Pattern 1: Server Action
The simplest approach for Next.js App Router:
// app/actions/send-welcome.ts
"use server";import { langr } from "@/lib/langr";
export async function sendWelcomeEmail(email: string, name: string) {
const result = await langr.mail.send({
from: "[email protected]",
to: email,
subject: Welcome, ${name}!,
html:
<h1>Welcome to our platform</h1>
<p>Hi ${name}, your account is ready.</p>
<p><a href="https://example.com/dashboard">Go to Dashboard</a></p>
,
});
return { ok: result.ok, id: result.id };
}
Use it in a client component:
// app/signup/page.tsx
"use client";import { sendWelcomeEmail } from "@/app/actions/send-welcome";
export default function SignupPage() {
async function handleSubmit(formData: FormData) {
const email = formData.get("email") as string;
const name = formData.get("name") as string;
await sendWelcomeEmail(email, name);
}
return (
<form action={handleSubmit}>
<input name="name" placeholder="Name" required />
<input name="email" type="email" placeholder="Email" required />
<button type="submit">Sign Up</button>
</form>
);
}
Pattern 2: API Route
For more control over the response:
// app/api/contact/route.ts
import { langr } from "@/lib/langr";
import { NextResponse } from "next/server";export async function POST(request: Request) {
const { name, email, message } = await request.json();
const result = await langr.mail.send({
from: "[email protected]",
to: "[email protected]",
reply_to: email,
subject: Contact form: ${name},
html: <p><strong>From:</strong> ${name} (${email})</p><p>${message}</p>,
});
return NextResponse.json({ ok: result.ok });
}
Pattern 3: With Authentication
Combine email with OTP auth for a complete signup flow:
// app/api/auth/signup/route.ts
import { langr } from "@/lib/langr";
import { NextResponse } from "next/server";export async function POST(request: Request) {
const { email, name } = await request.json();
// Send OTP to verify email
await langr.auth.sendOtp({ target: email });
return NextResponse.json({
ok: true,
message: "Check your email for a verification code",
});
}
// app/api/auth/verify/route.ts
import { langr } from "@/lib/langr";
import { NextResponse } from "next/server";export async function POST(request: Request) {
const { email, code } = await request.json();
// Verify OTP and get session
const session = await langr.auth.verifyOtp({
target: email,
code,
});
// Send welcome email after successful verification
await langr.mail.send({
from: "[email protected]",
to: email,
subject: "Welcome!",
html: "<h1>Your account is verified</h1>",
});
return NextResponse.json({
ok: true,
session_token: session.session_token,
});
}
Error Handling
import { LangrClient, LangrAPIError } from "@langr/sdk";try {
await langr.mail.send({ / ... / });
} catch (err) {
if (err instanceof LangrAPIError) {
console.error(LANGR error: ${err.code} — ${err.message});
// Handle specific errors
if (err.status === 429) {
// Rate limited — retry later
}
}
}
Environment Variables on Vercel
When deploying to Vercel, add the API key via the dashboard or CLI:
printf '%s' "$LANGR_API_KEY" | vercel env add LANGR_API_KEY production