htmx Makes UI Development Less Costly

by Jeremy Anderson

htmx is a library written in Javascript that enables hypermedia controls for HTTP on every HTML element.

img

So what?

HATEOAS, that's what.

It sounds familiar

The concept of HATEOAS (Hypermedia As The Engine Of Application State) was introduced by Roy Fielding in his ca. 2000 dissertation that brought the idea of RESTful web applications to the world. Representational State Transfer (ful?) applications use HATEOAS as a principal concept for state management. Since then, many attempts at building RESTful applications have been made. More often than not, huge confabulations of JSON have been parsed to accomplish that end, to varying degrees of failure.

What's the deal with JSON APIs?

"What is the problem with the industry-standard approach to 'RESTful' API design?" one might ask.

  • Unreliable or unclear data linking conventions

  • Generalized non-use of hypermedia responses, not enough Content-Type mime-type header use to support the growth of rich hypermedia interoperability.

  • The lingering absence of at least half of the HTTP verbs (GET, PUT, POST, PATCH and DELETE ) that should be available to HTML markup elements for their intended purpose as hypermedia controls.

  • Inconsistent data schema implementations.

  • Unreliable or limiting data interchange formats.

I'd say that's one heck of a problem.

Other valid points against JSON-based "RESTful" APIs are related to JSON and JavaScript/TS performance issues, especially when parsing data. JSON is slow, I don't think this is a controversial assertion, but on the off-chance the reader has never encountered this information prior, here's a good video discussing the topic, and an article on Medium that goes a little bit deeper on the topic of data interchange formats and protocol buffers, which are a great solution for many uses. Even when one adopts a system of conventions for structured data on the web, like schema.org, there are missing, yet reasonably common, use-cases. It could also be argued that this leads to various forms of misuse more often than it leads to authoring extensions to fill those gaps. There are, additionally, the ever-looming topics of web API versioning, data interchange formats, text encoding, and data change management, all of which are too complex to allow for any reasonable summary of the compromises typically involved to be included here. Managing data state and schema in one place (the server) is tricky enough, juggling that state between an insecure client across a highly variable network inevitably adds unnecessary complexity to our applications' source code.

Complexity is both our power and our enemy, write it down.

Complexity is our power because the software systems human beings have collectively built can manage complex tasks in ways individual humans, and even massive teams of people, have never been able. Complexity is our enemy because it can still defeat us, utterly. Unchecked complexity is what we use for encryption, after all. It is somewhat trivial to write a program that would consume all computational resources imaginable when executed, it is even easy to understand the logic of such a program, but there are complexities which we can create that we can never comprehend, and these are the traps we must avoid to prevent complexity from thwarting our best efforts at understanding and remediation. We can harness this complexity readily, to a point; but the delta, in my opinion, between where complexity gives us power and where it robs us of options, is narrow.

"In the long run every program becomes rococo - then rubble." – Alan Perlis

Weeb Frameworks

I pulled that term out of thin air, and I'm running with it.

Weeb frameworks are characterized by having a community that embodies jingoistic fanaticism, often in spite of any contraindicative context, and exhibit blind allegiance to whatever "the new thing," is, within the given framework's ecosystem. For members of the cult, I mean community; whatever problem you have, Weeb Framework version X.x is the clear answer.

Frameworks can easily become ponderously complex. The de-facto standard weeb framework, WeebJS, (which is not a framework, according to the authors, but definitely is a framework according to any working definition of the term) is an abstract abstraction generator factory. There's no typo there, Weeb is an abstract generator factory for making abstraction for other abstractions to live inside of. Weeb is trying to provide a universally generalized solution to an inherently multifarious set of problem spaces. Anyone who has worked inside of a long-lived React, I mean Weeb, project knows what I mean. Perhaps this section will remain merely anecdotal, if only for the fact that the whole scene makes me wince, and I simply do not wish to read any more WeebJS-related content. At the very least, in my experience, Weeb makes it overwhelmingly alluring for developers (who are known to be attracted to shiny objects newly introduced into their environment) to create new abstractions, in general, rather than solve the actual problem at hand. React has long-since passed the point of being a cargo cult, it has become a Weeb Framework.

