Lustre and Gleam Make my Heart Rate Go Down - a Case Study

enoonan

Eileen Noonan

Posted on October 3, 2024

Lustre and Gleam Make my Heart Rate Go Down - a Case Study

I was recently approached by a client about a "financial assessment" javascript app on their Wordpress site that no longer worked. It had a slew of problems, and in the end, the easiest route was to rebuild it.

In this app, users can enter basic financial and personal info, and the app tells them whether they're on the right path in terms of financial planning. It's not super complex logic, but there is quite a bit of it.

I'm not, primarily, a frontend dev. I'm most comfy on the backend. But I've implemented projects in Vue, Angular, React... They work, but I don't fully trust them. And as the months and years pass by, I always develop a creeping anxiety over just how out of date the dependencies must have gotten, including the dev toolchain itself.

Enter Gleam

Gleam is a friendly language for building type-safe systems that scale!
~ Gleam's website

I've been excited about Gleam since they first declared v1 was ready for production. Its functional style, immutability, exhaustive pattern matching, type inference, and the simplicity+stability of Go meant Gleam hit all my sweet spots.

The type system pretty much guarantees that if your code compiles, it works. I've yet to encounter a bug in my Gleam code that wasn't some version of "my bad, I forgot to finish implementing that."

Enter Lustre

Gleam was built to run on the BEAM (Erlang's legendary battle-tested VM), but it also has a Javascript compilation target. That means it can easily ship to Node and the browser.

Lustre is Gleam's pre-eminent frontend framework. It's a faithful port of Elm to the Gleam ecosystem, and features Elm's "Model -> View -> Update" state management architecture.

This is a drastically simpler conceptual model than other frontend frameworks. Rather than offering state management as an opt-in library (I'm looking at you redux), Lustre's state management model is its beating-heart core.

You simply describe every verb that can take place to modify the state within your app, and map that verb to a type-safe pure operation that returns an updated version of the model. The view functions (also pure) flow directly from that unitary model's state.

Lustre also provides a managed effects system so that even with various I/O operations that may fail, your app code can be implemented using entirely pure functions.

The cool thing about pure functions? They are guaranteed to always provide the same output given the same input. This makes them predictable, easy to test, and extremely stable. Pure functions don't break. They kinda mathematically can't.

Sweet, Sweet Boilerplate

Lustre apps can involve a bit more boilerplate setting up the app and creating all the types and such. But ...

Never has there been a more apt framework to which the term "boilerplate" was applied. It gives me the same feeling of confidence I'd get from driving a rivet into a sheet of steel. Once in place, that thing is not going anywhere.

I struggle to express how different this feels compared to my prior experiences with javascript. My app might have been fewer LOC if I'd done it in another framework. But would I trust it not to break? Would it be as simple to understand?

The End Product

I shipped my app on time and under budget. The client is really happy with it. And I sleep easy knowing that this project is well and truly done.

Not only that, but it lives comfortably in Wordpress of all places. I made a shortcode to load the compiled assets, popped it on the page, and that's that.

The JS bundle is 18.1 kb, minified and gzipped. That's almost as small as htmx. For crying out loud!

I do have some reservations about shipping a project using what is still a relatively obscure language and framework. But those reservations are soothed knowing that the app won't break, and that Gleam itself can be learned in an afternoon.

Most important - I honestly don't think I'd be as confident in the end product, in the stability of the toolchain, or in my ability to upgrade it in the future, if I'd built it using anything else.

My Heart Rate

I am now coming to my entire motivation for writing this post: the feeling of having a Lustre app in production

It's been a couple weeks since this app shipped, and I still like to revisit it from time to time. Not because the client has asked for changes. Just to look at the code.

I almost feel embarrassed saying this, but most of my other code feels like a liability on some level. Especially javascript. Even if it's Typescript, even if it has tests. It makes me feel anxious, like it's strewn with hidden landmines and booby traps.

Maybe it's a skill issue. Maybe I've just been burned too many times.

Looking at my Gleam/Lustre code makes me feel calm.

That's it. That's the tweet.

In closing, it is my sincere wish that other developers will give Gleam and Lustre a try, so that they too may enjoy this same Zen-like bliss when contemplating their code.

Thank you for reading.

💖 💪 🙅 🚩
enoonan
Eileen Noonan

Posted on October 3, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related