How a hypermedia approach can address usability concerns with multi-page apps
htmx.org
htmx.org
Why yes... if you use Stack Overflow usage as your measurement.
The problem is that doesn't tell you anything about JavaScript or Python... except whom is using Stack Overflow.
As a JavaScript developer (primarily), I use Stack Overflow far less than I did in years past, not just because I need less help in general as a senior, but because SO is so littered with JS answers that are outdated, poor quality, and conflate JavaScript with jQuery, that it's simply not worth using 99% of the time because MDN provides excellent documentation.
It's been a while since I've used Python, so maybe things have changed, but I remember the documentation not being comparable. It's good documentation, but MDN is excellent.
I'm not saying that either one is better, but that to use Stack Overflow trends to prove a point seems very fallacious. By that point I couldn't finish the rest of the article.
> We are fond of talking about the HOWL stack: Hypermedia On Whatever you'd Like. The idea is that, by returning to a (more powerful) Hypermedia Architecture, you can use whatever backend language you'd like: python, lisp, haskell, go, java, c#, whatever. Even javascript, if you like. There's no accounting for taste, after all. Since you are using hypermedia & HTML for your server interactions, you don't feel that pressure to adopt javascript on the backend that a huge javascript front end produces. You can still use javascript, of course, (perhaps in the form of alpine) but you use it in the manner it was originally intended: as a light, front end scripting language for enhancing your application. Or, if you are brave, perhaps you can try hyperscript for these needs.
> This is a world we would prefer live in: many programming language options, each with their own strengths, technical cultures and thriving communities, all able to participate in the web development world through the magic of more powerful hypermedia, rather than a monolith of SPAs-talking-to-Node-in-JSON. Diversity, after all, is our strength.
With JS or TS, it's really easy to have all the same IDEs, CI, testing frameworks — and of course libraries, programming idioms, and the general way of thinking both on backend and frontend.
This makes hiring easier, and hiring engineers is one of the tougher problems in tech companies.
There is a reason why folks writing Haskell on the backend try to compile it to JS for frontend, or go for PureScript. The same reason lies beneath other attempts to write non-JS and compile it to JS for client-side execution. Switching between languages for major components, and between different approaches these languages offer, has a real cost.
With JS being the only game in town for client side, the playing field is heavily tilted towards JS for everything.
(Yes, I know about WASM and about Dart. It's still not it, because they can't directly operate on DOM. It's like using a game engine to write a native Windows or MacOS app: most OS-wide affordances don't work.)
But a large enough proportion of modern web sites need enough interactivity to make even jQuery or even HTMX slightly inadequate.
They argue that JavaScript is still available for its “originally intended” purpose of light scripting, but that using less JS on the front end somehow frees you to use whatever you want on the back end.
But there is nothing inherent to SPAs that would force anyone to use JS on the back end.
And if “diversity is our strength” then I see no reason that wouldn’t be equally true when building JS-heavy SPAs.
I'd also add that the author also failed to notice that all time series in that graph, with the exception of Python, either flatlined or are dropping. Thus that says more about SO and bad data analysis than real world trends in frontend development.
I've gotten a lot of mileage out of ignoring grandstanders and focusing my time and energy on learning how browsers work. If you understand the DOM, CSS and core JavaScript fundamentals, you can apply your skills to virtually any front-end stack.
In the end, the thing that hurts the web the most is complexity in the name of DX. We are tricked into thinking that the simple thing is too hard to learn on the one hand, while being asked to juggle multiple layers of "sophisticated" abstraction on the other. These days there are entire businesses rising on the need to reduce the cognitive load created by our layers of sophisticated abstraction. But, I bring you the good word: you can still build incredible experiences without pulling in most of the complexity (and without sacrificing as much DX as you think).
That is, we've changed our goal from the original page request/response model to one of delivering native-like SPA experiences. But, the frameworks that win don't fundamentally reconsider the old technology. Instead, they stop at the DOM layer, speak heavy HTML/CSS, make us manage browser mechanics like URLs, history and back buttons, and help us to better manage those old Web constructs while keeping them in focus.
So, they've added these abstraction layers that just keep piling up.
At some point we have to ask whether this is fundamentally the right approach.
In other words, it's a demo of what Web performance and usability will be like ten years from now. Twitter and Reddit are already working on redesigning their websites to incorporate this new technology.
(In all seriousness, it's a demo of a subset of Qt compiled to run in a web browser, and it seems to work better on desktop.)
All those shitty restaurant web sites that were forced to become almost useful when flash went away, can rejoice and go back to being as awful as they were.
Great graphics, often great performance. Also, trouble with spell-checking, copy-paste, even selecting text. Often hard to make the layout responsive. Reading mode, screen readers need not remind of their existence. Hypertext links into that are also problematic.
It would be nice to be able to create a new, different platform for hypermedia documents right inside the legacy browser platform from 1996. Sadly, it's not yet there.
Hopefully, those aren't the only possibilities.
>new, different platform for hypermedia documents right inside the legacy browser
I believe there are use cases for which we need to chose between documents and applications.
Currently when people choose it to be an application, it's usually a React / Angular / Svelte application. Purpose-built tools fulfilling their purpose.
Me too! I've written about this on HN more than once and bore myself with it at this point, but the short version is that I'd like to see more alternative approaches that effectively abstract away Web idioms altogether.
React, etc. code could be compiler output, not the code in which we think or write.
By building apps using 100% client-side rendering with GraphQL and Rest APIs, I can use tools like Storybook to build a user interface that are easy to automate testing and ultimately, and consistently, ship enterprise-grade UIs. All my apps are behind auth walls. If need SSR, there's tools like Next.js.
In the end, what makes the work product great has more to do with the team than the technology.
it is a response to a talk that Mr. Harris gave at JamStack entitled "Have Single-Page Applications Ruined the Web?":
https://www.youtube.com/watch?v=860d8usGC0o
in the article I show how a hypermedia-oriented (rather than javascript-oriented) library like htmx can address many of the usability concerns that Mr. Harris raises with MPAs, without abandoning the fundamental REST-ful architecture of the web for a more RPC-like javascript architecture.
I did some experiments around on how to do animated shared element transitions (as well as reactive functionality) within a REST mindset here, if anyone's curious: https://dev.to/eshan/toward-the-postmodern-web-38h (you can just scroll to the embeds)
Ultimately, maybe the browser vendors will do something here, like Google's portal elements, for example. A lot of effort is being spent on that flash during page loads.
One really really nice thing about HTMX is how easy it is to "spruce up" a UI. You say "this part of my website could really do with some active content" and you start thinking about xmlHttpRequest and callbacks and and JSON and all that and you think "does it really need sprucing?". But with HTMX it's usually just adding a couple hx- attributes and maybe a couple serverside lines and you're done.
Another really really nice thing about HTMX is how easy it makes it to make things degrade gracefully. Javascript enabled? Get your beautiful ajax. No Javascript? Get a good experience in the "traditional" model. In anything else I've ever seen, if you want that experience, you need to write your UI twice (and usually in two different languages / models).
So basically it drastically lowers the bar for making nicer experiences on top of a solid MPA. Especially if you're a solo developer, this basically means that you end up producing better UIs "for free".
Also there are some systems trying to do the same thing but using Wasm (e.g. Percy).
On one hand you suggest the culture of complexity is overwhelming, when just a few paragraphs earlier you suggest that sql-tuning and redis caching are how to deal with some of htmlx's problems with latency. That seems highly complex. You have to make deep changes to the back-end and data persistence systems to solve a front end issue.
It feels like the article is trying to say you shouldn't use javascript frameworks in a lot of cases, but then it advocates for using htmx, which is a javascript framework, in those cases?
In my experience the issues people have in front-end come from using tools and frameworks incorrectly, because they don't understand the tradeoffs being made -- so they don't account for those tradeoffs in a reasonable way that eventually comes back to bite the team. Handing people a new JS library that is seeming to intend we completely avoid javascript and therefore the library itself, creating an incentive not to learn how it works.
Htmx isn't a JavaScript framework, it's a hypermedia framework, and they're encouraging taking hypermedia as far as possible before dropping to scripting.
htmx (and intercooler.js, its predecessor which is 8 years old) is a lower level extension to HTML, allowing for targeting specific regions for replacement, using different events for triggering requests, etc.
htmx is closer to hotwire.dev, which 37signals recently released, but again is lower level and a more straight-ahead extension of HTML
But even without SPA frameworks, a boilerplate for a simple project was insane: linters, assemblers, template frameworks, etc.
With React it was one notch more boilerplate, and yet after all that you had to write pretty much all the interactive UI still on your own.
Using HTML to drive an app's interface has nothing to do with the tech stack, in fact, I think it opens the door to a more diverse tech stack. Optimistic UI updates, state management, and other "modern" JS techniques are cool, but often, the complexity is not worth it.
Also, let's not forget that web browsers are already good at taking HTML/CSS and showing it in your screen. Somehow, we decided it was better to make all your users waste CPU cycles to do the same with Javascript and a Virtual DOM (but only after 10MB of JS files have finished downloading)
[0] https://developers.cloudflare.com/workers/examples/return-ht...
The layout mechanics are complicated. DOM is slow and non-transactional which means jumpy redraws and jank during partial updates, and you just can't render it at 60 fps, or even 30 fps, like you would with a direct-mode game-style UI; at best you can peg several CPU cores to 100%.
And this can never be fixed because backwards compatibility. It can only be replaced in some indefinite future.
This is why the virtual DOM was invented. And yes, if you know how to cook it, it's faster than jQuery.
OTOH great many web pages are not apps, and should not be treated as SPAs. But this happens, and it will until server-side rendering is made ridiculously easy to set up, and also becomes the fashion.
It's DOM diffing anyway. It's still the "track and update dirty regions" logic of 8-bit game consoles, instead of the "redraw the whole screen from scratch" logic of modern game engines. DOM is not performant enough, and likely will never be, in its current shape.
Merging the vDOM-less transactional DOM update logic into the DOM standard could be nice, though.
I built my own (proprietary for my employer) general-purpose AJAX etc framework that uses minimal javascript to produce flexible, interactive web sites with 1/100 the bulk of React. It even degrades gracefully for clients that don't run JS. But I'm tired of maintaining it. HTMLX looks like an even better approach because it doesn't seem to require me to add explicit event handlers all over the place and it's open source so I won't be the sole maintainer.
Looking forward to evaluating HTMLX as a replacement for my stuff.
Anywayz, I’m loving htmx and I’m pretty sure it is making my development faster. I don’t know, yet, if it will degrade for larger applications.
I actually attempted to make a "simplified" "js" framework (where you just had some html tags and it did things for you) for tasks congruent to alpine (since I found alpine rather complex, or that it comes with so much but you still have to do a good amount of work to get things working) but I'm not as savvy; using the DSL you all have in hyperscript is real smart, simple.
Not too long ago I looked into using Svelte for a one-off project (since it was the highest rated framework at the time) which then prompted me to look into the current state of web development.
It's absurd, and left such a sour taste that I just shelved the project for another time.
Great stuff you guys got going here, it makes me excited to see what'll turn into in the future! Looking forward to trying this out later.
SPAs might be the right approach for specific applications that are actually applications (e.g. text editors, Jupyter notebooks, chat and other web apps) but more generally the web is designed from the ground up to work well with separate pages representing separate resources.
Each keypress would direct you to a new URL derived from a hash of the new text, an approach that takes advantage of browser history to provide a built-in undo function. Fans of this “content-addressable text editor” say it reminds them that writing is ultimately a grand exploration of Borges’ Library of Babel.
For example, here is a fully functional Svelte component:
``` <h1>Hello world!</h1> ```
And here's another one that adds a bit of design:
``` <h1>Hello world!</h1>
<style> h1 { color: red; } </style> ```
I wouldn't call it particularly hard!
The web is a platform and we should not treat these tools as one-size-fits-all. Use the tools that fit your use case; there's no use in talking about the how without the why.
As an example, I don't care about bundle size at all. A given app might have a hundred users all on desktop loading from an internal network. I will happily add a few MBs to the bundle if it increases the development velocity of my team.
I'll also note that htmx is making a programming language, but they don't seem to understand they are making a programming language, and that usually ends up a disaster. See all the YAML stuff in the devops world.
Rather, we are making two programming languages:
I agree with the general sentiment though. I think the issue is that it’s easy to just import the whole npm registry in a bundle and ship it — and it’s too hard to trim it down.
For you a 2MB bundle is ok, but for me it’s taking 30 seconds to open this site and I’m standing here. That’s not ok.
Frameworks like Next.js provide a sane base for this; Most others don’t.
That said, the one criticism I can lob is toward the assumption that JavaScript / TypeScript will be the only path for SPAs, creating a full-stack monoculture. Web Assembly is on its way to negating this point long term.
I don't think this affects the position on MPAs, but weakens that one particular argument against SPAs.
For instance, with infinite scroll - I spend 10 minutes scrolling down through 7000 rows, with all but the first few loaded dynamically.
I now want to send what I'm looking at to a friend. Or I want to bookmark it. Sure, I can have my app put the scrollposition in an anchor tag in the URL, but what happens when that URI is navigated to? Whatever solution you pick, it is horrid.
https://github.com/unpoly/unpoly/blob/4854c7ccb268890a9522c6...
and it uses several X-HTTP-Headers, which could be standardized.
Do any browsers have the early workings of a "native web application sdk"?
in this article we respond to specific criticisms of MPAs in terms of htmx, as it is a response to Mr Harris's talk
i think you are missing the hypermedia vs. RPC aspect of the discussion, and the javascript-everywhere vs. Hypermedia-On-Whatever-you'd-Like aspect of it, which i believe are relatively unique in the discussions i have seen
but, it is fair, both laziness and self-promotion are forever a danger for me
A sibling comment offers a perhaps useful comparison:
> We have been asked for our opinion on the talk, so this essay is our response
I had the same question, answered by the above.
"We have been asked for our opinion on the talk, so this essay is our response."
I was writing something like htmx without intercooler with Angular with Django (which I fondly called Djangular) in 2013.
It just needed yet another framework type abstraction to reduce the boiler plate.
Send json with the html on initial page load, use the json api to load addition data, hard navigate between "sections" of the app but tabs and such were SPA pattern.
I think a middle ground combo of svelte and htmx is a killer idea (similar to all the "live view" stuff people are loving).
The difference between us on that matter would be that I would recommend leaning hypermedia, whereas, at the risk of putting words into his mouth, he would appear to lean SPA/RPC as the default approach.
Isn't the default essentially @svelte/kit now? That's got SSR built in and a preloading layer that's much closer in nature to HTMX than to an SPA framework. RPC just happens to be the easiest way to abstract out data for static sites, SPAs, and runtime SSR.
Another issue is how browser cache 404, for SPA app, the "known" routes are stored in main.js rendered in browser, the nginx doesn't know which page is not defined, so every page is 200 and then rendered 404 in browser only, the browser would still cache the "wrong" 404 page because nginx has to serve index.html with main.js as 200 first.
The first thing being, 95% of what I do on the web doesn't need to be an SPA. Most of what I do is content consumption. HN doesn't need to be SPA. NewsReading doesn't need to be an SPA.
The second thing being once you allowed developers of SPA, and break free of the browser default usage pattern, there are very few SPA I have used that I even considered to be decent. Actually there is only one, Feedly. And yes, as pointed out in the video, even instagram cant do the basic right. Not Facebook web, and not Twitter. Look at new Reddit.
The problem with SPA is once you try to make a Web App, aka Reddit, I will instantly try to compare it with a Native App. And I have yet to see a single decent Web App that compares to "average" native app. It is far easier to make a very decent MPA with added magic like HTMX or Hotwire than a decent SPA.
The third being transitional design. Which is a compromise or taking best of both worlds. Interestingly HTMX or Hotwire are also considered as Transitional, since they try to make the those web page that needs a little more interactively without switching to SPA.
There are some things that are better for SPA, so far most them for me tends to be financial tools and graph based.
One argument for SPA is that your backend is just an API, your front end could now work not only in browser but even compiled natively into Apps. But so far none of them worked flawlessly across all platform without a team of expert.
And for simplicity, PHP is still by far the best in modern web backend tool kit. I am not advocating for PHP, I hate the syntax but other than that it is dead simple to use and set up. Considering both Hotwire / HTMX with Django and SPA camp with Svelte just shows how little the vocal web developer community value simplicity.
For REST APIs one can use Nest.js or so to get a similar experience.
hyperscript, our other project, is a more direct competitor w/ alpine:
What about an SPA that made internal requests to a server backend, running in the browser?
Strange place to post such a … misguided stance. HTMX regularly brags about how it’s meant to be used to mutate the DOM the user already has loaded, thru custom HTML attributes handled by their JS framework.
You’re just arguing in favor of HTML, but HTMX is trying to have their cake and eat it too. JS-level state is clearly easier to manage than DOM-level.
Is CPU cheap? I can literally host a static site or SPA on GitHub Pages for free. Where can I get free CPU time for an htmlx application?
whatever can serve that can be used with htmx: it is intended as a straight-forward extension of HTML
Cheap != free, but the large cloud providers all have a free tier.
The core behavior of a SPA is that it loads pages via ajax and just replaces content in the current “document”. The difference between a simple SSR React site and this is that React will only fetch JSON and templates after the first load, whereas this one fetches whole chunks of HTML.
An htmx site still has to deal with all the pitfalls of SPAs, namely non-native navigation and history, and memory leaks.
Just like htmx may have solved some of these issues, a (other framework) SPA can do too.
the core difference between htmx (and hotwire, unpoly, etc) and most SPA frameworks is that they stick closer to the original hypermedia model of the web, thereby saving a lot of complexity and additional abstraction
> This is, unfortunately, part of the culture of front end development right now: sky-high levels of complexity are tolerated in application frameworks, in build tool chains, in deployment models and so on, and, when problems arise due to all this complexity, more complexity is often offered as the answer.
> "Simple" is disparaging and "sophisticated" is high praise.
So, rather.
There was a series of similar Twitter discussions when a popular JavaScript "influencer" published an article[0] on how they built their website. The amount of complexity that is self-inflicted in the said article was obviously enormous for proponents of MPAs.
However the JS community mostly echoed that the complexity was absolutely within norm. The cultural chasm between JS developers and people who push for simplicity was huge. And the refusal to admit the unnecessary complexity was nothing short of Stockholm Syndrome, imho.
[0] https://kentcdodds.com/blog/how-i-built-a-modern-website-in-...
This was the HN reaction to the article:
I've been working recently on two code bases: one using angular and the other htmx (with python/jinja2/FastAPI). Both aiming to deliver broadly comparable interaction - so approximately comparable in essential complexity.
In a month, or a year, I'm confident I'll be able to check out the htmx app and work with it pretty much right away. The dependencies won't have changed much; the build will still work; and I'll be able to understand the code. I will lay bets now that the same will not be true of the angular app. On any one of those three counts.
If simple, understandable, stable and effective are what GPP meant by "primitive", then I want more "primitive" tools like htmx.
Light sabres, not death stars.
Yet another cheap shot. Might as well say 'fu js devs'. How come every time we have a thread on this thing its devs and supporters always come across as arrogant, bitter folks with an axe to grind.
I don't like your technology. I didn't like it several years ago when I was introduced to it, and I don't like it now. It's not a bad idea but calling me an idiot for not doing UI on the backend is not going to win over anyone that doesn't already hate js and the people who write js.
People seem to act like those problems just "go away" when you don't do SPA but it doesnt.
It seems the backend community mostly echoes that the complexity is absolutely within norm. The cultural chasm between backend developers and people who push for simplicity is huge. And the refusal to admit the unnecessary complexity is nothing short of Stockholm Syndrome... imho
You don't need jumbo jet to deliver pizzas locally.
I'm not saying that all sites need to migrate to SPAs but there is a HUGE market segment that has been replaced with a React SPA over custom apps that had to be downloaded. And now those same SPAs work in your phone and your computer.
HTML POST REDIRECT HTML is dead, get over it.