I used to encounter this in relation to a thing called Drupal. Way back, many years ago, in the mid-to-late 2000's Drupal was a popular web content management framework. Drupal was the tool that real PHP developers would swear was the best CMS. They would further argue that WordPress was just a blog engine, Drupal was superior in every way. In truth, both are fungibly horrible in many ways, but WordPress is horrible in a more tolerable way to non-technical users, which is probably why it still has a huge user base and continues to be the engine running as much as 43% of all extant websites in early 2024. Drupal claims only about 1.5% of global websites, clearly not showing off the superior strength it once claimed, with that figure. WordPress is useful, in certain cases, in spite of being limiting in other cases. It's a blog engine at heart, the Drupal fans were right about that. It stays out of your way and lets you author content, and that's a good thing. I was shouted down in forums at the time for preferring other tools, and I never relented, though there could not be an argument made that I made distinctly better choices. I was pretty new to programming the web, but I learned fast and eventually, I even learned to trust my instincts.

I've learned a thing or two about software and the business of making it since 2005, and one of those things is that HTML forms still suck. We only get two verbs, GET and POST, and this is insufficient to meet any HTTP specification, the protocol upon all of this stuff is intended to be built, has extremely limited vocabulary in the actual HTML implementation, which is wild if you stop and think about it for even a second.

TypeScript (is a linter)

I hate to be the one to break it to you, but TypeScript will not save us. TS is just a type-checking linter, not a language unto itself, and definitely does not provide proper "type safety," in any traditional sense. Every time TypeScript files are saved, they have to be checked and built in whatever way is required, and there is some amount of waiting. Is TypeScript with well defined types better than plain JS? Sure, and so are JSDoc annotations, which I ultimately feel are a better solution for the simple fact that they can completely eliminate the build step, and the majority of build tooling, thereby shortening the front-end developers' feedback loop dramatically, in ~100% of cases where TypeScript was previously used. Shortening this feedback loop saves computational and human energy, it should be an exercise for the reader to calculate the savings they might encounter from such a change in their own development team workflows.

HTMX is the Way

What does all this preamble have to do with htmx?

  • What if there was no build step?
  • What if instead of maintaining your giant build system contraption for a couple of days every month, what if your developers were just shipping new features?
  • What if we had a useful tool to abstract away 90% of the programming done in JavaScript/TS and we could just get on with solving the business use-case needs with no fuss?
  • What if we could mix in other JavaScript dependencies and it (htmx) would just stay the hell out of the way?
  • What if you could have a development team write a single language and it didn't have to be JavaScript/TS?
  • What if I told you, this utopian future is already here?

Hypermedia APIs are not a new idea, merely one that has been unfashionable for long enough to feel new.

Let's take a look at what htmx, at <16.8kB (at the time of this writing) gives us, right out of the box.

  • A real HTTP verb set. PUT, PATCH, and DELETE are available to your forms!
    • All of the HTTP verbs are available to any HTML element in your application.
    • simply use the attributes hx-get, hx-post, hx-put, hx-patch, hx-delete with the values set to your target URIs
  • htmx extends HTML with sensible behaviors for common AJAX operations, which focuses all state management onto the server, except in relatively infrequent use-cases.
  • hx-swap can dynamically swap out the markup of any element, innerHTML or outerHTML of any element, without triggering a page reload. How neat is that?
  • The htmx docs have a lot more detail, and great examples
  • Most browser interaction events, your mouse-in, your mouse-out, what have-you, can be used to trigger htmx behaviors
  • hx_push_url pushes a url to the browser history, which helps in handling the cool new view transitions you can now make with ease by using hx-swap
  • hx_boost can be applied to a set of child elements to make the child elements anchor links by default, hx-boost is subtly amazing.
  • hx-target allows you to target any element, outside of the one triggering the event, based on many different criteria.
  • It plays well with other JavaScript! It integrates easily with, and works alongside many popular frameworks, as needed.

With a bit of thought about your application design, replace most functions of popular SPA frameworks, in my opinion. If you can use htmx and get the job done, why make it harder? Or stick with your weeb framework, instead, depending on your needs.

Chonky

Most web frameworks do the opposite of staying out of our way. In fact, most development teams these days spend a good chunk of their time maintaining the meta-tooling around UI frameworks' confabulation of build tools that come as locked-in dependencies when The Weeb Framework was adopted. There will always be different shearing layers in your application, and the UI is likely to be the fastest-changing of them all, why are we making it worse by managing a huge number of ever-changing frameworks? Chasing dependencies is a sucker's game, and I'm not playing any more. A handful of tiny libraries seems much more manageable, especially client-side. htmx is one of the good ones. HOWL, an acronym for Hypermedia on Whatever You Like, is easily my new favorite stack with which to build UIs for the web.

img