Skip to content

The HAT stack

A spark lit up in me when I discovered HTMX. Not at first, of course. Like many others, I was sceptical at first, having spent the last years building sophisticated fullstack apps with microservice JSON API backends and hyper-optimized React frontends with SSR that I lost track of how good simple web development could be.

Throw away everything you think you know about modern web development. Go back to the bare minimum. Now you're left with basic HTML. You can add links to pages, have forms submit your data. It works!

<form action="/comment/" method="post">
  <textarea name="comment">Write a comment</textarea>
  <button type="submit">Send</button>
  <a href="/blog/">Blog</a>

Then, somewhere along the line we decided that the best way to improve upon this is by adding five megabytes of Javascript and CSS frameworks. This has been going on for almost a decade now (React.js is turning 10 this year!)

I, too, have been succumbed into this tech debt hellhole. But what if I told you there was a simpler way? Nostalgia, but for web development, I suppose.

The currently most effective way to quickly iterate over and finish new features for me personally is what I'd like to propose as the "HAT" stack. A combination of HTMX, Alpine.js and Tailwindcss.

Thanks to all aspects of your application residing closely together, you get all the benefits of the new cool kid on the block, a.k.a. web components, without any downsides of having to figure out Javascript SSR, data fetching and more. You only render your backend template (in this case Django is my go-to).

A todo app that keeps track of task states could be as simple as this:

  {% for todo in todos %}
         hx-post="{% url 'mark_done' %}"
         {% if todo.done %}checked{% endif %}
      {{ todo.description }}
  {% endfor %}

Look ma, no MobX!

Next, we add classnames for styling with TailwindCSS and have a nice UI. Need more interactivity? Alpine.js has got you covered.

Before you know it you have a completely encapsulated component in your template that will just work (tm).

As a backend focused developer, this stack brings so many benefits to me. And every millisecond in performance improvement directly translates to your frontend as well.