ringvold

ringvold

Hemmer - A Rust library for transforming HTML into email-client-ready output

Hey! :waving_hand: I made a thing!

Well, mostly Claude but I did have some say in the matter. :grinning_face_with_smiling_eyes:

It is a library for transforming HTML to email client optimized output. It was inspired by Maizzle, but as that is a node based project it did not fit very nicely with our Phoenix app and we also had some other use-cases we would like to have supported.

Story time!

We currently use MJML to create our emails in the apps we want some something else than plain text emails, but we found that it was hard to figure out what the end result would look like, with a sub-par feedback cycle, and had some issues related to different rendring in different email client (some important buttons just disappeared in gmail for some reason :smiling_face_with_tear:).

Also we had an experiment where we wanted an LLM-based agent to produce parts of the email and it had problems getting it right with MJML. But plain HTML and CSS, and also Tailwind, is something they do well so I searched for some projects similary to MJML and possible Tailwind support and found Maizzle. Its Nodejs based and already there it was a bit of a showstopper as I would like to not add node as a depenency and also it requires a build step as far as I understood. It also has its own template system which we dont need as we will just use HEEx.

I’m sure Maizzle a great project but it did not quite fit our needs. It did spark an idea though: what if we could create a library that could do the most important transformations for producing email optimized HTML, with Tailwind support, if you are so inclined, at runtime.

So thought, so done, as we say in Norwegian, or “No sooner said than vibe coded” might be a bit more correct her. :stuck_out_tongue:

The fun side effect of this for us is that we can create the email template/design in a way that is much easier to validate, whether its artisanally handcrafted or LLM-aided or generated.

Hemmer is a rust crate and a hex package packaged and delivered with rustler and rustler_precompile.

It has transformers for CSS inlining, table attribute defaults, Outlook conditional comments, rempx conversion, CSS variable resolution, and other smaller fixes and optimalizations.

TL;DR: Hemmer is a rust and elixir library for optimizing HTML for email. It’s early and tested to work well with a sample size of one, but you are free to give it a try if you want. :smile:

https://github.com/ringvold/hemmer

Where Next?

Popular in Announcing Top

danschultzer
In short Plug n’ play OAuth 2.0 provider library. Just set up a resource owner schema with Ecto (your user schema), install the dependen...
New
mischov
import Meeseeks.CSS html = HTTPoison.get!("https://news.ycombinator.com/").body for story <- Meeseeks.all(html, css("tr.athing")) do...
New
ostinelli
Let’s write a database! Well not really, but I think it’s a little sad that there doesn’t seem to be a simple in-memory distributed KV da...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43622 214
New
Eiji
ExApi is a library that I’m developing now and hope release soon This library will allow to: list all apis list all api implementation...
New
bluzky
You may know https://ui.shadcn.com/, a UI component library for React. I really love it’s design style and components. I’ve built some co...
384 13736 119
New
Flo0807
Hello everyone! I am excited to share our heart project Backpex with you. After building several Phoenix applications, we realized that...
New
OvermindDL1
Been making an MLElixir thing (not released yet…) for fun in spare time in the past day. I’m just trying to see how much I can get an ML...
132 13966 106
New
marcuslankenau
I feel kind of stuck with the absence of a proper xml library for Elixir. Currently I use SweetXML which was ok for me more or less to pa...
New
trisolaran
Hi! :waving_hand: I would like to present LiveSelect, a little library that I wrote to easily add a dynamic selection input to your LV f...
198 10858 107
New

Other popular topics Top

sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 42920 311
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29377 241
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

We're in Beta

About us Mission Statement