We have htmx & hyperscript running in production powering a fintech saas.
It is fantastic in the way that all really good technology is: it just does what it's supposed to do so simply and efficiently that you kinda forget it's there, so you end up spending time where it counts (UX and business logic), instead of fighting finicky frameworks.
No-one in the real world cares about the supposedly great framework powering a web app - they just care that the app is fast, easy to use and saves them time and money.
I have htmx running in production with a Django backend. It’s honestly like having a cheat code for web development. Simple, scalable code that does the job perfectly!
This exactly. I just started a new project with htmx this past week, and it absolutely amazing. It brings the magic of the web back we first experienced moving away from 90's windows programs. I'm a firm believer that react/angular are grossly mis-used for information based apps and websites, they should really only be used for rich client apps like chat, music players, image editors, offline, etc.
I have mixed feelings about htmx. It's wonderful, but it's going to take years for companies in my area to know it exists. I will totally pick it for some personal project though.
I find this approach really interesting and have spent some time browsing HTMX docs in the past but there's one thing I feel like I'm missing. Most existing server-side rendering frameworks / templating engines I'm familiar with tend to assume they're rending a complete HTML document rather than just an HTML "fragment" needed by something like HTMX to do dynamic page updates. What does the server-side look like with an HDA stack look like in practice?
From TFA, they use the example POST /search where a snippet of HTML is returned from the /search call and is injected into the page. What would the backend look like? Presumably you still want HTML templating and component-based design instead of regressing to hand building the response, but what frameworks/packages/utilities exist in that space that don't assume they are rendering a complete page?
In particular, "whole app" frameworks like NextJS or SvelteKit are automatically mapping URLs onto a root component that is automatically decorated with all the chrome needed to make it a complete page. Is the approach to just overload those root page components and take all the chrome away to get a partial document in the response?
htmx includes headers, `HX-Request` which will be true if the request is an htmx request, and `HX-Target` that will be the id of the target element, if any, that allow you to modify your response as needed on the server side. This is very common: you have a single URL that satisfies both the htmx and non-htmx request (e.g. /search) and in the htmx case, you don't render the surrounding layout, but in the "normal" case you do.
If a server side option isn't available or is inconvenient, you can instead use the client-side attribute `hx-select` to select a bit of the HTML from the response for inclusion in the DOM.
With Django and flask and everything else I've ever used, there is a templating system at play. I use the request headers to determine if I should return a whole page or a portion of a page.
For example I have a form that's something like
form_partial.html: partial form template:
<form hx-post="{{ request.path }}" hx-swap="outerHTML" hx-encoding='multipart/form-data' hx-target="this">
{% csrftoken %}
... some other form stuff from django
</form>
form.html: A normal page that includes that form:
{% extends core.html %}
{% include partial_form.html %}
Then in the controller code I choose whether to render the entire page (form.html) or a partial page (partial_form.html) depending on the presence of the htmx headers.
So the full load might look something like:
1. Visit mysite/coolform
2. Server renders whole page
3. Browser submits form data
4. If the form is invalid, return only the partial form, swapping the forms html
and if the form IS valid, return a redirect
Another cool thing (checkout hx-boost ) about htmx is that even if you return a whole page you can actually still avoid a full page reload and only swap out the body component. So even though you're returning a few extra bytes the site isn't re-executing the entire JavaScript bundle every time you navigate to a new page.
Compare to turbo/stimulus from Rails world; I would put the approach in the same basic category, that being: Custom HTML attributes triggering standardized behaviors, with HTML sent over the wire for partial page updates.
I wonder what other platforms are going on right now in this same category -- anyone have more examples?
And in general how much "mind share" (or really development-share) it's getting.
I'm not super familiar with this but what I can say is that many of these things were inspired by Phoenix LiveView, and as far as I know LiveView is still the one that works best.
I don't know much about this field, but as a WWW user i would be happy if such features became part of the HTML spec so that browsers can implement them natively without becoming an entire javascript-based operating system with all the problems involved by this endeavor.
The core assumption of stacks like htmx is that you don't need fine-grained client-side interactions implemented in custom Javascript; that when you need the UI to change, it's ok to go through the server.
An example edge case where this fails completely is a canvas-based interactive game, where you (a) cannot "ask the server for html" in order to update your game UI and (b) going through the server for every UI update is unacceptable for performance.
That said, people are realizing that in a very large percentage of practical cases (i.e., CRUD apps), you do not need the high fidelity of javascript and you can skip a lot of the related complexity by using simplified stacks.
The big fail would be if you use htmx at first but over time you end up grafting a bunch of custom JS on top anyway, and your backend is a complicated Jinja mess, which is what made old school Rails/Django projects total messes and caused people turn to SPAs + JSON pumps. It probably takes some discipline to stick with pure htmx and push back on requests to graft random crap on top.
Yes. Like any application architecture, the Hypermedia Driven Application architecture has strengths and weaknesses.
In the case you outline, a canvas-based application, a hypermedia driven application is not going to be a good choice. However, that being said, it may be a good choice for parts of your application (e.g. the settings page.)
Thankfully many SPA libraries are now embedable within an broader application, so you can use that approach when it fits best, and other, simpler approaches in other parts of your application.
You still can write client side only JavaSCript with Unpoly compilers, alpine.js, and probably htmx also has a way to add custom javascript without making jquery spaghetti.
A tool like this that rely on server rendering (or livewire, hotwire, etc) is a perfect replacement for when your user interaction will need to reach to the server anyway (to save data or fetch something, etc).
For example, you're not forced to go back to the server to display a modal. You can have it already rendered on beforehand and when clicking a given button just toggle its visibility.
Or if you want to mark a todo item as "done" you can just apply the "done" styles with alpine.js or similar and make an async call to the backend that will persist the state, etc.
Going full "SPA" just because this is less ideal than state based react, etc does not compensate the overhead of everything else involved in any web application (SEO support, translations, security, authentication, etc) which are incredibly complicated to get right with SPAs.
Specifically this html attribute in the delete button: `hx-delete="/contact/1"`. where the id of that contact is 1 and it is hardcoded as a string.[0]
How do I dynamically generate a list of deletable items?
In react would be something like (simplified obviously) `contacts.map(c => <button onClick={apiDelete(c.id)}/>`.
I dont understand how could I generate dynamic lists without hardcoding Ids... is that a case where I would need to use normal vanilla js ?
Very interesting developing tech philosophy. I was a bit in the js bubble for a while. Its refreshing to see such a simple and powerful idea/tech outside of it:)
Thanks for finding/sharing those links. As I read them they reminded me a lot of what I've been seeing as I have been using Remix (remix.run)
For example: in "how to update content", they discuss path dependent updates. Those are how remix does all it's updates - they use nested routes, so it knows it only needs to update a part of the page (eg only update the content of the page, leaving the nav alone, since an update occured only in the content part of the page)
I think the htmx folks would have a lot of issues with remix but I think remix takes a lot of the best of both worlds. Remix focuses on using basic html/http concepts and layering some smart JavaScript on top of that.
To return the favor, here's a couple docs I found helpful:
https://remix.run/docs/en/v1/tutorials/jokes - this is their advanced tutorial and it's a bit long but once you get past the setup steps it's a really well written introduction to the concepts of remix through useful examples. One of the better tutorials I've ever read.
The key concepts is remix is understanding the loader(), UI component, and action() interactions and how those work with minimal code changes in:
1) server side only mode (with only raw html served)
2) server + smart JS client mode
Just generate these ids on the server. For example, when I render a new field for which I need a delete button, I send numbers of other fields along with them, and server renders a new field for me with a new id.
Thanks for responding. If I understand correctly, then I would need a server like nodejs or django generating and sending the "index.htmx" to the browser and then responding to users interactions by embedding the data from the server inside of the htmx files, correct?
It’s the good old server templates (we use Jinja), and for interactivity I have additional attributes here and there, and sometimes additional endpoints.
It’s miles better than full-fledged JS SPA. I’ve had React+GraphQL app that I’m migrating piece by piece when we need a new feature, and it’s a few times faster to do and easier to understand.
apparently I’ve been doing a lot of HDA, by just placing inline javascript on my html pages, specially where first time to render is essential and interaction not so heavy
I thought it was just laziness from my side of not wanting to set up the whole react scene
Nothing totally new, but it is an attribute based extension of html that allows any element to generate http get/post and handle/target a hypermedia response back into the dom... without the need (but still have the option) to write javascript if you want. You end up writing almost zero js and it's wonderful.
So each HTML element can have a a JS onclick handler (via htmx) that hits the server, which generates HTML, and the requesting page then uses JS to replace the instructed DOM node?
This reminds me of the era before AJAX when we used to POST to a hidden iframe, and then JS in the hidden iframe would update the parent page.
Yes that's about the idea, except since HTMX is somewhat specified there is hope for browsers to implement that natively and therefore empower users, not remote website operators.
I mean this sincerely: can you demonstrate how using React et al for 95% of web apps (not talking about highly interactive stuff, offline-first or other special cases) was at all a step forward for web apps, OTHER than eliminating full page refreshes and thereby improving UX? Nevermind developer experience, although that is more subjective of course. The "decoupling" and "single JSON-based REST API for all clients", etc. arguments are nice in theory but impractical in reality. By all means have a JSON-based API for exactly that - application programming interfaces, not human-consumable interfaces.
I would argue the development, deployment & maintainability complexity of those SPAs can not be justified for most web apps, if you are able to offer the essentially the same UX benefits with an HDA approach.
I love the idea of a SPA without full page refresh. But from experience, the UX of that is terrible! 99% of SPAs i've tried prevented me from using history navigation from my browser, and simply failed in unobvious way when the network wasn't reachable (yeah just keep on spinning without ever loading anything or timing out).
When doing a "full page refresh" my browser has good UX for displaying errors and retrying requests, potentially resending <form> data. SPAs don't have any of that.SPAs is a cool pattern but as long as it is not supported by the HTML/CSS specs (and therefore the browser natively) it will remain terrible from a UX perspective.
By far the biggest downside of this approach for me is that I found out about it in 2020 instead of 2013, when htmx predecessor was created (intercooler).
The hype around reactive technologies in the mid to late 2010s looks kinda funny now considering how much unwarranted hot garbage companies have built with it.
But hindsight is 20/20. Someone may be building a beautiful language that will kill JS in the 2020s, and in 2026 we'll all be wondering why weren't using it in in early 2022.
TBH I think one of the real drivers was just being able to share an API with mobile apps, as 'mobile app for everything' dies down so will SPAs for everything under the sun
It definitely is worth looking into. By reducing complexity around the interactivity portions of an application and all of the dom manipulation, it frees frontend developers to focus more on the aesthetic portion and the user experience itself.
the core idea is to use hypermedia, rather than an RPC-style architecture, and that is, at the least, an interesting alternative approach to consider when creating front end code
Yes, this is not for a front-end developer, this is for all the other people who don’t want to be front-end developers and don’t want to spend months every year to keep up with JS churn.
Since we began using this approach, we can be full-stack developers again. One person can easily implement both parts, which is so much faster.
On one hand, I like the simplicity of it. On the other, I fear it’s a backward move. We loose access to data as, well, data. If you get data from the backend it can be rendered in different ways by the front end. You loose that flexibility with HDA.
It appears HTMX supports non-HTML APIs. The json-enc extension encodes <form> fields as JSON, and client-side-templates allows templating from JSON (and others) API responses.
Now, take my words with a grain of salt because i'm unaware of the details, but i don't see a reason HTMX couldn't support XML with proper schemas which would be great:
- for structured/typed data and ensuring proper API protocol negotiation between client and server
- for data structures closer to the DOM model (which has both fields and children for most elements, while a JSON key can point to a list or an object, not both)
- for serialization formats the browser knows about and is optimized for
- for interoperability with other systems/protocols based on XML schemas, such as XMPP
Data can be served in many forms. Your API could be a DNS key-value server, or a JSON endpoint, or a HTML page. Just because most people don't structure their HTML semantically doesn't mean it can't (or shouldn't) be done, which means you don't loose "access to data as data".
On the contrary, designing your API as semantic/structured HTML empowers users to parse/script your website to better suit their needs, whether that's for accessibility purposes or for developing 3rd party clients. Something that's become almost impossible in the age of SPAs and CAPTCHAs imposing the developer's will on my browsing experience.
Other than returning html responses and the proprietary hyper script format how is this difference from something like API Platform[0]? The unspoken claim is you can’t do the same thing with an SPA yet that shows you can.
There is absolutely nothing proprietary about the format. It's just plain html and vanillajs works fine if that's what you'd like to use. Hyperscript is no different than any other open source compile to js lang.
Can't edit this apparently, so this is what I really mean:
I understand the appeal of what they are laying out here. I'm just wondering why the htmx approach has more benefits over the HATEOAS approach of something like API Platform that I linked to, which doesn't have any opinion on something being an MPA, SPA, or something in between
Also to clarify: I mean proprietary as in proprietary to htmx, this is a poor word choice on my part, no different to how Vue has its Single File Components which are "proprietary" to Vue. I'm specifically trying to understand the advantage of something that ties your APIs to markup rather than using an interchange format such as JSON, as such when building scalable systems it not uncommon to need some form of interchange functionality. Even at a smallish company I work for we need to make sure it is digestible on web, and mobile applications.
I'm just trying to apply some intellectual rigor to the model, as something I do think about is scaling, not say, Instagram Scale, even just something like a company with a 100+ million ARR may bubble these concerns
About API Platform you linked to, the homepage is not very clear (full of buzzwords but little info) but it appears to be a Backend+Frontend framework/distro based on PHP+JavaScript. Compared to that, HTMX is an HTML extension (just additional fields in the markup) which any backend/frontend can implement: even web browsers which don't have a JS runtime could implement HTMX and that's pretty cool.
> I mean proprietary as in proprietary to htmx
I believe HTMX is free software and i don't see a reason the specification can't be implemented by other projects. It's therefore not proprietary in my definition of the word.
> something that ties your APIs to markup rather than using an interchange format such as JSON
HTML/XML isn't that different from JSON. Just like your markup can evolve with your data structures and use-cases, so can your JSON. If you want interoperability, you should probably be using XML/JSON schemas and API versioning.
One issue is that JS builds on large SPA's get tricky to understand because the code is not in the same place as the area of the markup that it's relevant to.
With something like htmx + hyperscript, the logic is tied to the components that are actually using them.
We can easily create endpoints that will respond with JSONs for mobile apps and with partial HTML for our hypermedia-driven application. The code is the same, just in the end check headers and render a template if we need to.