Modular Messaging Workflows with Resend and React Email
Executive Summary
Email is still the connective tissue between our funnels, product surface, and customer success automation. The problem with traditional setups is that every campaign duplicates markup, QA is manual, and engineering ends up on-call when a CSS regression hits Outlook. We rebuilt the Marsala messaging stack as a proper software system: React Email component libraries, Storybook-driven previews, Resend for authenticated delivery, n8n for orchestration, and automated QA that runs on every pull request. This post documents the reasoning, architecture, and rituals so other teams can ship email like they ship web apps.
Problem Statement
By mid-2024 our email operations were brittle. Marketing had dozens of HTML fragments living across Google Docs, designers exported images ad hoc, and ops triggered sequences through Zapier recipes that nobody owned. Regression bugs, duplicate sends, and inconsistent branding were daily occurrences. Worse, a single template tweak required dev time because nobody trusted the tooling. We needed an approach where:
- Templates are components with clear props and tests.
- Workflows are declarative, versioned, and observable.
- QA is automated, not produced via screenshots in Slack.
- Delivery is authenticated with traceable webhooks.
Architecture Overview
The new stack is split into four logical layers:
- Component Library. React Email components stored in a private package. Designers work in Figma using the same tokens as our site, then developers export those tokens into the components.
- Template Assembly. Each email template is a composition of the shared components plus content fed through MDX or CMS entries. Storybook renders them in multiple viewport sizes.
- Workflow Orchestration. n8n flows triggered by Segment events or internal API calls. Each node uses environment-scoped credentials and is linted as part of CI.
- Delivery + Telemetry. Resend handles sending via domain-authenticated keys; webhook payloads flow into PostHog for journey analytics and Supabase for compliance logging.
Component Design System
The component library uses a strict design token contract. Every building block—hero, call-to-action, metric card, testimonial, invoice detail—receives props for copy, colors, and layout states. Components are stateless functions with exhaustive TypeScript definitions. We adopted a “render once, hydrate nowhere” mindset: there is zero client-side JS, only responsive HTML that degrades gracefully.
Key patterns include:
- Utility wrappers (
Stack,Section,InvertedSection) that enforce spacing and fallback colors. - Composable lists for feature bullets, metrics, and timelines, each supporting optional icons.
- Dynamic footers that pick the correct compliance copy (waitlist vs transactional) based on props.
All components live inside /packages/email-kit with their own ESLint + Prettier config, Storybook stories, and snapshot tests.
Automated QA Strategy
Quality is enforced at three levels:
- Storybook visual regression tests run through Chromatic for major clients (Apple Mail, Gmail, Outlook). We capture both light and dark modes.
- Mailosaur end-to-end runs: on every PR we send sample emails to disposable inboxes and assert on subject lines, major sections, and tracking pixels.
- Accessibility linting using custom scripts that check semantic markup (roles, alt text, heading order) and color contrast ratios.
If any test fails, the GitHub Action blocks the merge; marketing cannot override the gate without involving engineering. The result is a predictable QA pipeline instead of pixel chasing before launches.
Workflow Orchestration with n8n
Each workflow is described in YAML alongside the code. We disable the n8n UI editor in production instances to avoid out-of-band changes. The typical lifecycle:
- Create an
automation.ymlfile referencing triggers, nodes, and expected outputs. - Check the file into the repo; CI transforms it into an n8n JSON workflow.
- Deploy via Fly.io and verify using scripted smoke tests.
- Register the workflow in the catalog so observers know ownership, SLOs, and alert channels.
Example triggers include form submissions, CRM stage changes, product usage thresholds, and billing events. Each flow enriches the payload (Clearbit, Supabase lookups), selects the proper template, and sends via Resend’s API. We also emit structured logs so revenue ops can audit who received what and why.
Security and Compliance
- Secrets management: All Resend keys live in Doppler, then flow into Netlify functions/n8n through short-lived tokens.
- Domain authentication: We authenticate
noreply@marsala.devvia Resend’s domain settings plus DMARC enforcement. n8n notifies us if DKIM fails. - PII handling: Templates never include raw PII; we reference hashed IDs and fetch sensitive data on-demand from Supabase just before rendering.
- Opt-out logic: Every workflow checks suppression lists maintained in the warehouse; suppression mismatches trigger alarms.
Performance and Telemetry
Every send writes three records:
- Resend webhook capturing delivered, opened, clicked events.
- Journey analytics pushed to PostHog for cohort analysis.
- Warehouse log in BigQuery for compliance and capacity planning.
We monitor per-template stats—send volume, open/click rate, spam rate—and feed them into dashboards. If a template underperforms for three consecutive days, the workflow automatically routes to the previous stable version until owners review.
Results
- Time to build a new sequence: 2 days → 4 hours.
- Manual QA debt: reduced by 80%; engineers rarely need to eyeball HTML.
- Click-through rates: up 38% thanks to better personalization and consistent design.
- Incident count: zero production incidents tied to email assets in the past six months.
Implementation Checklist
To replicate this setup, we recommend the following order of operations:
- Audit existing templates. Capture every email variant, map required modules, and delete anything redundant.
- Define tokens + typography. Align with the main design system so the site and emails share visual primitives.
- Build the component library. Start with basics (logo header, hero, CTA, footer) before tackling complex modules.
- Wire Storybook + Chromatic. The earlier you integrate visual regression tests, the less tech debt you accrue.
- Codify workflows in YAML. Treat your automation definitions like infrastructure; lint and version them.
- Instrument Resend webhooks. Observability must launch on day one, not as an afterthought.
- Educate stakeholders. Marketing, support, and RevOps should know how to request changes and read dashboards.
Cost of Ownership
The financial footprint for our setup looks like this (rough monthly estimates):
| Item | Cost | Notes | |------|------|-------| | Resend (50k sends) | $60 | Includes dedicated IP warm-up | | Chromatic | $30 | Unlimited collaborators | | Mailosaur | $59 | Automated inbox tests | | Fly.io (n8n) | $25 | High-availability deployment | | Engineering time | 8h/month | Mostly reviewing PRs and improving components |
The all-in cost is lower than what we previously spent on legacy ESP templates and manual QA hours, while delivering much higher reliability.
Migration Notes
- Parallel run for two sprints. Keep the old ESP running while the new stack shadows sends, so you can compare logs.
- Gradual template rollout. Start with transactional emails (password reset, invoicing) before moving into marketing campaigns.
- Change management. We held office hours for marketing every Friday during the migration; catching misunderstandings early prevented shadow tooling.
Frequently Asked Questions
Q: Can non-technical users edit templates?
A: Yes. Content lives in MDX/Notion documents with clearly defined slots. Marketing edits copy, runs preview links, then opens a PR. Engineering reviews but rarely rewrites copy.
Q: How do you test multi-language emails?
A: Localization teams commit translation files per template. Playwright tests send each locale to Mailosaur inboxes and assert on subject/body strings.
Q: What about dark mode quirks?
A: We run Storybook stories in both light/dark tokens and use CSS prefers-color-scheme to switch backgrounds. Components expose fallbacks for clients that ignore media queries.
Failure Playbooks
Even with automation, things break. We maintain playbooks for the four most common failure modes:
- Webhook backlog. If Resend webhook retries stack up, we trigger a Cloud Run job that replays events from the last hour and sanity-checks delivery states.
- n8n workflow crash. A healthcheck monitors DAGs; on failure we roll over to a hot standby and notify owners with the payload that caused the crash.
- Template regression. Chromatic diffs failing in
mainautomatically roll back the package version consumed by the site and trigger a blocking issue. - Compliance alert. If PostHog flags an unsubscribe breach, the workflow flips to “manual send” mode and raises a PagerDuty incident until the suppression lists are reconciled.
Practicing these drills quarterly keeps the team confident and reduces time-to-recovery to minutes.
Lessons Learned
- Treat email like software. Component libraries, linting, and CI/CD are non-negotiable.
- Version workflows. YAML-as-source-of-truth prevents “mystery nodes” from appearing in production.
- Telemetry beats opinions. The feedback loops (Chromatic, Mailosaur, Resend webhooks) tell us when a template regresses faster than any manual process could.
- Shared ownership. Marketing can propose changes, but engineering reviews them in PRs; nobody bypasses the pipeline.
What’s Next
We are extending the component library to support Liquid-like slots so localized copy teams can author content independently. We are also exploring AI-assisted QA—models that scan renders and flag off-brand layouts before Chromatic even runs. If your team wants to adopt a similar approach, reach out; we’re happy to share the repo structure and the n8n linting scripts that keep everything sane.