Add native MJML support
Hi 👋,
First of all, thanks for maintaining listmonk — it’s an awesome project!
I’d like to introduce a Go library I’ve been working on: gomjml. It provides a Go wrapper around MJML, the popular framework for responsive email markup. The goal is to make it easy to define MJML templates directly in Go projects and render them into production-ready HTML.
Why this might be useful for listmonk
- Responsive HTML emails: MJML is a widely used standard for email templating, ensuring compatibility across major clients.
- Native Go integration: gomjml makes it possible to render MJML templates in Go code without external build steps or calling external APIS.
- Potential use cases in listmonk:
- As an alternative templating engine for users who prefer MJML.
- To simplify building responsive email templates directly within the app.
- To provide a ready-made solution for users struggling with HTML email quirks.
Links
- GitHub repo: https://github.com/preslavrachev/gomjml
- MJML project: https://mjml.io/
I’d love to hear your thoughts on whether this could be integrated (either natively or as an optional plugin/extension) to enhance listmonk’s email templating options.
Nice, @preslavrachev. MJML has been requested a few times here before. I'll give native integration a shot.
Hi @preslavrachev , I just launched an open-source alternative with a visual drag'n drop MJML editor at https://github.com/Notifuse/notifuse, feel free to try it out!
Hi @pierre-b - nice to see you've decided to use Go for the backend! I can see you are currently using the WASM-bindings version of the MJML compiler that calls into the official JS library.
I am wondering if you'd be interested in trying out the native version I have made open-source recently, and compare the performance. One of my concerns with the WASM one was that it won't scale well under load. With the native one, you should barely see any significant changes.
I would be happy to support you in porting that.
Amazing news @preslavrachev ! I was thinking of doing the same but never found time... it was definitely needed in the go ecosystem! Will ping you when the integration is done.
@pierre-b - fantastic, happy to hear! Yeah, it's a major endeavor. I mainly did it, because our team has all sorts of Go projects that would greatly benefit from not having to call an external API, or precompile and store unreadable HTML files in source control. And, I must admit, the AI helped here a ton. I wouldn't have achieved that in 10x the amount of time, if I had to code by hand. Claude Code required a bunch of course correction on my side as well, but having established a solid testing base, I could just let it solve the implementation by more or less following TDD.
Anyway, I'd be happy to support you, and update the library thanks to your feedback. It should go without saying that we are far from v1.0, so API and implementation might still change, but for the most part, existing templates should work fine. You are more than welcome to prove me wrong - if you have an edge case that's not rendering as it should, we can always add it to the suite of integration tests.
Yes TDD is the key to success with Claude, especially if the test suite already existed in the Rust codebase :) I'll follow up in your repo issues!
@preslavrachev I actually gave this a shot two weeks ago https://github.com/knadh/listmonk/pull/2643/files but mjml.Render() was failing despite being given valid markup. I haven't had a chance to debug it further, but please feel free to try out the branch if you're able to.
@knadh - indeed, @pierre-b and I discovered some breaking bugs, and a fix is on the way. Can you send me the exact MJML content you tested with?
If you want to try and see if this works, the beta tag is v0.7.0-beta.2 - I will soon make a proper v0.7.0 release.
@knadh https://github.com/preslavrachev/gomjml/releases/tag/v0.7.0 is out with some of the critical fixes. Try it out by forcing go mod to update to latest.
Seems to be working fine now @preslavrachev. I've updated https://github.com/knadh/listmonk/pull/2643 to also ship with a default MJML template.
Please try it out. You can compile from source or use the attached bin: listmonk-v5.2.0-rc1.tar.gz
@knadh Great to hear 🙌 — indeed, v0.10.0 was a major milestone in achieving feature-parity with MJML. I was previously misled to think that going after MRML (MJML's Rust compiler) was a better idea, because language-wise, Go and Rust are closer to one another. Big mistake!
Nonetheless, the library is finally on the right track, and I'd be happy to see it make listmonk users' lives easier.
I would have to build a Mac-compatible, version of the branch to test it, but if you happen to merge to master in the menatime, let me know. I'd be happy to spread the news.
when are you merging ?