Abhishek E Tweb · email · bengaluru

home / projects / cms-email-sync

Case 03 / 06 · X-Pipeline: content → inbox

Edit in the CMS. Render in the inbox. Touch nothing in between.

Web content and email content usually live double lives — the same announcement written twice, drifting apart by the second edit. This pipeline makes the CMS the single source of truth and treats email HTML as a compile target.

Project
Independent build
Role
Full-stack developer
Timeline
2023 — 2024
Stack
Python · CMS · Templating · HTML email
CMS and email sync project — content editing interface alongside compiled email output
The pipeline in use: structured CMS content on one side, compiled email-safe HTML on the other.

The brief

Every content update was being produced twice: once as a web page in the CMS, once as an email hand-assembled from that page. Twice the work, and worse — two versions that disagreed within a week. The brief: let editors write once in the CMS and have correct, email-safe HTML fall out automatically.

The constraints

  • Web HTML is not email HTML. The CMS's rendered output — divs, flexbox, external CSS, modern tags — is precisely what email clients mangle. The pipeline can't reuse web markup; it has to re-express content.
  • Editors are not email developers. Whatever they can type into the CMS must produce something valid. There is no "please don't use that block" in a real workflow.
  • Images and links need translation: absolute URLs, dimensions on every image, tracking-parameter injection — none of which editors should think about.
  • The output has to survive the usual suspects: Outlook's Word engine, Gmail clipping, images-off rendering.

The build

The core decision: map structured content, don't transform markup. The pipeline reads the CMS's content model — headings, rich text, images, buttons, lists — as data, then renders each block type through a Python templating layer into table-based, fully-inlined email components. A heading block becomes an email heading component; a button block becomes a bulletproof link. Web markup never crosses the boundary.

  • Block-type allowlist: content types without an email mapping fall back to a safe text rendering rather than leaking unsupported HTML into a send.
  • Sanitisation pass: whatever rich-text quirks editors paste in (Word artifacts included) are normalised before templating.
  • Asset handling: images get absolute HTTPS URLs and explicit width/height so layouts hold even before images load.
  • Preview before send: the compiled email renders side-by-side with the web version, so editors verify the pair as one piece of content.
The design insight: this is a compiler problem wearing a CMS costume. Source language: structured content. Target language: the dialect of HTML that Outlook 2016 speaks. Once framed that way, every decision — allowlisting, safe fallbacks, normalisation — becomes obvious.

The outcome

One edit, two channels, zero drift. Non-technical editors ship email updates without ever seeing a table tag, and the email that goes out is built from components that have already survived client testing.