Back to work
Internal

Production Pipeline

The internal tooling our team ships on every day, three pipelines for three deliverable types, built to take production cycles from days to hours.

Role
Director of Technology
Timeframe
2021 – Present
Stack
Gulp · MJML · Mustache · SASS · Node · AWS

When I joined CultHealth, every deliverable started from a blank file. Emails were hand-coded in HTML. Banner ad sets were rebuilt by hand for each size. Static landing pages were copy-pasted from previous projects. Three different types of work, three different ad-hoc processes, and no shared tooling between them. This is the story of consolidating that into a single pipeline.

The problem

Health brand work happens in tight cycles. A new campaign means a dozen emails, a banner package across six sizes, and a landing page, all due in the same week, all needing to pass the client's compliance review. When everything is hand-built, every cycle starts from zero.

Three problems stacked up. Production time was unpredictable, depending too much on who was building it and how recently they'd done one. Quality drifted between deliverables because there was no shared component layer. And every change request meant manual updates across multiple files, with the inherent risk of forgetting one.

I wanted three things from a new pipeline: consistency (the same brand should look the same everywhere), speed (production measured against a single short cycle, not stretched across weeks), and auditability (every build should be reproducible from source for compliance audits).

The architecture

I built three sub-pipelines that share a common Gulp foundation and toolchain but specialize for their output format. Each one ingests structured content, applies brand tokens, and emits the deliverable.

System overview
Site tokens
JSON
Content
YAML
Partials
Shared
Email
Gulp · MJML
Banner
Gulp · Mustache
Static Site
Gulp · Mustache · SASS
.html
Consistent on all major email clients
.zip
Ad bundles
Static build
Configured for environment

Email pipeline

Emails are the highest-volume deliverable and the most regulated. The pipeline takes a structured content file, merges it with the brand's MJML template library, and outputs compliant HTML with inlined styles, alt text validation, and test-rendered previews across the major mail clients. Audit-ready in one command.

Banner pipeline

Banner ads have to ship as a zip per size, each containing self-contained HTML and CSS that the ad network can serve. The pipeline reads a single source template, applies size-specific variants from a Mustache layer, and emits the full ad set with one build. What used to be a multi-hour designer task is now a single build command.

Static site pipeline

For one-off landing pages, the pipeline combines Mustache for templating, SASS for tokenized brand styles, and a shared component library. Pages ship as fully static HTML with optimized assets, ready to deploy to S3 behind CloudFront via the AWS pipeline.

Key decisions

Gulp over Webpack

Counter-intuitive in 2021, but the team's deliverables aren't apps; they're documents. Webpack's strengths (module graphs, code splitting, hot reload) are wasted on email and banner work. Gulp's task-based model maps naturally to "given these inputs, run these transforms, emit these files." Easier to reason about and easier to extend.

Mustache over a JSX-style templating library

Mustache is intentionally restrictive, no logic in templates, just substitution. This matters when content can come from non-developers (writers, account managers editing YAML). It's harder to break a Mustache template than a JSX one, and the constraint forces clean separation between content and presentation.

Brand tokens as a shared layer

The pipelines look different but share their input layer. A brand token change (a color, a font, a logo) propagates to every deliverable on the next build. This is the single biggest reason the system reduced rework: global changes that used to ripple manually across files now propagate at the token level.

Outcomes

The pipeline now runs every day across the team, resulting in a 40%-60% reduction in development turnaround time. It's the platform new engineers learn first because it's what everything depends on. Where we used to spend cycles rebuilding the same scaffolding, we spend them on the harder work: getting compliance right, getting the brand right, shipping more for more clients.

What I'd do differently

Gulp held up better than I expected, but the next iteration would invest in stronger schema validation at the build step. The pipeline grew organically, and a clean rewrite with a schema validator on the token and content layers would catch a class of content errors we currently catch in review.

I'd also invest earlier in a visual regression layer. The automated BrowserStack regression testing the team adopted later would have caught a handful of subtle output bugs that shipped because we trusted the build was deterministic. It mostly was. Trust, but verify.