In-depth Next.js guides covering App Router, RSC, ISR, and deployment. Get code examples, optimization checklists, and prompts to accelerate development.
Last month I was automating customer notifications for a local business and realized how messy it becomes when HTML and CSS for emails live inside code. Updating text meant redeploying the backend. Changing layout meant editing dozens of string literals. Sharing the design with non-developers was impossible.
That changed once I started using Brevo’s transactional email templates. Instead of building emails in code, you design and manage them directly in Brevo’s visual editor, then send only the data. This separation of logic and presentation makes life easier for both developers and designers—and adds analytics automatically.
This guide walks through the full implementation: creating a Brevo template, passing parameters dynamically, and sending personalized emails from a Next.js project or an n8n workflow.
Why Templates Beat Inline HTML
When you create emails programmatically, you usually embed long strings of HTML in your codebase. Over time this becomes difficult to maintain and nearly impossible to style visually.
Brevo templates solve this problem by keeping the design in one place and using params to inject personalized content at send time. Designers can edit and preview templates visually, while developers send structured data. Brevo also provides delivery logs and analytics for every message.
Step 1 – Create a Transactional Template in Brevo
Log in to Brevo and go to Transactional → Templates.
Create a new template and open the Design tab.
Use the visual builder or import your own HTML.
Reference variables dynamically using double curly brackets:
html
<h2>Hello {{ params.FIRSTNAME }},</h2><p>Your order <strong>{{ params.ORDER_ID }}</strong> is ready for pickup.</p><p>
{{ params.LOCATION_NAME }}<br>
{{ params.LOCATION_ADDRESS }}<br>
{{ params.TIME_START }} – {{ params.TIME_END }}<br><ahref="{{ params.MAPS_URL }}">Open in Google Maps</a></p>
Save and note the template ID (you’ll need it for the API call).
Lesson learned: you don’t need to pre-create “attributes” inside Brevo. Any key inside your params object automatically becomes available in the template. Brevo reads them dynamically when the email is sent.
Brevo template
Step 2 – Send a Test Email from n8n (optional)
If you want to test before integrating into your codebase, you can send an email directly from n8n. Create a Function node and use this snippet:
This gives you a complete round-trip test before writing any application code.
n8n workflow example
Step 3 – Send Transactional Emails from a Next.js Project
Once your template is ready, sending an email from Next.js is just another fetch call. You can do this from a server action, an API route, or directly in any server-side logic.
The route can be called from anywhere in your app when an order is created or status changes.
The environment variable BREVO_API_KEY is securely loaded from .env.local.
You keep your design and copy in Brevo, not in the codebase.
Step 4 – Monitor and Iterate
Brevo’s dashboard gives you analytics, delivery logs, and open/click tracking for every transactional email. You can adjust wording or layout visually in the template editor without redeploying your Next.js project. All data placeholders continue working automatically as long as the keys in params remain consistent.
Conclusion
By switching from inline HTML emails to Brevo’s templates with dynamic params, you achieve a clean separation of logic and design:
Maintainability: Change templates visually without code changes.
Visibility: Built-in delivery and engagement analytics.
If you’re still embedding HTML emails in your backend or workflows, try this approach. It simplifies maintenance, reduces code churn, and gives your team full visibility into how messages perform.