About HTMX

I’ve heard a lot of buzz about HTMX lately. It’s a JS library that “gives you access to AJAX, CSS Transitions, WebSockets and Server Sent Events directly in HTML, using attributes, so you can build modern user interfaces with the simplicity and power of hypertext.

Here’s the simplest example that makes a POST request to /clicked, receives HTML from the server, and then replaces the button with the response.

  <script src="https://unpkg.com/htmx.org@1.9.12"></script>
  <!-- have a button POST a click via AJAX -->
  <button hx-post="/clicked" hx-swap="outerHTML">
    Click Me
  </button>

The idea is that you set up your server API to respond with HTML fragments instead of JSON, and you write that directly to the page wherever the HTMX attributes say to put it. Since all of the HTML is rendered on the server, there’s no need for a JS framework like React. Instead you just use a templating engine like http/template from the standard library, or Templ which was made to provide a great experience for building components in Go.

This appealed to my desire to write as little JavaScript as possible, and with a JS library like Hyperscript you can sprinkle in client-side reactivity when you need it, like in this example to set a CSS class on a button when it is clicked:

<button _="on click toggle .red on me">
Click Me
</button>

Also there’s an element of simplicy about using hypermedia as your state, and not having to serialize and deserialize JSON objects back and forth between the frontend and backend.

Drawbacks

Having used a few frontend JS frameworks, there were a few things that jumped out to me as areas of concern when thinking about how I would create an application with Go + Templ.

Tight coupling between the UI and the backend

With a design-first approach starting with an OpenAPI document, a frontend dev could immediately start up a mock server and start building the UI. You can work on UI components in isolation, using Storybook to preview and test them. You can tie in a test runner to run automated tests on your UI components.

If instead we are generating all of the HTML on the server in Go, you need to actually have a working API first so that your browser has something to fetch. You have to rebuild your app after every little change. If you want to preview individual components you would need API routes to render them out of context, otherwise you may have to navigate your application to get it into the state that you want to view. I haven’t thought of any good way to wrap automated testing around this.

Lack of component libraries

Even JS developers don’t necessarily want to build all of their components from scratch with every project. That’s why there are many popular component libraries that you can drop in to get all kinds of fancy widgets without having to build the CSS and JS yourself.

There’s nothing like that for Go + Templ. There doesn’t seem to be a consensus on how to build reusable components with Templ, and I found an open discussion about that at https://github.com/a-h/templ/discussions/432.

I did find web component library called Shoelace which can work with without a framework. Since it creates custom elements, until the JS loads you will see a flash of unstyled elements flicker on page load until those custom elements are initialized. I find that a bit unsatisfying.

I figured out how to incorporate Tailwind so that I could use it in my Templ components, which is nice, but I’d still have to build my own component library to provide any reusable UI and scripting elements that I need.

Debugging

I haven’t gone far enough to see what the experience of debugging the UI is like, but anecdotes I’ve read on forum posts suggest that the exprience is not great.

Editor support

There’s a Templ LSP that you can use in VSCode to get some support, but it doesn’t give you any completions for the HTML elements in your template.

Workarounds

Templ has a hot-reload feature runs a proxy to sit between your browser and the server so that it can tell the browser to refresh when there’s been a change. It’s been a little glitchy from time to time but it seems to work decently well otherwise.

I discovered that Storybook has a server framework that allows you to create JSON files for each of your components and include a URL to your server where that component will be rendered with any options provided as query parameters. I spent several days researching this and creating a storytempl package in Go to wrap around Storybook and spin up a server to preview your Templ components.

Final thoughts: Who is this for?

This seems like a stack that solo devs could use, and it’s no surprise that a bunch of Youtube content creators have been making videos on this. If you’re on a team, though, unless EVERYONE is a Go dev and you don’t have any JS frontend guys, it seems more likely that you would take an API design-first approach where frontend and backend guys can do their own thing without stepping on each others toes.

Still, I have the feeling that HTMX and server-side rendering is going to stick around like gum on the bottom of your shoe.