No one likes to code email templates
Let’s be honest, when a new email template needs to be coded, the ticket jumps around like a hot potato until it lands on the intern’s lap. Nobody wants to code emails. They are cumbersome and unrewarding. In an age where browsers are pretty good at complying with W3C specifications (some E2E libraries, like Cypress, don’t even implement browser engines other than Blink), emails feel like a 2010 throwback party.
Why is that? Well, the problem boils down to email clients having outdated and restrictive engines in place (here’s a good article that explains why). Not only that, implementations differ from each other. What does this mean?
- On some clients, external links to CSS files are ignored, to the point of only accepting inline styles on elements.
- Most modern CSS techniques are useless, especially those around layout (tables to the rescue) and media responsiveness.
- Current tools to make this process easier are lacking some essential features for writing reliable software: re-usability between projects and unit testing to name a couple.
Looking for a solution
Our first instinct was to use a simple Gulp pipeline and throw a couple of libraries into the mix for style inlining and SASS capabilities. It’s a proven workflow that’s been implemented before that we were already using for a couple of old projects.
This solution would’ve been enough, but it was still a far cry from what we’re used to here at Paddle. Some might say that us modern developers are spoiled kids with all our shiny tools, but coding an email felt quite rudimentary compared to our newest React projects.
So then we thought, why not use React?
Using React to write emails
React is output agnostic. We have a library that renders the code into HTML for the browser, but we also have libraries to serve code from the server, create PDFs and even generate Sketch documents. Why don’t we use this potential to render out emails as if they were pages on an SSR application? Doing so would allow us to:
- Create components that can be re-used between emails and obfuscate the complexity of an email layout. We would have composition as a by-product.
- Write snapshot testing with Jest so we can run unit tests before deploying to production.
- Use processes and workflows already in place for other projects.
- Use the same component library that we’re using for our main React apps, ensuring stylistic consistency.
- Make them pleasurable to work with. I can’t stress how important this was to us.
Our first impulse was to use
ReactDOMServer, which provides a simple way to render any component to an HTML string. The only downside is that it would also attach extra DOM attributes necessary to React but useless to us. Fortunately, this library also provides
renderToStaticMarkup, which renders HTML without them.
Here at Paddle, we use styled-components library to manage our component styling. Although it’s now a vital part of our tool belt, we went through a big mindset shift to feel comfortable with it, partly because it didn’t fit our idea of “separation of concerns”. We needed a mental category reshuffle: from “concerns” being the “layout/style/behaviour” triad to being “isolated components”. Also, hey, categories are just social constructs, we thought. So we went for it and called it a day.
We wanted to use this same library to build our emails, so we were more than happy to discover that
styled-components has an excellent API to help us out. We used
StyleSheetManager provider to help us out with building an external stylesheet.
Some email clients don’t read embedded styles (or external style sheets), so we needed them to be inlined. We found that the fine guys from Automattic (the company behind WordPress) have open-sourced a nifty tool called juice. It inlines your styles in your markup and embeds the ones you can’t inline (eg. media queries).
We discovered the hard way that email clients don’t like compressed markup, so we beautify it after the build process.
Conclusions and next steps
So, what are the next steps for this tool?
- Come up with a brilliant name (I’m personally pushing for Pony Express).
- Keep an eye open for bugs and possible improvements.
- Move most of our current emails to this new system.
- Abstract the main pieces into their own
npmmodule, so we don’t have all of our email templates in a single repo.
- Open source the project and try to help other developers improve the email development experience.
It’s weird (like, pleasant weird) to work in a project that feels and behaves like a React app but compiles to an email, but our first project using our React Email Library (we’re still working on the name) went to production and we’re delighted with it.
Want to work on creative coding projects like these? Check out our current engineering openings here.