DEV Community

Muhammad Shahid
Muhammad Shahid

Posted on

Stop Writing Brevo Email Boilerplate — Use This Production-Grade Node.js Kit Instead

If you've ever integrated Brevo (formerly Sendinblue) into a Node.js or Next.js SaaS app, you already know the pain:

  1. You copy-paste transactional email logic across three projects
  2. Your webhook handler has no signature verification and breaks randomly
  3. Your "drip sequence" is three setTimeout calls held together with prayer
  4. GDPR right-to-erasure is a TODO comment from six months ago
  5. Every new dev on the team re-implements the same contact sync logic

I've shipped three SaaS products in production using Brevo. After extracting and refining the same patterns over and over, I packaged everything into brevo-saas-kit — a production-grade, zero-opinion email automation library for Node.js SaaS applications.

This isn't a thin wrapper around the Brevo API. It's the actual email layer I use in production — with drip workflows, HMAC-verified webhooks, GDPR compliance, BullMQ queue support, and native Next.js App Router + Express integrations.

Transactional emails
Welcome, verification, invoice, password reset, role change, account deletion
Contact management
Create, update, tag, segment, bulk sync
Automation workflows
Onboarding drip, trial reminders, re-engagement, upsell sequences
Webhook handling
HMAC-SHA256 verification + typed event routing
Next.js integration
Server actions (use server) + App Router webhook handler
Express integration
Middleware + webhook router
Queue system
Immediate or async BullMQ processing
Analytics
Campaign stats, contact engagement scoring, CSV/JSON export
Security
In-memory rate limiter, HTML sanitizer, API key validator
GDPR
Right to erasure, signed consent logging, unsubscribe handler

Installation
npm install brevo-saas-kit

or

yarn add brevo-saas-kit
pnpm add brevo-saas-kit
bun add brevo-saas-kit

Optional: async queue support

npm install brevo-saas-kit bullmq

Set your environment variables:
BREVO_API_KEY=xkeysib-your-api-key
BREVO_SENDER_EMAIL=no-reply@yourdomain.com
BREVO_SENDER_NAME=YourApp
BREVO_WEBHOOK_SECRET=your-webhook-secret

Contact list IDs from Brevo dashboard

BREVO_LIST_FREE=1
BREVO_LIST_PRO=2
BREVO_LIST_ENTERPRISE=3

Only needed for async queue mode

REDIS_URL=redis://localhost:6379

Scenario 1: User Signup Flow (Next.js SaaS)
This is the most common real-world use case. User signs up → create Brevo contact → send welcome email → start onboarding drip.
`// app/api/auth/signup/route.js
import { createContact, sendWelcomeEmail, startOnboardingSequence } from 'brevo-saas-kit';

export async function POST(req) {
const { email, name, plan } = await req.json();

// Save to your DB first
const user = await db.users.create({ email, name, plan });

// Brevo: create contact, tag with plan, add to right list
await createContact({
email,
name,
plan, // automatically adds to BREVO_LIST_FREE/PRO/ENTERPRISE
updateIfExists: true,
});

// Send welcome email
await sendWelcomeEmail({
email,
name,
dashboardUrl: https://yourapp.com/dashboard,
});

// Start 5-step onboarding drip (Day 0, 1, 3, 7, 14)
await startOnboardingSequence({ email, name, mode: 'inline' });

return Response.json({ success: true, userId: user.id });
}`

Scenario 2: Production Webhook Handling (Next.js App Router)
The #1 thing I see broken in Brevo integrations: webhooks with no signature verification. Anyone can POST to your endpoint and fake a bounce or unsubscribe event.
brevo-saas-kit handles HMAC-SHA256 verification automatically:
`// app/api/brevo/webhook/route.js
import { createNextjsWebhookHandler } from 'brevo-saas-kit/integrations/nextjs/webhook';

export const POST = createNextjsWebhookHandler({
secret: process.env.BREVO_WEBHOOK_SECRET,

onDelivered: async ({ email, messageId }) => {
await db.emails.update({ status: 'delivered' }, { where: { messageId } });
},

onBounced: async ({ email, isHardBounce, reason }) => {
if (isHardBounce) {
// Suppress future sends, notify your team
await db.users.update({ emailBounced: true }, { where: { email } });
await notifyTeam(Hard bounce: ${email} — ${reason});
}
},

onUnsubscribed: async ({ email }) => {
await db.users.update({ unsubscribed: true }, { where: { email } });
},

onSpamComplaint: async ({ email }) => {
// Immediately suppress — legal obligation in most jurisdictions
await db.users.update({ markedSpam: true }, { where: { email } });
},

onError: async (error) => {
console.error('[brevo-webhook]', error.message);
// Send to your error monitoring (Sentry, etc.)
},
});`

Every event is typed. No more if (event.event === 'hard_bounce') string matching across 200 lines.

Scenario 3: Trial Expiry + Re-engagement (SaaS Lifecycle)
This is where most SaaS email integrations fall apart. You need timed sequences, not just one-off sends.

Scenario 4: Invoice Emails (B2B SaaS)
Stop attaching PDFs nobody reads. Send a clean, structured invoice email.

Scenario 5: GDPR Right to Erasure
If you're selling to EU customers, this isn't optional.

Scenario 6: Express Middleware (REST APIs)
Scenario 7: Contact Engagement Analytics
Know which users are actually reading your emails before you trigger upsell campaigns.

Why Not Just Use the Official @getbrevo/brevo SDK?
The official SDK is a raw API client. You still need to:

  1. Build every template yourself
  2. Write webhook signature verification from scratch
  3. Implement retry logic, rate limiting, error normalization
  4. Create your own drip/sequence orchestration
  5. Handle GDPR compliance manually

brevo-saas-kit is the production layer on top of that. It handles the patterns, not just the API calls. Think of it the same way you think of next-auth vs raw JWT — same relationship.

Links

npm: npmjs.com/package/brevo-saas-kit
GitHub: github.com/msal95/brevo-saas-kit

If this saved you time, a ⭐ on GitHub goes a long way. PRs, issues, and feedback welcome.

Top comments (0)