← Back to Blog

How to Build Emails with Claude Code and MJML

Building HTML emails with Claude Code follows a three-phase workflow. Phase 1: Claude builds a plain HTML preview with contenteditable text areas for fast, in-browser editing. Phase 2: the user iterates on content and design by editing directly in the browser and pasting changes back. Phase 3: once content is locked, Claude converts the HTML to MJML, a markup language that compiles into email-client-compatible HTML. The MJML output gets packaged and uploaded to an email platform like Loops.

What is MJML?

MJML is a markup language designed for building responsive HTML emails. Standard HTML and CSS features like flexbox and grid don’t work reliably in email clients. MJML uses its own tags (mj-section, mj-column, mj-text) and compiles them into the table-based, inline-styled HTML that email clients require. Write the clean version, MJML generates the compatible version.

Email HTML is not like web HTML. That distinction trips up a lot of people, and it’s worth understanding before you try to build anything.

Modern CSS, flexbox, grid, custom properties, most of it doesn’t work reliably in email clients. Outlook renders HTML from the 2000s. Gmail strips certain styles. Apple Mail does its own thing. Building email HTML by hand means writing table-based layouts, inline styles, and a bunch of fallbacks. It’s tedious and error-prone.

MJML is a markup language that solves this. You write clean, readable code using MJML tags (mj-section, mj-column, mj-text, mj-image), and MJML compiles it into the ugly, deeply-nested HTML that email clients actually need. You write the readable version. MJML generates the compatible version.

This post covers a three-phase workflow for building an email with Claude Code. The key insight: build as an HTML preview first, iterate fast with real editing, then convert to MJML for your email platform.

The problem with going straight to MJML

If you jump straight to MJML, every content change is an edit-compile cycle. You need to run the MJML compiler, reload a preview, look at the result. That’s fine when the structure is locked. But in early drafts, you’re changing everything: the order of sections, the copy, the visual design. Doing that in MJML is slow.

HTML in the browser is instant. You can see it. You can change it. You can hand it off to someone for edits without giving them a development environment.

Phase 1: HTML preview with editable zones

Start by building a simple HTML file, not MJML yet, just a web page that looks roughly like the email you want. The trick is adding contenteditable="true" to the text areas.

contenteditable is an HTML attribute that turns any element into an in-browser text editor. The user can click on it and type. No code editor needed. You can put it on a paragraph, a heading, a div. Anything with that attribute becomes editable on the page. This same browser-as-editor pattern is the basis for interactive HTML check-in tools.

The prompt to Claude Code:

build this as a web view first - contenteditable zones so I can edit text directly in the browser

What you get: a full HTML file you can open in any browser. Every section of copy has contenteditable="true". You can click, edit, reword. The structure stays intact. When you’re done, you select all, copy, paste the whole page content back into the conversation.

This is faster than describing edits in prose. “Change the second paragraph to say X, move the CTA above the recap” is slower than just making those changes directly in the page, then handing Claude the result.

Phase 2: Iterate with feedback

Once you have the HTML preview, review it, make your changes directly in the browser, and paste the updated content back. You can also add structural notes alongside the paste:

[pasted page content]

also: move the project pitch above the session recap, replace the promises section with a link to the /slides skill

Claude rebuilds the HTML with both the content changes and the structural changes applied. You preview again. Repeat until it looks right.

