Progressive Emails Using Vue + MJML
Sending email to users is something almost every developer has to deal with. One thing we deal with when writing web applications is authentication. This typically entails sending an email to the user so they can verify that they are indeed the owner of the email address.
As a back-end developer, I’m very eager to just send plain-text in an email with a link for the user to verify their email. This works well but, at some point, our email should look “professional”. Here’s an example of an email we send out to new users at DevWars:
The pains of writing HTML / CSS for email can take away the excitement of working on the core functionality of your application.
This is where MJML comes in. It provides a great set of common components that render responsive email HTML. These include buttons, columns, images, etc.
MJML has a compiler which generates static HTML files from our MJML files. However, we need more than static content when sending out email to users. For example, the email shown above must contain a link with a custom key per user.
This is where a templating system like Vue.JS comes in. Here’s what the markup for the “Confirm Email” button looks like:
Using Vue, we can quickly turn this into something even more visually appealing:
Now we have an idea of just how simplified this process can be. Let’s see what our implementation looks like.
Our API server needs to send the “welcome” email and pass along a “url” property so the button has the appropriate verification link.
Our API server will make a POST
request to our web server with the route /mail/welcome?url=https://api.devwars.test/auth/verify?key=xxx
.
Nuxt.JS supports Server Side Rendering(SSR) out of the box, so we can use the query parameter from the request in our Vue instance.
Now the url property is on the instance of the Vue component.
Now it’s as simple as taking the HTML returned from Nuxt.JS and sending it off to your mail provider of choice (MailGun in our case).
The web server can make calls to our API server just like any other part of our front-end web application. Our email rendering service has full access to all of the front-end code.
We can even allow our front-end to provide a dynamic subject line:
We’ve setup our web server to respond to our API server with a JSON schema of:
{
"subject": "Welcome to DevWars - Please Confirm Email",
"html": "<rendered html here>"
}
This is 🔥🔥🔥🔥🔥. Now our web server is fully responsible for everything about an email. However, all of this wouldn’t be useful unless our designers could see what they’re working on in the browser.
To handle this, we have two routes
mail/render
— Responds with HTML only (No subject line).mail/translate
— Responds with the JSON schema shown above.
Now our designers can see their in progress email design update in real time by hitting the route mail/render/welcome?url=xxx
.
Closing Thoughts
A lot has changed in the past couple of years in the field of Web Development. We’ve migrated from a back end which is responsible for serving HTML and data to a split system where the back end serves data to our front end, which then takes that data and renders it to HTML.
This has left us in a strange limbo state where we’re just not sure where / who is responsible for rendering email. If you’re of the belief that your API is responsible for data and your front end is responsible for rendering for the web, then I think what we’ve discussed above is a good solution for you. Adopting this mindset saves you from having to use two templating engines. Your front end developers will be much happier to implement the design for an email.