Because you’re working in plain HTML rather than MJML at this stage, Claude can also iterate on visual design fast. You can go from white background to black to cream (a specific hex like #f5f0e8) in one message. You’re looking at live browser output, not compiled email previews.

Phase 3: Convert to MJML for your email platform

Once the content and design are locked, convert to MJML. MJML’s tag structure maps closely to what Claude just built:

  • Full-width rows become mj-section
  • Columns inside rows become mj-column
  • Text blocks become mj-text
  • Images become mj-image
  • The overall wrapper is mj-body

The prompt:

convert this to MJML for Loops - cream background #f5f0e8 to match the course site, package with screenshots in a zip

Loops is an email marketing platform (used here for cohort emails). Like most modern email platforms, Loops accepts MJML templates. You upload a folder with an index.mjml file and any image assets referenced in it.

Claude generates the MJML, puts it in a folder with the right structure, and zips it. You drag that zip into Loops. Done.

The full workflow

  1. Write a rough prompt describing the email’s sections and purpose
  2. Claude builds an HTML preview with contenteditable zones
  3. Open in browser, edit directly, paste back with any structural notes
  4. Repeat until content and design are locked
  5. Convert to MJML, specifying brand colors and target platform
  6. Claude packages the MJML and assets as a zip
  7. Upload to your email platform

The first few steps happen in the browser with no email tooling involved. You’re only dealing with MJML at the end, when the structure is already finalized and you just need a compatible format.

What makes this different from a regular AI email workflow

Most AI email workflows ask you to describe what you want in prose, have the AI write the email copy, review it in a chat interface, and then manually paste it into your email tool. Each revision goes through the chat.

This workflow puts the editing in the browser. The HTML file is the draft. You edit it like a document, not a prompt. That changes the feedback loop. Structural changes (reordering sections, adding or removing blocks) are visible as you make them. Copy changes are instant. You’re seeing the actual rendered output, not imagining it from prose.

The tradeoff is a small upfront cost: Claude needs a few seconds to build the initial HTML. But that’s it. From there, every iteration is faster.

A note on brand colors

When you’re building an email that goes with an existing site or product, give Claude the exact hex code. “Cream” or “off-white” will get you a reasonable guess. #f5f0e8 gets you the right answer.

If you don’t know the hex code, open the site in a browser, use the eyedropper tool in browser DevTools (any Chromium browser), and pull the exact value. Five seconds. Worth doing.

Before you send, test your deliverability. Testing Your Email Provider covers how to check if emails actually reach the inbox.

Further reading

  • MJML documentation for the full tag reference and compiler setup
  • MJML live editor if you want to preview MJML in the browser without installing anything locally
  • Loops documentation for how to use custom MJML templates in Loops
  • Can I Email for checking CSS and HTML support across email clients (the email version of Can I Use)
  • Email on Acid for testing your final email across real clients before you send

Common Questions

What is MJML and why use it for email?

MJML is a markup language that compiles to email-compatible HTML. Email clients like Outlook and Gmail don’t support modern CSS. MJML handles the cross-client compatibility automatically, so you write clean tags like mj-section and mj-text instead of nested tables with inline styles.

Why not build emails directly in MJML?

MJML requires an edit-compile-preview cycle for every change. During early drafts when content and structure are changing rapidly, plain HTML in the browser is faster. Build and iterate in HTML first, then convert to MJML when the design is locked.

What is contenteditable in HTML?

contenteditable="true" is an HTML attribute that makes any element editable in the browser. Click on the element and type. For email workflows, this means editing copy directly in the browser preview instead of describing changes in prose to Claude Code.

How do I convert HTML to MJML with Claude Code?

Once your HTML email design is finalized, tell Claude Code to convert it to MJML for your target email platform (Loops, Mailchimp, etc.). Specify brand colors by hex code. Claude generates the MJML file and packages it with any image assets as a zip file for upload.


A note from Alex: hi i’m alex - i run code for creatives. i’m a writer so i feel that it is important to say - i had claude write this piece based on my ideas and ramblings, voice notes, and teachings. the concepts were mine but the words themselves aren’t. i want to say that because its important for me to distinguish, as a writer, what is written ‘by me’ and what’s not. maybe that idea will seem insane and antiquated in a year, i’m not sure, but for now it helps me feel okay about putting stuff out there like this that a) i know is helpful and b) is not MY voice but exists within the umbrella of my business and work. If you have any thoughts or musings on this, i’d genuinely love to hear them - its an open question, all of this stuff, and my guess is as good as yours.

Ready to build this yourself?

Join the next cohort of Code for Creatives

Join the Next Cohort →