The Future of Htmx
htmx.org
htmx.org
It’s really quite buggy, in my experience it plays poorly with fundamental web and browser features (relative links are broken in at least 2 ways, I fixed a third way). One of the events just stopped working at all in the most recent release. The docs are lacking. And where it promises to let you write less JS, if you ever do need to write some JS you’re on your own in structuring that, and you’ll be fighting against HTMX (who gets to update the DOM, maintaining event handlers, etc).
As a (brief) contributor to HTMX, I also feel like these issues were all inevitable. It’s a single 5k line file with 190 top level functions in it meaning it’s pretty impenetrable to get up to speed on. When proposing a bug fix the maintainers weren’t sure if it would have other consequences. Tests didn’t cover the functionality. I’ve been mostly a backend engineer in my career, and I empathise with not wanting the complexity of a modern frontend, but that doesn’t mean we can’t have some basic organisation of the code to make it approachable and more obvious whether changes will work or not.
After porting to Turbo and Stimulus I have a more reliable code base, I have significantly less JavaScript, and I have a JS code base that much easier to reason about. I really wanted to like HTMX but the execution is not there. A focus on stability is a great fit for the project, but it’s most certainly not there yet and has quite a way to go in my experience.
HTMX had no issue, tho
Library availability has mostly not been a problem for me, there are some really high quality libraries, particularly open source ones from Apple. Quality is high compared to other ecosystems.
I'm targeting Linux/Docker for deployment and while I don't have the project running in production yet, I've been running CI builds and it so far seems fine. It's fairly clear when things are Linux compatible and when they're not. Most things you'd expect to be are compatible. Some third-party libraries are accidentally not Linux compatible, but it hasn't been much of a problem for me.
The new Swift Testing library is really nice, and I'm using that for all my server tests with no real problems. Vapor could have more testing support (Django's is excellent and my bar for comparison), but it all works.
Overall it's just a lovely language to work in, and I'm enjoying server side development with it.
I would love to know in what other two ways relative links are broken, and which event stopped working, so we can get those fixed. With respect to the fix you PRed (thank you, by the way), we did get that merged very quickly, and would love to do the same for whatever is broken here, even (especially) if you are no longer interested in doing the fix yourself. [0]
As for the DX of making changes to htmx: absolutely true! The single file is a DX we've chosen, and it has both costs and benefits, which we've written about in "Why htmx doesn't have a build step". [1]
* Note to non-JS hackers: JS module symbol scope is per-source file.
We generate esm and cjs modules for people who want to use htmx in that manner though:
an aesthetic decision, I suppose
(Which is why bundlers still exist.)
The relative link bugs are [0] and [1], and I fixed [2]. My fix was merged quickly, but the other two bugs of what appears to be similar significance, have been open for well over a year each. My issue however is less about these specific issues, and more the general lack of support for hypermedia, which speaks to a general state of HTMX not living up to its promises.
As for the DX, I think not having a build step, and code structure, are somewhat orthogonal. I agree with much of that essay, but most of it is about issues with complex build systems and the use of Typescript. It's not about having 190 top-level functions, which, with all due respect, I think indicates a lack of architecture. Again, the issue is less about the specifics, and more about the fact that HTMX is not living up to its promise of simplicity because of how impenetrable the codebase is in this regard.
As mentioned, so far I have found Stimulus and Turbo to be better implementations of what HTMX appears to promise to be. More activity in this space from anyone and everyone is great here though!
[0]: https://github.com/bigskysoftware/htmx/issues/1476 [1]: https://github.com/bigskysoftware/htmx/issues/1736 [2]: https://github.com/bigskysoftware/htmx/pull/1960
They're sectioned off, so "event/log support" and "AJAX" and such are grouped by the type of method, but they're not prefixed so there's no way for your editor to help you explore grouped functionality.
Given that the code isn't particularly organized or structured in any way that I could quickly glean (aside from the aforementioned grouping of related functionality, which is only so helpful), I think I'd be put off from wanting to contribute to this codebase.
I haven't looked deeply at HTMX, so I won't claim they're falling prey to this exact problem. But it's definitely a code smell that's concerning.
https://htmx.org/essays/codin-dirty/#i-prefer-to-minimize-cl...
A lot of functions doesn't necessitate a lot of things to hold in your head, but in my experience, HTMX hasn't got enough other structure to prevent this. I was not confident about the changes I made, and the reviewer was not confident about the changes. In a well architected codebase the goal is for these things to be obvious.
As for minimising classes? Sure. I can get behind that. But I think it's orthogonal to having a lot of top level functions with no clear naming or sorting.
If the goal is to have a single-file codebase, I'd suggest considering the following (you may already have done so, but I haven't noticed consideration in the few documents I've read):
- Structuring the file into clearer regions – there is already some of this, but comment blocks are easy to miss in a 5.2k file, and utilities are everywhere.
- Adding named closures for grouping related functionality – "classes lite", at least gives some function namespacing and code folding.
- Ordering the file to help direct readers to the right bit, literate-programming style, so that there's a sort of narrative, which would help understand the architecture.
- Function name prefixes to indicate importance – is something the entrypoint to core functionality? is it a util that should be considered a sort of private function?
- Pure functions – so much of the code is state management performed in the DOM, which makes it hard to test, hard to know if it's working, hard to know what interactions will be introduced, etc. State management is always hard, but centralising state management more would be good.
- (That said... arguably library internals are the place to have make the low-abstraction high-performance trade-off with a bunch of mutable state. However, this makes it hard to have other Javascript that co-exists with HTMX, because it's too easy to stomp over each other's changes. A better integration path, like Stimulus, might alleviate this and retain HTMX's control over the DOM).
- I understand the preference for longer functions, but `handleAjaxResponse` is a lot. More abstraction would really help make this more understandable.
I get that personal preferences are key to why HTMX is the way it is, but I think it's important for the general health of open source projects that others are able to contribute, safely and effectively, and I'm not sure the current choices are most conducive to that. Hopefully some sort of middle ground can be found where HTMX doesn't lose its "personality"(?) but where some of these things can be improved.
We have other people contributing on an ongoing basis and i've had people (mostly non-JS people) comment on that they find the codebase easy to navigate, since you don't have to rely on IDE navigation.
There isn't a lot of state involved in htmx: it's mostly passed around as parameters or stored on nodes. History, where you ran into a problem, is a tricky part of the library that's hard to test, and that's where most of the problems have cropped up. I could probably factor that better to make it more testable, at the cost of more abstractions and indirection.
In general, I'm not inclined to change the organization much (or the codebase, per the article above) so that we can keep things stable (including the behavior of events, which apparently changed on you at one point.) I'll sand it, but I'm not going to do a big refactor. We've had people come in and propose big changes and reorganizations, and we've said no.
https://data-star.dev is a result of someone proposing a big htmx rewrite and then taking it and doing their own thing, which I think is a good thing. htmx will stay boring, just generalizing hypermedia controls.
I did a walk through the codebase here:
https://www.youtube.com/watch?v=javGxN-h9VQ
Given the lack of API changes going forward, I hope that artifacts like that, coupled with overall stability of the implementation, will mitigate risks for adopters.
Maybe the sanding will help, and if HTMX is not going to change much then maybe not much is needed, but I think there's still a way to go to stability and feature completeness.
> https://www.youtube.com/watch?v=javGxN-h9VQ
Thanks for the link, I'll definitely give this a watch!
https://htmx.org/essays/codin-dirty/
htmx is feature complete (see the article)
we can argue about stability, but we have lots of happy users
Thanks. Genuinely asking something here: are relative links actually common in frontend? I've only ever used absolute URLs for static assets. Actually I even made tooling that ensures that static asset paths will always be correct: https://yawaramin.github.io/dream-html/dream-html/Dream_html...
Of course, this kind of tooling exists for many frameworks. But I've never seen frontend frameworks suggest using relative links for static assets, they always seem to put them in a separate subdirectory tree.
Besides that, they are a very basic part of the spec, and I consider anything that breaks them to be truly fundamentally broken.
(edit: I should clarify that I'm mostly working in Go these days, and all my assets are embedded in the binary as part of compilation. That does make some of this much easier to deal with. Javascript-style build mechanisms tend far too much toward "complex" for my tastes.)
The link gens inherently accept relative paths (foo) and output relative links with appropriate adjustments (foo.png?v=abcdef), though they can generate fully-qualified links if circumstances warrant (eg I often have a global shared css file for theming, though that's all I can think of offhand other than "/" for back-home links). The module can then be mounted under /bar/blort, or wherever else, and the links remain relative to wherever they are mounted.
On occasion I do hardcode links for whatever reason; my rule of thumb is relative links for same level or deeper, or root-anchored if you're referencing a global resource outside the current path, but there aren't many of those in my apps. A rare exception might be something like an icon library, but I tend toward font-based icons.
To put the rule more succinctly, I never use "../foo". Going up and then over in the hierarchy strikes me as a recipe for bugs, but that's just instinct.
I also never use fully-qualified (including hostname) urls to reference my own assets. That's just madness, though I vaguely recall that WordPress loves to do crap like that; there's a reason I don't use it anymore. :)
So the main difference if I understood your link correctly, would be that I would have maybe one or two items in /static/assets by root-anchored urls, and the rest accessed as /path/to/module/assets/whatever (edit: or just assets/whatever from within the module).
Because I'm doing this in go, the module's assets live where the code does and gets embedded in a reasonably standard way. I actually tend to use git commit as my cache buster to avoid having to hash the content, but full hashing can be done as well very easily just by changing the generator functions.
I can then just import the module into an app and call its associated Route() function to register everything, and it just works. Admittedly it's very rare that I reuse modules between apps, but it's easily possible.
For background to my thought process, I originally started using the link gen paradigm long ago to make it easy to switch CDN's on and off or move between them, back before whole-site proxying was considered best-practice. The rest is just a desire for modularity/encapsulation of code. I like to be able to find stuff without having to spelunk, and keeping assets together with code in the source tree helps. :)
> and which event stopped working
It was `htmx:load`. On 1.x this fired on first page load, which I used to do a bunch of setup of the other little bits of JS I needed, and which would cause that JS to re-setup whenever the page changed.
On 2.x this never fired as far as I could tell. Maybe I got something else wrong, but only downgrading to 1.x seemed to fix it immediately, I didn't investigate further.
I did wonder if there were breaking changes in 2.x, but as far as I could tell from the release notes and documentation there were not.
Which leads to the appeal of HTMX. It promises no other dependence. It just does exactly what it advertised. I'm not sure whether your issues were due to implementation or specific known bugs in HTMX not covered.
I am curious to know more about Hotwire, I'm just worried about state management and this is greatly overlooked when it comes to adding application logic beyond just hydration of specific components on page.
So far I have not seen anything that competes with Sveltekit.
Personally I'm using Hotwire (was using HTMX) with a Swift backend with no issues.
I have backend solutions and existing databases and existing backends. I would never consider a Js backend in a production app to begin with, despite the benefits an isomorphic approach offers. I dislike when physical actual boundaries in code execution contexts are obfuscated, for one...
But not everyone is building SPAs, and my dev server is my actual backend, thanks
Yeah, Svelte5 said "away with these pesky svelte users, lets market to React devs and make everyone realize that Vue3 has a bigger ecosystem, since you are gonna have to do a rewrite anyway "
Basically the opposite of this principled stance here on this htmx missive
Frontend framework churn costs money and lives
We started using react a couple of years after hooks were introduced when there were millions of ready libraries, all major design patterns were established, tons of docs were written, etc., and although there's still major churn, it's nothing like it was when react first came out.
I looked at svelte when the hype circle started and decided to postpone using it for at least five years — these comments show it was a right decision.
It saves money and time to be conservative with these things.
That's interesting. Do some people prefer this style? If yes, how come?
But the htmx.js file itself seems to struggle from a certain type of internal naming scheme that will take a while to get up to speed with and doesn't really lend itself to being easy to context switch in & out of it, where you might simply forget that things exist and end up re-writing or inlining these fragments.
This naturally stems from a very organic development process, where something starts out as a quick prototype, then the functions get too big so you split fragments out into things like `shouldProcessHxOn` and `processHXOnRoot` which absolutely make sense at the time where you're avoiding duplication, and trying to turn it into something 'more proper' with 'better abstractions' would actually cause the code to balloon in size and make it much bigger and much more like object spaghetti.
On the whole though, a large amount of the file is type documentation, e.g. `/* @param {Node} start */` which is more a failing of JavaScript itself than anything else, and honestly a 5k self-contained file with good public documentation of what's user-facing vs internal is pretty easy to grok if it's something you work with frequently.
If you were to rewrite this in a saner language like Python with a more functional style, you could probably condense it down to 1000 lines or less.
Also, having all the code in a single file helps expression exposition of the code. You can sort of captivate the reader of your code, and present the code in the order of your choosing.
This is the way.
Having lived the alternative, I won't consider building anything significant on top of an abstraction that doesn't credibly promise these.
When the abstraction you've built on changes or fails, the thing you built breaks. When you choose an unstable abstraction, you're creating future bugs you'll have to spend future time on to resolve (and if it wraps the lower layer rather than sitting beside it, you have fewer options to fix them).
These aren't concerns for things that will be short-lived, or are small enough to replace if needed. But I've seen plenty of small and temporary things turn into large and permanent things when they end up being useful.
Given my experience with node ecosystem, react, and nextjs, I am inclined to agree.
But the node ecosystem includes essentially everything that touches on javascript, both the bad and the good.
I don't think there are very many ecosystems that are guaranteed to have only good stuff. Regardless of ecosystem, the developer has to examine what is available and make wise choices.
There are exceptions, but at this point the verdict is clear. It’s like the meme about Java being enterprisey and over-abstracted with factories. As far as stereotypes go, it’s true. (Or was, haven’t used it in forever)
I’m not even against JS, and much less the web. I think it’s the 7th wonder of the world. But the developer practices makes me want to tear my hair off.
If Svelte version 4 and 5 are very different, then they're "SvelteV4" and "SvelteV5", both on version 1.0.0, in my mind :)
I won't touch it if I can help it. No matter how good it is, I'm fairly certain there will be a svelte 6, 5 will be abandoned, and whatever issues crop up in it will not be addressed unless I move to 6... probably just in time for 7 to come out. I know this because that's what happened before, repeatedly.
I don't know if htmx is actually any good, but they are saying all the right things.
Not to me.
I know there's plenty of junk, but if you opt out of the node ecosystem in its entirety, you're essentially opting out of most of javascript development as well, which is a substantial part of web development.
That's your choice, but you're missing out on a lot of good and useful things... just in terms of software development but also in terms of meeting whatever your business needs are (if you're trying to make money).
Javascript static analysis tools can be very useful (like TS and eslint). app frameworks can provide routing, UI frameworks, UI controls, validation libraries, etc. that you would otherwise have to implement on your own.
These are all part of the node ecosystem. htmx is part of the node ecosystem. IDK, lumping it all together doesn't make sense to me because there's a lot lost and little gained.
I'm also not sure whether the move from class- based components to functional components with hooks should've been part of the "regular" React or if it would've been better to do a hard break (e.g. a version 2.0), but I think the collective front-end developer world is still traumatized from the AngularJS -> Angular transition.
Yes, it's not perfect but right now it's pretty good. I like composables, there are a few gotchas to get used to, but that's everywhere, when in Rome.
Vue is better IMHO, but doesn't have the graphql client I require and there is more momentum in the React ecosystem right now. More innovation is happening in the React ecosystem than elsewhere.
Angular is still stuck in the past. Ngrx as the only state management library, full of boilerplate and the annoying rxjs. One doesn't simply with Angular.
Svelte is too barebones for my taste. Manually doing form validation and rendering for instance. If it had a larger ecosystem it would be great, but it doesn't. It for the purists who like reinventing the wheel. Of course it has other good uses as well, it's fast, much faster than React.
When I used React, I use high level libs where I don't have to manually do stuff. But when I do it comes naturally, it's a simple learning process.
I prefer logic in templates from Vue over the brackets and conditions of React. I like Angular's templating and 2way binding. I don't like Reacts aliases, like having to write className instead of class.
But in the end productivity is what matters for me, and React is pretty productive and has a large ecosystem. But finding the right packages is a journey.
React SSR is a horror story. Vue's especially with Quasar is a love story with butterflies and perfume. Great tooling.
It's good enough and I'm actually enjoying to work with it, maybe because it's so new to me and learning new things makes me happy (like when you're young you're happy because there is so much new stuff constantly, which studies found that it makes people happy).
That they removed the ability to embed it without compilation from v19 on is a very bad move though.
My experience is that probably more than 9/10 temp projects end up forever projects. My goal is never to work anywhere again that insists on just get it done quick and dirty "its temporary" ever again.
1. If you consider yourself a "backend developer" only and want to write the minimum amount of JS/TS.
2. If your application is simple. Yes you can do more complicated interactivity with oob swaps, but you end up with more complexity than you chose HTMX for.
For my next projects, I will still use Django but with React/Vue for pieces that need interactivity. As an example in my HTMX app, I wanted to add a profile image uploader. Lots of great frontend libraries exist to resize / modify your image before even uploading it to your server.
Finally, HTMX is just not testable the same way modern frontend libraries are. I've managed to write some decent tests using beautifulsoup, but it's night and day compared to vitest or jest.
For HTML tests, if you target elements by their ARIA role, semantic tag, or by matching against the text/label/title the user would see, it should be robust to a lot of presentation changes (and does some accessibility checks too). It's much more robust than e.g. `body > div > div .card > h2` which are sure to break in tests and slow you down when you make changes later.
See Playwright locators for example:
https://playwright.dev/docs/locators
Not sure if this is what you meant, but you can't rely on only the JSON because you can't assume it's been properly transformed into the expected HTML.
One property of good tests is that they only fail when something is broken.
Snapshot tests aren't really automated tests, because you have to manually check the outputs to see if failures are genuine. It's a reminder to do manual checking but it's still not an automated process.
> The best testing technique in the world can't save us from developer error.
Sure, but using a testing technique that increases developer error is unwise, and snapshot testing has done that every time I've seen it used, so I don't use it anymore.
Then fix the test so that it fails only when something breaks? Do people not fix flaky, overly broad, or incorrect unit tests? How is a snapshot test any different?
Any change that modifies the rendering of any component under test will break snapshot tests. It's literally just a test that says, "Is this render function still the same as it used to be?"
Eg in htmx we can add a snapshot test for the pagination component I mentioned in this comment: https://news.ycombinator.com/item?id=42619553
This snapshot will break if I have a bug in my pagination logic implementation, and it's highly unlikely to fail for random irrelevant changes.
> If you have snapshots that are breaking for irrelevant changes, then by definition those changes don't need to be snapshotted, do they?
You're so close to getting it.
How often? All the time? Or relatively rarely? For most projects, it's the latter. We are not constantly churning the styling.
> Need to add a new hx-attribute? The snapshot breaks. It's not tied to the logic
An `hx-` attribute is logic. That's the point of htmx.
> You've reduced the surface area of the problem, but not eliminated it.
That's a risk of any kind of unit test. You can always have false positives.
> You're so close to getting it.
That tests should be fixed until they're robust? I'm not a fan of the learned helplessness of the 'We couldn't figure out how to do XYZ, therefore XYZ is a bad idea' approach.
If you introduce a new feature and have a new button on the page, for example, the snapshot test will fail (by necessity, you're changing what's on the page) because the snapshot doesn't match the current version with the new button, for example. So, what you have to do is regenerate the snapshot (regenerating it will always make it pass).
The problem is in my experience, that these kind of tests are massively unreliable. So you either fiddle with tolerances (most testing libraries let you set a threshold for what constitutes a failure in a snapshot) a lot, or you manually have to hunt down and pixel peek at what might've happened.
As an example of what usually happens is that, at some middle step of the test an assert fails because some new code causes things to render slightly out-of-order or delayed in some way. Ultimately the final product is good and if it was an intelligent system it would give it a pass. The unit tests pass. Even the integration and E2E tests pass, but the snapshot tests fail because something changed. The chance that this test failure is a false positive is much, much higher than the chance of it being a legitimate failure, but let's assume it's legitimate like the good citizens we are and try to hunt it down.
So, you go through the snapshots, 1-by-1, setting breakpoints where you think things might break - note that this process by itself is painful, slow and manual, and often running snapshot tests on your local machine can break things because things get rendered differently than how they would in CI, which leads to an extra set of headaches - What happens here is that you're testing an imperfect reflection of what the actual underlying app is, though, because a lot or most of it will be mocked/hoisted/whatever. So sifting through what is a potential breakage, and what is just the quirk of the snapshot test is basically a gamble at best. You spin up the app locally and see that nothing looks out of the ordinary. No errors to be seen. Things look and behave as they should. You have your other tests, and they all pass. So, you chalk it up to a false positive, regen the snapshots, and go on with your day.
The next day you add some other thing to the page. Uh oh, snapshots fail again!
Rinse and repeat like this, and after the 50th time sitting there waiting for the snapshot to be captured, you decide there are better ways to spend your limited time on this mortal plain and just say "Fuck it, this one's probably a false positive as well" after taking a 2 minute look at the page locally before hitting the repacture command again.
I legitimately don't think I've ever actually seen a non-false positive snapshot test failure, to be honest.
As an example - the different browser you have running locally and in CI? That's a bug. The fix is to run the browser in a container - the same container in both environments. You can probably get away without this with an E2E test. Snapshot test? No way.
Ive seen people decry and abandon E2E tests for the same reason - simply because they couldnt get flakiness under control and thought that it was impossible to do so.
I dont think it's intrinsically impossible though. I think it's just a hard engineering problem. There are lots of nonobvious points of flakiness - e.g. unpinned versions, selects without order bys, nondeterministic JavaScript code, etc. but few that are simply IMpossible to fix.
Theres a big payoff if you get it right, too.
The problem is that end to end tests are the hardest kind to write. At least if you have a frontend code base you can have some tests there and get some confidence about things working at a lower level.
Only using the standard Django test client? I don't find this myself when I've had to work with HTMX code e.g. if you're using HTMX for your sign up form, it can be completely broken on the happy path and on form errors if the HTMX attributes are wrong, and the standard Django test client won't let you know, so you lose a lot of confidence when making refactors/changes.
One addition makes it an order of magnitude more versatile: a way to visualize non-textual information as text in the tests. For example add a data-test-icon attribute which contains the replacement text that should be shown in tests. Another method is to parse the HTML and write custom visualization for some elements, so that you get useful default visualization for at least form elements and such, without having to repeat the data-test-icon attribute every time.
See https://martinfowler.com/articles/tdd-html-templates.html#Bo...
Seems very brittle and may not catch actual regressions browsers introduce.
They're both fantastic expansions of what server-side rendering can do. They can't really do work as nice as what React can, but you can get perhaps 85% of React for 5-10% of the development time. And a big increase in usability of your app.
This is a great point and should be underscored more. I think generally the HTMX vs React/Vue/Svelte argument gets undercut when people don't express their innate bias on which part of the stack they want to give more control to. HTMX is great if you're pro-expanding the server; JS Frameworks if you're trying to expand it from the application layer.
For example, error handling in complex forms. When you have React handling errors you simply return a 400 JSON response with fields and reasons, or some other error message, and React decides what to do depending on the context, which it knows. When this responsibility is moved to the backend you now need to track the request location, state etc. and find the right fragment, which very quickly turned the code into a mess.
I think the choice of backend is also important. I suspect that Java (Spring Boot) made using HTMX much less pleasant than it would have been with something else, especially when it comes to templates and routing. Using Java for HTML templates (Thymeleaf or any of the other popular libraries) is something I will never do again.
Edit:
The analogy with jQuery is interesting. I feel the same way about HTMX now as I did about jQuery ten years ago. I used to plug jQuery into every project even if it was just to select elements or whatever, but whenever I used jQuery entirely over the frameworks that were popular at the time (Ember, Angular) I ended up with way messier code.
Maybe not? I'm just returning a 422 JSON response with fields and reasons and I have a tiny bit of JavaScript in the frontend that just plugs them in to the form with the built-in Constraint Validation API.
https://dev.to/yawaramin/handling-form-errors-in-htmx-3ncg
> I suspect that Java (Spring Boot) made using HTMX much less pleasant than it would have been with something else, especially when it comes to templates and routing.
I strongly agree with that and created a library to help with those aspects: https://github.com/yawaramin/dream-html?tab=readme-ov-file#f...
What's your plan for "plugging" these into your HTML? Web components?
Does Django have some kind of integration with Vite for hot reload during dev?
If I was to write tests, it'd be basically http get/post/put/delete requests and measuring the responses are what I expect.. how can HTMX be any different here ?
How do you "test" a button works without a browser engine ? Every browser engine ?
https://github.com/jsdom/jsdom
https://github.com/capricorn86/happy-dom
but they're about as reliable as you can expect: it's difficult to keep up the pace with the big three (or two) on standards compliance, and they usually don't even try.
So the only reliable solution is a headless Chromium, Firefox, and/or WebKit-based noname browser like the sibling says.
I'm interested in using it more, but I want to be 100% confident that I understand how to get htmx sites to work well with screen readers. I worry about things like fetching new data into a page not altering the screen reader user in the same way as refreshing a page completely would.
I'm not interested in whether or not htmx uses the correct ARIA attributes - I want to be confident that those ARIA attributes (or similar) do the right thing.
My ideal is still to use JavaScript libraries where the documentation not only describes how they work with screen readers, but is accompanied by video evidence showing the experience a screen reader user gets for different problems solved by that library.
As for handling dynamic content for screen readers, focus management is already a thing, and is in the scope of browser standards and the HTML your backend returns. As before, it's your responsibility to manage this. HTMX will neither help you nor get in your way.
HTMX merely extends hypertext functionality to its (mostly) natural conclusion. It is not a component library, or a framework for building components, or a site building framework, or...
You can use other tools to enhance and audit accessibility, but their use is orthogonal to HTMX. I think web developers in general are very used to frameworks abstracting a ton of complexity, but HTMX is not a framework so much as a standardized set of tools for specific low level problems, it is not a one stop shop.
Leaving accessibility up to the end developer feels like a genuine missed opportunity for me here. One of the great things about NOT using a JavaScript library is that you can rely on the browser's default accessibility features for forms and links. Those benefits are the thing I care most about when considering HTMX or jQuery or React or Vue or similar.
You can refer to the WAI-ARIA standards.
> Leaving accessibility up the end developer feels like a genuine missed opportunity.
This doesn't compute for me. What would HTMX even provide? It's a set of attributes that extend the behavior of form submission to other elements and all request methods.
> HTMX or jQuery or React/Vue
These aren't the same kinds of tools. They address fundamentally different things. Handling ARIA automatically for you isn't in scope for any of them.
I feel completely starved of information here. I care about accessibility. I want to build a web page where clicking on a tab refreshes a subset of that page... and I still can't find a really good guide on how to do that in a way that works in screen readers, that's accompanied by a video (ideally multiple videos, one for each common screen reader) showing the experience I can expect my users to have from that pattern.
HTMX actively encourages that pattern, so I'd love to see the project also embrace helping developers do The Right Thing with regards to the accessibility of that pattern.
Why not try it? But also, why wouldn't it?
I completely agree that this is a pain point. In general, high quality documentation is lacking. I am not however convinced that this is a problem that can be automated and abstracted away. Neither am I convinced that it's one we should necessarily try to hide. It won't win me any favors but I think the issue here is simply an endemic skill and knowledge gap. Shifts in culture via higher educational curricula and stated quality attribute priorities within companies will do more good here than anything else.
Accessibility is a quality that needs to be built in from the start. The good news is that provided your HTML is sane and not a mess of class tagged DIVs, or you're building a pretty straightforward document-like navigation/content/etc site, you really only need to declare attributes to handle the places you do something unusual. The defaults are generally correct.
Much of this "unusual" behavior that needs special treatment is within custom components (e.g. a custom date selector widget with plenty of invisible divs used for layout of the calendar days can be inscrutable to a screen reader without hinting) and is the responsibility of component library or framework producers. Some issues here run deeper, like properly correlating ARIA attributes in shadow and light DOM. But that being the case, such component libraries aren't even necessarily suitable for many sites (either too complex, or make too many mismatching assumptions).
The bulk of the remaining accessibility attribute slinging that needs to happen has to do with the overall site layout (especially reactive layouts). I don't know of any framework that will handle this for you in a satisfying way for anything sufficiently sui generis. I think the tough but true answer here is "the people building the site should have at least skimmed the WAI-ARIA standard, and be using an auditing tool, and know what to be thinking about as they design the site from the start".
That guy is asking you if replacing a part of the html with some other html alerts screen readers to the change.
It’s a reasonable question and you could share what you know about how screen readers react when this replacement happens. You could write some documentation on how to alert them, some best practices to follow.
Instead you say read the fucking manual, as if that helps. You put on a veneer of caring for accessibility but it seems you care about the “purity” of htmx more.
Frontend frameworks often do spend a lot of time thinking about the accessibility concerns associated with client side routing, so it's not absurd to consider this question in scope for a frontend library that handles DOM updates.
See for instance this 2019 study by Gatsby: https://www.gatsbyjs.com/blog/2019-07-11-user-testing-access...
Or even the modern Next docs on route announcements: https://nextjs.org/docs/architecture/accessibility#route-ann...
Some of this will have to be bespoke work done on a per-site basis, but I'm not sure I'm comfortable with the idea of completely punting this responsibility to developers using htmx, even if it does make philosophical sense to say "this is scope creep", because ultimately users with disabilities will end up being the ones whose experience on the web is sacrificed on this altar of ideological purity.
Of course it is, but it's like asking if using React.js will prevent SQL injection attacks. They are orthogonal things. Making screen readers announce things is controlled by the HTML you write, not by htmx.
It's actually like asking what a database library will do to prevent SQL injection attacks. And the answer is simple - "don't do string interpolation yourself, instead use the `(?, ?)` syntax". If you use that the SQL escaping will be taken care of automatically by the library. If the database library said something idiotic like "read the spec and implement your own SQL escaping logic" it would be a dereliction of duty.
Make no mistake, a frontend library like htmx has a responsibility to not break the front end from an accessibility perspective. If existing screenreaders break when you replace HTML then the htmx approach is broken and htmx needs to address that.
EDIT: here's the one mention of `aria-live` in the React.js codebase defining it as a valid ARIA attribute for ReactDOM: https://github.com/search?q=repo%3Afacebook%2Freact%20%22ari...
The one mention in Vuejs core to define its accepted values: https://github.com/search?q=repo%3Avuejs%2Fcore%20%22aria-li...
The one mention in the Svelte runtime defining its accepted values: https://github.com/search?q=repo%3Asveltejs%2Fsvelte%20%22ar...
Do people go after these frameworks saying they need to handle breaking screenreaders by dynamically updating content? Of course not. Setting live regions is the responsibility of the web page creator, not the framework.
I'll believe that once I see you file an issue which mentions accessibility against any of the projects I linked to ;-)
https://github.com/facebook/react/issues?q=is%3Aissue+author...
https://github.com/vuejs/core/issues?q=is%3Aissue+author%3As...
https://github.com/sveltejs/svelte/issues?q=is%3Aissue+autho...
Simon don’t waste your time with this guy. I thought he was affiliated with htmx but he’s just some dude trying to prove he’s “right”.
Now if you say that component frameworks like shadcn/ui or whatnot should implement accessible behaviours and patterns, I am 100% with you on that. But React/Vue/htmx are at a lower level, they can't decide those things for you.
EDIT: sure enough, someone filed an issue with shadcn/ui that it does not announce something properly in screenreaders: https://github.com/shadcn-ui/ui/issues/4209
My problem with that is that, as you can hopefully see, I am very motivated to learn how to do this... and yet I have not managed to learn it.
"Learn how to do it" only works if there are clear and obvious resources we can point people to that will help them learn what the need to learn. The ARIA spec is not that.
This also feels like an inherently solvable problem, which is why I always take any opportunity to put it in front of people that might feel incentivized to help solve it.
And yes, I agree it is not the clear and obvious resource we can point people.
We DO need better "guide" format documentation, rather than dry technical reference. Nearly everything I've seen online is in very poor shape or outright wrong.
I share your feeling that it is solvable, and I also hope that people will help solve it.
But I'm sure of one thing: the people who write that documentation will be familiar with the specifications and refer to them (among other sources) while writing.
An "Accessibility Book" (like sections of the Python and Django docs, or the Rustonomicon for unsafe Rust) would be a fantastic resource and I hope someone writes it.
There are. Start with MDN. There is no more clear and obvious resource than this: https://developer.mozilla.org/en-US/docs/Web/Accessibility
There was a time when I didn't know anything about web accessibility. But I learned by reading, trying out small experiments, and using a screen reader to check my work. If I can do it, you can certainly do it.
After a while you face issues like 'Why isn't the screen reader announcing the dynamic content update', you search for solutions, and you come across incredibly helpful content like this: https://tetralogical.com/blog/2024/05/01/why-are-my-live-reg...
> This also feels like an inherently solvable problem
It shouldn't, especially if you don't know anything about web accessibility. It's hubris to think that something we know nothing about should already have been solved, why hasn't it? Is everyone else just an idiot? No, of course not. It's a complex and nuanced problem. Not the basics like always put an `alt` attribute in your `img` tag, those things are easy. But when you insert dynamic updates with JavaScript into the mix, it gets more complex.
More generally, I often see people calling others "lazy" for not making websites accessible, but I personally found it hard to get my head around the WCAG recommendations, and I work with designers/developers all the time that don't know how to follow the WCAG recommendations even when you point them to documents and tutorials.
It's like nobody wants to admit it's difficult, and that's not even getting into screen readers still having many inconsistencies for basic UI patterns.
There are some sites that try to document what works and doesn't in different screen readers (e.g. https://a11ysupport.io/tests/), but even then it's still not easy knowing what to do and I don't know of an authoritative up-to-date site.
> It's like nobody wants to admit it's difficult, and that's not even getting into screen readers still having many inconsistencies for basic UI patterns.
Accessibility IS hard.
It feels sometimes like nearly everyone involved thinks they'll just read a few good blog posts and know how to make sites accessible. Then the struggle is due to not having read good enough blog posts.
Everyone wants a quick "fix" to a lack of education. Nothing replaces familiarizing one's self with primary source specifications, and most crucially, spending significant time trying out real screen readers.
> You can refer to the WAI-ARIA standards.
Every time someone asks for concrete a11y advice for concrete situations, some joker refers them to WAI-ARIA. This is ridiculous! That document is extremely hard to parse, and it offers absolutely no guidance wrt which parts matter the most, or, say, how the various real screen readers used in the wild behave. Please stop doing this. Accessibility is hard to get right! Making people feel like they're idiots for trying is very unhelpful.
I think everyone's afraid of getting sued.
No, but it does enumerate what is available which is the starting point for figuring out what is relevant to your use case.
If you want tutorials or guides relevant to your particular use case you can seek those out, but to understand them you will need familiarity with the set of available attributes and where they are or are not permitted.
Many (most?) tutorials online have flagrant violations of the specification. We need better ones that actually emphasize understanding WAI-ARIA and not cowboy markup recipe books.
> Please, stop doing this.
No, I will not stop telling people to familiarize themselves with the primary reference material. Reading technical documentation and specifications relevant to a project is not an optional step.
It is not complete in the ways you describe (actually testing real screen readers is crucial), but it is absolutely essential reading to begin with.
Well, I'm competent at HTML and CSS yet I never properly read the HTML or CSS specs either. Specs are generally a terrible place to learn a technology.
I simply don't understand how it's possible that the people who seem to care most about accessibility also seem to deeply, strongly believe that doing good accessibility ought to be very hard and time-consuming, and you don't deserve to call yourself a proper web dev without going through the rites. It's... not very accessible!
I would strongly recommend you do! Most web developers are unaware of a good deal of just what all is available to them in those specs (especially HTML).
As for "real screen readers", yeah. There needs to be a caniuse.com for assistive technology.
The htmx documentation does include examples with accessibility guidance. Eg https://htmx.org/examples/bulk-update/
> The server will bulk-update the statuses based on the values of the checkboxes. We respond with a small toast message about the update to inform the user, and use ARIA to politely announce the update for accessibility.
If you check the Server Requests panel it also shows the responses and the ARIA attribute they include.
EDIT: I've submitted a PR to fix the notification toast announcement, with this the screen reader announces the notification correctly: https://github.com/bigskysoftware/htmx/pull/3112
The key is to mark all live regions statically before doing any htmx requests, then injecting the response HTML inside those regions. Then they are announced by the screen reader. This is nothing special to htmx of course; every app needs to work the same way.
Isn't this more of a general browser question that would apply to any website that uses Javascript to load page elements?
How would using HTMX (as opposed to any other library, or plain old Javascript) affect the answer to the question?
[1] https://htmx.org/examples/move-before/ [2] https://github.com/bigskysoftware/htmx/issues/1431
tl;dr htmx is better than a lot of alternatives, but Simon is right, it can improve this story and it has a responsibility to do so.
As a framing device: any interactivity that is not described with HTML is interactivity that someone is responsible for making accessible (which you correctly pointed out). Unlike JS frameworks, htmx encourages the developer to solve problems with HTML first, so the inaccessible surface area that the developer has to worry about is going to be much smaller on htmx-based applications than it is with JS-based applications. That's a pretty strict win from where a lot of the industry is right now.
That having been said, I agree with you (and disagree with a lot of our defenders in the comments) that thinking about this is in-scope for htmx. In fact, I'm a firm believer that libraries are exactly where responsibility for implementing ARIA attributes live. The average web developer should not have to think about this at all—they should be able to use declarative abstractions and trust that they are annotated correctly for screen readers. This is the only system that scales, and htmx should adhere to it as much as possible.
Ideally, htmx would just add the polite notification attribute to the elements it processes, and give an easy way to customize that. I think it's basically possible to do this in a backwards-compatible way (first as an extension) that aligns with the maintenance strategy outlined in this essay. And I do think we can improve the documentation as well.
What would be the appropriate place, imho, would be component frameworks that are built on top of htmx. FastHTML is an example; they already have htmx integration and they talk about server-side components. If we look at a popular one in React, this is what they do: https://blog.logrocket.com/aria-live-regions-for-javascript-...
Thinking about it in terms of dream-html[1], it might look like:
let announce msg =
p [
class_ "announcement";
Hx.swap_oob "innerHTML:.announcement";
Aria.live `polite;
] [txt "%s" msg]
(* POST /purchase *)
let purchase request =
let thank_you_fragment = ... in
Dream_html.respond (
(* Join fragments together *)
null [
thank_you_fragment;
announce "Your purchase has been successful!";
]
)
[1] https://github.com/yawaramin/dream-htmlIn a way it’s a bit of a lesson in managing complexity, rather than seek to be “the next JavaScript framework to replace all the others with its theory of the universe”, it instead carved off a smaller slice and said these Thich are related, we’re just for dealing with these thing, nothing more.
In one swoop a whole raft of manual developer programming workload was packed up with a new easier to understand abstraction.
Kudos to the team, I’m grateful for the considered way you’ve developed this tool for the rest of us.
HTMX highly encourages client side scripting for dynamic updates if that's what your UI needs. It's very pro-JavaScript even though a lot of people get confused and try to use it to fully replace JavaScript
You can do the component side on your backend language of choice, and output html like htmx likes it, and it works (have done it in Python, for example).
It is extra work, but it works with a bit of programming.
Kudos to the developers.
I really like turbo-rails [0] (the ruby gem that Rails 7+ bundles in for turbo support, meaning helpers that make turbo frames/responses a native "thing" rails understands) because it's a complete solution. There's at least some obvious structure to build off of, and I'm not stuck trying to build up my own framework on the BE for my newly simpler FE.
django-htmx [1] also fits in this case too. I feel like any honest pitch of HTMX should involve some BE solution as well.
A large chunk of our business comes from Spring Boot, so we are experimenting with JTE - looks decent so far (Thymeleaf feels just old nowadays).
My sell is pretty simple: You have regulations coming up in europe which will require you to keep applications up-to date and secure. Extending your SBOM by 1k NPM libraries is a huge cost. I want to get rid of that.
HTMX might not be something that will vanish in a week, but it's also nowhere close to a mainstream framework.
Modern React is too simple. A component is just a pure function taking arguments and returning UI as JSX. The only other thing you need to know is few hooks.
React is simple only in some mathematical theoretical sense, but not for understanding by human minds which fundamentally operate imperatively ("if I click on this, load data X from the server and show them to the user...").
You can get some hello world example relatively easily, but you hit the complexity wall quite quickly (need to know "some hooks" - some, like useEffect() are very complex, yet often needed for basic things). The worst of all is debugging with stacktraces making no sense with it all being from the React itself, not your code, not tracking some logical pathway.
(I'm saying that as someone who generally likes React and would choose it for a new project)
...and then draw the rest of the owl.
And where you can't use them. Hopefully there are zillions of YT videos from experts teaching you all react gotchas.
That seems a bit backwards, no? Why can't those other elements manage their own updates? You can have the server respond with an `HX-Trigger` header to dispatch an event and any elements that care about that event can listen for it. Far simpler than trying to coordinate surgical DOM updates in a single HTTP request.
Events form the backbone of the browser environment and leaning into that model makes a lot of things much easier
If that is actually the case, there is an issue with your component design.
I tried create-react-app, the thing built and downloaded for several minutes, and then there was a nest of file relationships that I didn't grok. It seemed like any change required three files to be updated. Lots of ancillary things like bundlers, packers, tree shakers, lions, tigers, and bears, oh my. After an hour, I didn't get what I was doing. Somehow, altering this function over here made this other thing over there go "moo."
I used to do web development back in like 2001. I understand the web, http, css, html, and basic js. I'm not up on all the latest, but I have a very firm base.
I got htmx working and pretty much fully digested in the same amount of time I wasted on React and have produced a working prototype. I find htmx to be like how the web used to be. It makes sense.
It's much better just to use Vite with React as a plugin. Then you only need to install three React packages to get your app going.
The best tutorial I've used was "Road to React" by Robin Weiruch. His example app you learn is how to build a Hacker News front page. Very clear and it goes step by step.
Most of the tutorials online are all over the place, or mix Class tutorials with Hooks tutorials, or starts adding in things like Redux (which aren't needed).
The person you're responding to is correct, at it's core React is very simple, especially if you just stick to hooks. Most of my code is just bog standard HTML (as JSX), CSS and JS with a few React hooks thrown in.
FWIW, I've been doing frontend dev since '94 and personally find React jives the most for me and how normal HTML/JS/CSS work. I can see why people would like HTMX, but I've never liked overloading HTML attributes as some strange event model. But it's good there are choices.
But this all or none of it has anything to do with React rather with a broken language design which never imagined anyone would write JavaScript worth more than a few paragraphs in a single file.
That's where tons of bundlers come into play from parcel and webpack to vite.
But then there are some language extensions that must be transpiled before they can be bundled. Your JSX comes to mind.
Typescript can be considered in the same league.
Minus all that - Modern React has a very minimal surface area, very few concepts and that's about it.
https://htmx.org/essays/when-to-use-hypermedia/#if-your-team...
the reality is that the only way to prove htmx is around for the long term is to stick around for the long term, and I hope this essay contributes towards that.
We'll see how this years JS rising stars shakes out.
People need to spend time learning this tool. They need to be proficient with it. Your new stack might need to still work with existing code at some point. That means training, overhead, ramp up and potential risk in a less established area. Why would people do that?
You should be thankful you didn't get warnings from your boss for messing around instead of actually pushing features out.
In my opinion, HTMX + custom elements does everything React does but better, and is a billion times cleaner.
Would be interested in seeing this
> People shouldn’t feel pressure to upgrade htmx over time unless there are specific bugs that they want fixed
Frickin A! Nice to see somebody pushing back against the trend of "if you haven't updated your software in the last five minutes you're on an unsupported configuration".
B) If you run into a bug, update that library, then look into fixing it and offering a PR with the fix. Easy-peasy.
Compared to: oh this is a bug in a library that's fixed in an update ... but then we need to update another library it depends on, but that requires an update to nodejs, but that requires us to update some other libraries, which introduce a new more serious regression, so we can't unless we re-write to remove that dependency ...
Why programmers like cooking: You peel the carrot, you chop the carrot, you put the carrot in the stew. You don't suddenly find out that your peeler is several versions behind and they dropped support for carrots in 4.3
I have been calling for this for a very long time even during pjax era. I hope that is not only an ideal but a realistic pathway forward. Chrome / Blink or Safari / Webkit. If we could just get one of them to implement it as experimental feature. How could we push this forward?
JPEG XL and HTMX in HTML, along with some sort of basic rich text editor for everyday writing is what I want browser to be included by default.
There's this vague general sense that the "Web used to be simple" and that "Everything is so complex now". There's even an enemy that can be pointed at: React and various other frameworks/libraries and JS tools. Sometimes even JS itself isn't safe from this.
Though I can never find myself agreeing with the arguments (if any get presented at all). There's a reason we're writing web APPS instead of web SITES now even if you might dislike it. Just as there's a reason the world itself is now more complex now.
Ultimately I don't hate HTMX or the people who want to use it. Though to me the experience of actually using it is awful. I would ask people that they don't pretend that the backend ecosystem is any different from JavaScript. By the time you've chosen the language, debated the backend framework/chosen your templating solution and DB library and build system you could have gotten through the decision paralysis for JS too.
By comparison, especially these days, making something like a Vue or React app couldn't be simpler. You run a single command and get everything generated for you, then you point it to one of a million free hosting sites out there and boom presto, you're live.
I feel like people are just afraid/cocky to admit they're too lazy to think about the frontend for whatever reason. All the arguments I've ever heard have been quite shallow and easily disproven if you spend, like, 5 minutes reading through some docs.
htmx is a good choice for some types of applications:
https://htmx.org/essays/a-real-world-react-to-htmx-port/
it isn't right for everything, as I try to outline here:
https://htmx.org/essays/when-to-use-hypermedia/
i think i've been open and honest about when the hypermedia approach is appropriate and when it isn't and I've been open about posting bad experiences with the library:
https://htmx.org/essays/#on-the-other-hand
populist or not, i think the htmx website holds up pretty well when compared with other libraries/frameworks with respect to honestly outlining its pros and cons
The best I've found is the github v3 API but it would be nice to review different approaches.
An offline first MPA:
https://github.com/jon49/WeightTracker https://weight.jnyman.com/web/
A progressively enhanced from no JS needed to JS with HTMF and web components to make it work a little nicer to partial offline support:
This uses C# to progressively enhance the website:
https://github.com/jon49/MealPlanner
This is like the weight tracker app but is a soccer game tracking app. The game play is much more complex then anything I've made in the other apps, I almost used a micro front end for that page, but it works fine with hypermedia. It also is a SPA as the page is always the same page using hf-select (works the same as hx-select). I'll be removing the SPA part as it is really unnecessary. I just added it originally because I didn't like the code calling the service worker code on every page. I've since made it so the service worker is under 100 bytes and then calls in the other code using importScripts.
https://github.com/jon49/Soccer
I hope you find those examples useful. Hit me up if you have any questions on github.
Remember Flash? Java Applet? ActiveX? Adding interactivity to web pages has always been abominable work.
Ultimately there's just a lot of tradeoffs to make in this space and I'm glad that we have more options now. For awhile it seemed like you were either doing SPAs or everyone thought you were doing it "wrong", but things like HTMX, LiveView, Livewire, and Hotwire make it much easier to build good backend driven web apps.
Inertia.js 2.0 is a really compelling middle ground as well & IMO is the best thing to come out of Laravel. You can get most of the benefits of a JS "metaframework", but you have adapters for many different backend and frontend frameworks.
I was writing web apps in 1998, with table layouts, almost no CSS and no JS.
Of course, it was simple. It was so simple you can't imagine how. And it was the simplest in the golden age of MVC frameworks (like Django, Rails, Symfony) some 10-15 years ago. Since that, everything went downhill.
Building sign in form or some simple form with validation and saving in database was 2 hours of work, 4 hours with testing and deployment. Salaries of devs were 1/4. Now, it takes 2 days to make a simple form, backend API, sync two states, run it via myriad of builders and minimisers and deploy it to production.
Development now is 4 times less productive, 16 times more expensive for marginally better UX.
In MVC framework, you just annotate a bunch of controllers, import Sign In and Sign Out functionality, and you are all set.
Another examples might be building data grids, CRUD functionalities, or more complex validation situations. Back then, you designed database, generated CRUDs, it automatically added Bootstrap CSS compatible classes. You added one beforeSave handlers to add extra logic, and it was done.
We web developers had to be competitive, because our competition were people using tools like Delphi, where you could drag'n'drop 30 screens in a day. It was ugly (default Windows 98 WinAPI look), it wasn't responsive, it wasn't prepared for people with disabilities, but it was hyperproductive.
If you can all get that done in 2 days you’re running a very fast dev team. Minus the QA and DevOps team my point is that a SPA/JavaScript-heavy web app is not only a technological choice but an organizational one. Things used to be faster because there were fewer divisions in the software, therefore fewer divisions in the organization.
I used to be able to churn out a form, naively, in two hours because I could just implement the elements, inline style them, give them a name and then go implement the backend form handler. Now there's a checklist of requirements: does it implement our design system, does it have test id attributes, is it responsive, does it work with password managers and auto populating form fillers, does it support internationalization, does it support multiple languages correctly, does it provide client side data validation, does the server return errors correctly and how should they be displayed, does it have rendering tests, does it have end to end tests, and so on and on and on.
Most of this isn't needed for a personal project or proof of concept but for a reliable product that millions of people use globally, a lot of it is table stakes or legal liability. You can certainly do it server side too, but the two hour effort window is still gone.
I'm currently using Go with Ent and Gqlgen and Relay extension on the backend and React vite with Relay graphql client as well as React-oidc-context for oidc with zitadel as the oidc idp.
It doesn't take 2 days to make a simple form.
You need to get put your comfort zone and learn.
I built a classifieds site in 3 weeks. Including admin ui. I'd call that as productive as it gets. There's currently as library in the works where you will be able to tell generative AI to make a frontend just from showing it the graphql schema.
Speaking of generative AI, I use and pay for v0 for frontend generation, tried Contember to generate backends from specification (the CEO is a guy I know for almost 2 decades), I pay for Cursor, ChatGPT, Claude Sonnet. I moved from Bootstrap to TailWind (which I don't like, to be honest).
But honestly, many things are just much slower than something like Rails/Django/Laravel+Bootstrap.
https://yohn.github.io/PicoCSS/
The "secret" to using these types of CSS is:
```css @import url("/css/pico.min.css") layer; ```
This makes it so there is no usage of `!important` anytime you need to make your own CSS and it would normally be difficult because of the base CSS library you are using.
It's nice having everything working out of the box and when I need to override anything it's easy peasy.
That sounds way more complex than even the average Rails or Django app, let alone the Good Ol' Days™ of CGI scripts.
Did we forget Spring was a thing?
Did someone solve async Rust?
And the only thing more numerous than JS frameworks is new databases.
Let’s not kid ourselves, this has always been hard.
We’ve made a lot of progress since then thanks in part to the powerful front-end state management and rendering solutions that are now standard. And if the argument is “we don’t need all that, I prefer simpler web pages…” then I just think you may have a totally different preference set from the average user. Normal non-engineers like sleek modern interfaces, not Web 1.0 forms and links and reloads
Is it too out there to say that we have both, and that's not a bad thing?
Some sites created 20 years ago were still not making use of AJAX, either. If they were, in very specific ways. It is more likely to be using IFRAMEs back then to achieve partial refresh.
Today, the difference is that we still apply "the old ways" building websites but with modern languages + htmx. This is the difference.
When I look at websites I have created or inherited, all I see if bloat crossing between code written on the server-side... and code on the client-side. The further back in time I go the more it was server-side but, as mentioned, begin to lack the AJAX side of it.
Personally, I prefer to be back to the vast majority being server-side code. Sure, the amount of Views (and Partial Views) on my backend codebase is much higher than before but it is still organised code and testable without even using a browser. I then let htmx do the magic onto the webpage.
I have success stories but I also mock some things I did in the past but with htmx and it is very promising!
Sure I am still using Javascript but it is not ready about the data anymore - mostly additional libraries used for better drop down features or other cosmetics/UI things.
EDIT - ADDED: It is worth noting that the last 20 years, despite various javascript frameworks from React to Angular to knockout to jQuery to MooTools, etc..... we also had Flash and Silverlight and other things. We also have HTML5, CSS3, etc.
I have tried many things in the last 20 years. I also accept that htmx, while my goto choice for todays web development... is not going to be the best choice in my future.
Web Assembly (WASM) is going to get better and more popular. It will not be about HTML coding like today or even javascript in many ways. They will still be there, of course.
(Javascript will always be there but its use will get smaller and smaller)
Funnily I get quite irrationally conservative vibes the other way around. People clinging to their tools. All this complexity I learned must have been for a reason! We are building webapps for a reason (and that reason is valid for absolutely everybody and their use case)! "You youngsters do not remember the bad old days when everything was made of spaghetti, never again!"
Fortunately this is not a struggle for democracy but only a quibble in web development.
Your abstractions live either in the frontend or in the backend. For most cases, either will be quite fine.
It doesn't have to be so emotional.
Htmx can be helpful to keep all your state in one place, it's simpler to reason about and make changes. Lower cognitive load for the system is better for smaller teams and particularly lone developers.
You can accomplish the same thing by going full front end and minimize backend code with a similar small library that takes care of most to all of it for you.
Living in the front end, with all app state in the front end, has distinct advantages. Lower latency for interaction. Lower server costs. Offline capable. It has some cons like slower initial render. If you don't like JavaScript, JavaScript.
Unless you are optimistic in your approach, that isn't true, both have to talk to the back end.
> Lower server costs.
Not necessarily. It depends on what language on the back end you're using and how your front end code is working. If it is making the API calls anyway then the cost should be the same, or close to the same.
> Offline capable.
Offline support with HATEOS:
https://github.com/jon49/WeightTracker
Progressively enhanced (No JS needed all the way to offline support) with partial offline support:
I feel this way about base React too, including -- functional/class components, hooks/non-hooks, and more recently, RSCs/Client components. Although I'm more willing to see React as an evolving research project, as contradictory as this may sound.
No new features is such an underrated feature. It's funny sometimes when people see some Common Lisp or Clojure library with no commits in the last X period of time, and people immediately come to the conclusion that something must be wrong.
In the world of AI tooling, "completed" should have a huge advantage over libraries with lots of churn. Maybe a positive side-effect of new AI tooling is that there will be competitive pressure for libraries to reach a completed, no-new-features state.
This argument is that jQuery is still very popular compared to JS frameworks like React, etc.
What about vanilla JS?
As someone who isn't that experienced with JS, my understanding is that modern vanilla JS is "about as good as" jQuery. i.e. if you don't need much JS these days, just choose vanilla JS.
JQuery might as well be a shorthand JS library.
But if you're working on bigger projects: It is possible, but have have to be very principled in how you use it, otherwise you're going to end up with either a massive spaghetti codebase and lots of edge cases in your app that breaks.
Alternatives like React and Rust may add more complexity upfront, but the improved structure and safety it gives has big benefits in all but the smallest projects.
<https://github.com/jquery/jquery/blob/main/src/ajax/load.js>
Then at the vanilla JS 'load' :
const response = await fetch('/path/to/template.html');
const body = await response.text();
document.querySelector('#some.selector').innerHTML = body;
IDK, all in all it is a proxy functions lib.What it doesn't show is that vanilla JS is not chainable (jQuery is).
let result = " hello jQuery "
.trim()
.replace("jQuery", "javascript")
.toUpperCase();
console.log(result);
map, filter, ... let numbers = [1, 2, 3, 4, 5];
let result = numbers
.filter(num => num % 2 === 0)
.map(num => num * 2)
.reduce((sum, num) => sum + num, 0);
console.log(result); // 12
Simple string let myStr = "This is a wonderful day.";
let reversed = myStr
.split("")
.reverse()
.join("");
console.log(reversed); // ".yad lufrednow a si sihT"
DOM elements document.querySelector('#element')
.classList.add('active')
.classList.remove('hidden');
Using a class class Chainable {
constructor(value) {
this.value = value;
}
add(num) {
this.value += num;
return this; // make it chainable
}
multiply(num) {
this.value *= num;
return this;
}
getValue() {
return this.value;
}
}
let result = new Chainable(5)
.add(3)
.multiply(2)
.getValue();
console.log(result); // 16HTML
<span class="a b c"></span>
JS function getClassList(el) {
let ele = document.querySelector(el);
let list = ele.classList;
return {
add: function (c) {
list.add(c);
return this;
},
toggle: function (c) {
list.toggle(c);
return this;
},
remove: function (c) {
list.remove(c);
return this;
},
}
}
getClassList('span').remove('b').add('e').toggle('a');
console.log(document.querySelector('span').classList);Plus jQuery is one of the most battle tested libraries in the world.
That "ops" you made with classlist, you're bound to repeat these mistakes ad infinitum. And they can bite in subtle ways only your users might experience.
People rarely report broken websites unless they really need to.
Plus using a homemade alpha version of jQuery written by one dev leads to more bugs, not less.
I think those two sentences are out of bounds, but I somehow get you. Yet I don't get the 'broken website' remark (took it condescending, or is it from experience?).
Mainly, I was replying to the affirmation that javascript is not chainable which is (imho) an indication of how one could get disconnected to the underlying lang by simply relying on libs such as jQuery (and I am thinking the same about htmx). Thanks for your reply!
Now if exploring the cutting edge is a goal of yours in and of itself, then by all means blow some of those innovation tokens on the new Reactangular.ts hotness. For a lot of projects, though, the goal is to get something out the door as painlessly as possible; jQuery and plain JS have (for better or worse) been the tried-and-true "boring" approaches, and HTMX (from what I can tell) seeks to be the similarly "boring" choice.
Obviously right now HTMX ain't the boring choice (because it's still pretty new), but a decade from now it could be. Having used it in a couple pet projects recently, it already does feel pretty boring (especially since it goes hand-in-hand with other boring strategies like "just use SQL" and "just use CGI scripts" / "just use classic MVC frameworks").
----
However to this day I still find jQuery to be one of the nicest APIs to ever be used on the frontend stack. It is legitimately just more pleasant to write.
(Yes yes I am more than aware of how to shim a lot of it for vanilla JS)
Vanilla JS, as an experienced dev, is the best thing for now. You can write your proxy functions, and globally you get the control over every little thing.
Some of the people you're dismissing have probably been using JavaScript for a lot longer than you have.
<button hx-get="/confirmed"
hx-trigger='confirmed'
onClick="Swal.fire({title: 'Confirm', text:'Do you want to continue?'}).then((result)=>{
if(result.isConfirmed){
htmx.trigger(this, 'confirmed');
}
})">
Click Me
</button>
or about <div hx-get="/clicked" hx-trigger="click[ctrlKey]">
Control Click Me
</div>
or <form id="example-form" hx-post="/test">
<input name="example"
onkeyup="this.setCustomValidity('') // reset the validation on keyup"
hx-on:htmx:validation:validate="if(this.value != 'foo') {
this.setCustomValidity('Please enter the value foo') // set the validation error
htmx.find('#example-form').reportValidity() // report the issue
}">
</form>
Htmx's own examples push you to code that is unorganized and inaccessible.<button @click="doThing">
In Vue. Or just plain old JS onclick in Svelte.
By comparison, HTMX is illegible
<button hx-get="/confirmed" hx-trigger="Do you want to continue?">Click Me</button>
Hardly the horror story you are trying to write.The second example: really? The words 'get' and 'trigger' don't tell you what it's going to do?
> Htmx's own examples push you to code that is unorganized and inaccessible.
You realize these are demo, ie sample code right? No one is forcing you to write exactly that code? You can write organized and accessible code in your own project?
And the second example is not accessible. It should be a button.
A library’s demo/sample code should present best practices, not worst.
> htmx supports the hx-confirm attribute to provide a simple mechanism for confirming a user action. This uses the default confirm() function in javascript which, while trusty, may not be consistent with your applications UX....In this example we will see how to use sweetalert2 to implement a custom confirmation dialog.
It's implementing a custom confirmation dialog. Customized, non-default UI/UX usually means custom-written code in any framework I'm aware of. Maybe React has implemented magical customizations since the last time I checked.
And even if it was - I would be prepared to suffer a lot of pain to avoid the javascript build pipeline and framework churn.
SPA frameworks drove me away from front-end dev and HTMX is making me consider returning.
And I fully accept that "web apps" probably need complex frameworks. I just think most people aren't really building web apps - they are building web sites.
In the remaining example, IMO it looks about as organized and accessible as I can imagine as far as HTML goes - my one complaint being the use of a div instead of something more semantically meaningful.
It’s just people would rather write a low level, well-designed language than maintain JS codebases.
None of that goes away, of course, it just moves to a different repo.
Actually, duplication of state, routing logic, auth logic, etc. really do get eliminated. Because we're maintaining all that on the server-side only and not having to reproduce it on the client side. It's a huge win.
But your larger point stands, HTMX is probably not a great fit for highly interactive webapps, even though you can push it pretty far
So before clicking 'next':
<a disabled>prev</a>
<span>Page 1</span>
<a href="/page/2" hx-get="/page/2">next</a>
After clicking 'next': <a href="/page/1" hx-get="/page/1">prev</a>
<span>Page 2</span>
<a href="/page/3" hx-get="/page/3">next</a>What happens when you click quickly? Does the UI just freeze until it eventually loads... some slide? What if you want a touch carousel using scroll-snap? How do you destroy and replace the entire section without interrupting the user?
> No more state!...Just use htmx, everything becomes so simple!...None of that goes away, of course, it just moves to a different repo.
With a purely client-side component, the state is managed purely on the client side, and the server would not touch it anyway. So it didn't have duplication of state to begin with, and htmx is solving (among other things) the duplication of state problem. So again–this example is not relevant to htmx.
Backend in a language that isn't JavaScript is a feature.
Also, a backend where you just serve a template instead of full layout (server-side rendered app) or JSON (client-side rendered app) is not more complex in most of scenarios.
You can't do real time time tickers. You can't call client side functions.
It's hyped by entry level web devs, because they don't know any better. You get all the baggage with it, that you hoped to be rid of with the separation of data provider and client consumer. Session management, path parsing and matching, flash messages, complicated nested if else blocks. Argh. Search engines can crawl js nowadays.
It's like going back to sysinit when you have systemd only worse. But HN never fails to hype bs tech
"But that's not SOLID and not OOP". But it's simple and does the job.
I moved to Go and AngularJS. That was 2013. I did full backend aka full ssr with Go, and it's a PITA.
I did try htmx with a jinja like template language in Go, with templ and in Rust and ... I forgot the library, it's the go to library in Rust for htmx. All the annoyances are still there.
Session management, service oriented design, if else blocks between and inside html tags. Path parsing and comparison. Template macros. And now also fragments.
Now I use a graphql backend for data, and react consumes it while the ide supports intellisense for queries. It's more simple than writing your queries by hand on the backend. You have interactivity for free. And you let the client worry about how the data is displayed. Also you let the oidc server worry about users.
Concerns are separated. I have authz middleware on the graphql backend, easily written. Everything has layers and there's order and a clean structure. As a plus I don't have to annoy my users with captcha. And I have reduced infrastructure costs as well as traffic.
I'm 50. My internet journey began 1995. I did enough of the old way to hate it and to know when something is better. I have met my share of fanatics, of language and framework Nazis.
You have to stay curious. I have tried htmx multiple times and found it inadequate, not good enough, too limited.
Like I wrote there are no frameworks in any language for it. It's just JS hidden behind html attributes, claiming it isn't JS.
I hate deception, the zealots are deceptive as all zealots in any language, package or framework are. Angular Nazis holy crap. Or React retards where you mention how Vue has simple SSR adaption and Rract doesn't, and are labeled as a React hater.
I'm pragmatic. I like clean structure and efficiency as well as simplicity. Sometimes you have to learn a bit of complexity to have it simple and efficient in the long run. I have tried many things. Ruby on Rails, Elixir. You know what, I have started programming at the age of 11 on the cpc 464 in basic, at 12 I cracked c64 games and wrote cracktros in asm. I'm one of the first cheat creators for MMORPGs ever. I don't consider myself super smart, but I have seen a lot and tried a lot. I also struggle with learning new things. But you have to. Htmx is not the way. It's a step back. It's only for simple things.
I do believe the hype when it's reasonable. Like with MVC. It was the natural way to write SSR websites. This is the way. But then something better came along and it took a while to solve the inadequacies it had. But now it's at a point where SPA + graphql + oidc = awesomeness. And it's going to become better. And I'm not talking about the Nextjs crap, those fake backend libraries that are hugely overcomplicated.
This multi-page demo is decent, where each click is actually loading a new page: https://view-transitions.chrome.dev/stack-navigator/mpa-prer...
https://developer.chrome.com/docs/web-platform/view-transiti...
> The View Transition API gives you the power to create seamless visual transitions between different views on your website. This creates a more visually engaging user experience for users as they navigate your site, regardless of whether it's built as a multi-page application (MPA) or a single-page application (SPA). Typical situations where you would use view transitions include:
> A thumbnail image on a product listing page that transitions into a full-size product image on the product detail page.
> A fixed navigation bar that stays in place as you navigate from one page to another.
> A grid with items moving positions as you filter through.
So this would cover a few uses of HTMX?
Recent Safari and Chrome now have decent support. Sounds like Firefox are working on it but I couldn't find an expected release date.
https://htmx.org/attributes/hx-boost/
There are already people, including people on the core htmx team, who think that hx-boost isn't a great feature:
https://htmx.org/quirks/#some-people-don-t-like-hx-boost
If that goes away, htmx will be useful for smaller transclusional features at a lower level of complexity, so the two should complement one another in my opinion.
Thanks! Any examples here to help understand where View Transition doesn't help?
It has more built-in functionality that most web applications are going to need.
https://x.com/search?q=from%3Ahtmx_org%20unpoly&src=typed_qu...
I interviewed the creator here:
It embraces a more structured and composable approach and I love that it embraces web-components.
I thought about writing a script to remove all references to eval (and all tests relying on eval), but at that point it would probably be easier to just rewrite the library.
There are so many sites out there using 4-5+ year old versions of React, and they all work perfectly fine. There's no compulsion to upgrade if you don't want to.
> Today many web developers consider jQuery to be “legacy software.” With all due respect to this perspective, jQuery is currently used on 75% of all public websites, a number that dwarfs all other JavaScript tools.
I feel that is misleading. I worked on a lot of websites and none of them included jQuery willingly or sometimes even knowingly.
Either it's shipped as a peer dependency or we're talking about wordpress and the like which use it (and drives much of the web!).
I've seen it frequently shipped because of scripts embedded into a larger frontend codebase. Stuff they really don't want there to begin with.
I do not for a second believe that 75% of frontend dev work is in jQuery. In fact, I'd be surprised if it's more than 5% of all frontend engineering work is using jQuery.
Obviously some people might still use it for whatever reason; but those are a tiny majority (and probably quite vocal about it / over represented if they still prefer it).
So yes, to all intends and purposes I would claim jQuery is legacy software. Current usage (wherever they got that number from) does not mean it's still the preferred choice for the majority of web developers.
it's too bad the two APIs have overlapping but not contained functionality.
I also happen to think that most web apps have no business being so complex, and that too much work goes into dealing with the added complexity of running SPAs where an SPA is not needed.
The attitude of the htmx developers is highly commendable.
That's why I think their roadmap looks right. I believe the way to broader adoption is to improve tooling, encourage standardisation, and integrate htmx more closely with well-known frameworks. That's the only way I can see dev teams buying into the paradigm change and htmx jumping into mainstream usage.
Writing the bulk of the logic in Go, Python, Kotlin, Rust, or Zig is a huge plus, as I consider them better-designed languages with easier maintainability.
[1]: https://backbonejs.org/docs/backbone.html
[2]: https://github.com/jashkenas/backbone/blob/master/backbone.j...
[3]: https://github.com/bigskysoftware/htmx/blob/master/src/htmx....
If you're planning no new features as a feature, why not first remove those quirks? Why keep them around?
> People shouldn’t feel pressure to upgrade htmx over time unless there are specific bugs that they want fixed
Truly, there exists a middle path: you can make breaking changes and user still can upgrade at their own pace (using future flags, codemods, etc.), you don't have to refuse progress - it's just a "more" work for the creator.
A couple of your replies in this thread have seemed a little half-hearted. Sometimes it's better not to reply at all - or to reply at a later date.
To preserve backward compatibility.
> there exists a middle path:...it's just a "more" work for the creator.
I think you just answered your own question. Unpaid maintainers of a free open source software project are trying to reduce their maintenance burden. This is normal and actually a good thing if it means they will be able to stick around for the longer term. Consider that you are asking a guy who has been maintaining open source projects for more than a decade, with some degree of success. So his strategy is probably working for him.
What backwards compatibility? There is already migration guide from v1 to v2.
Anyway, excellent article and discussion that showed me I can forget about HTMX :D
Of course, no one is forcing you to use htmx. Please use whatever you like.
i interviewed Henning Koch, the creator, here:
any advise from others how they handle complex client side components?
so unfortunately the major downside I see so far is it's fairly hard to find good open source vanilla js libraries for things, as most things seem to be written for react.
other examples include: - virtualized list - combobox
How others handle this?
P.S. I have seen some people using e.g. flowbite, but I havent tried it out: https://github.com/themesberg/flowbite/issues/812
By the end of the day having built quite a lot I then converted the entire thing to react within half an hour stopped wasting my time and got in with the job of building the thing.
I like to try library free JS every now and then and yet again it was not competition for react.
I know react, it makes sense to me, I find it easy and powerful, I know how to fix most issues and probably most importantly Claude is able to write react for me almost without me intervening at all.
I’m not saying react is for everyone but for me it’s a power tool that I know and the AI knows very well and it gets big stuff built quick.
All these new front end developers who jumped in on react with no other experience have no idea how web works are struggle to build without react.
Anyone competent in web development prior to react could build with htmx or even vanilla js just as fast without react as they could with react. Won’t stop the brainwashed react devs coming out defending their only source of income tho.
What's the problem with starting from an elevated starting point?
In a way, it’s depressing that the thing that holds developer minds hostage gets even more hold over devs, because the frickin AI knows it best.
Just a reminder: React was created as a not-a-framework-but-a-view-library but everybody writes React apps, not JS apps.
Honestly, I think this was the biggest mistake the React team made. It was never intended to be this way. It was just marketed this way in order to convince people to try it.
Once you started to use it you could very easily tell how it never fit in the traditional MVC model.
The app is fully SSR and integrates with a fairly complex inline data enrichment and analysis system. I used Tailwind alongside regular CSS for the layouts and some visual enhancements. Eventually, I gave in and added a bit of JavaScript to submit a form when a dropdown is selected—usability is important to me. Other than that, everything works as needed.
Tools like htmx make it easier for solo founders and small teams who don't have the bandwidth or the desire to manage all the churn. Keep the dependencies tight and ship!
i can tell you that it fits so so perfectly for finance apps with lots of forms and data. we have a very sophisticated quote page which also with oob was a breeze.
> We are going to be increasingly inclined to not accept new proposed features in the library core
I deeply wish the C# team recognized the value of this.
That said, back in the day it provided functionality that JS just didn't, or was quite cumbersome.
With recent JS versions, JS can do a lot of what JQ did for it, but JQ's API or "surface area" is still syntactically smaller and (IMO) more sane than those JS improvements.
[1] - https://colorlib.com/wp/wordpress-statistics/
[2] - https://w3techs.com/technologies/overview/javascript_library
Besides it having a way more convenient API than bare JS. (That honestly, I only don't use because bare JS is conveniently documented by MDN, otherwise I think I'd be fully on it too.)
If you are brand new to the space and looking to learn, then yeah stay away from jquery.
Unbelievably so
Yes, my site appears a bit clunky (this is intentional), but as a solo, full stack developer working on a personal project, I wanted things to be stipped down and focus on having a solid backend and significant tests.
Htmx is perfect for this.
Is it elegant? Yes and no. Is it ideal? No. But what it does very well is let me focus on the code I'm writing (python/flask), without having to put three different hats on (frontend, backend, and interactive js), and it lets me code in the language I love (python) without forcing me into a gigantic javascript platform I don't actually want to be in.
I'm not getting paid for this, and I won't actually spend my time coding if I'm not excited about the way I'm working. Htmx let's me code the way I want to code and that's why I'm a big fan.
Great work!
For example, the most recent update completely changed the way the index page loads, as I reverted it from Leaflet -> Maplibre so that I could use OpenFreeMap, saving $20+ per month in hosting costs, and allowing for vector maps to be used: https://openfreemap.org/
Thanks hyperknot: https://news.ycombinator.com/item?id=41635592
In that same update, I was able to add the "most recent week/month/year" for new and updated courses. After that update, I was overloading my flexible server instance with too much memory (oh, those for-loops and large lists). So, I then rewrote a significant section of the caching system!
The important thing is the "recent updates" lets people know the site is active. I got more than a few emails about whether it was a dead site in the last year (followed by random middle-man advertising pitches).
The reason why I think the styling is a low priority is that the site is targeted (for content creation) at older, non-computer literate folks at small clubs that would like to share their knowledge for posterity. It's also targeted at Wikipedians who justifiably know that this kind of detail about golf is inappropriate for Wikipedia, but still love golf. I'm not sure either demo cares too much about a site being super pretty.
The information ideally is targeted at golf nerds, but mainly junior golfers, looking for available information about relatively unknown course that they will be playing on in tournaments (hence the printable course guides).
With something like Elm, I'm basically thinking of the frontend as a state machine (composed of smaller state machines). I always know what's [supposed to be] going on exactly, and assuming that all the underlying machinery is working as expected and that I haven't messed up anywhere, I can be sure that everything is consistent. Basically, things are data-driven.
Htmx feels like a step back in this regard. Let's say https://htmx.org/examples/delete-row/ - something back in my mind yells at me that I don't really know what I'm presenting in that table. The state is in DOM, all "inverted" as the frontend is not really aware what it's displaying (it can figure it out by introspecting the DOM, but that's exactly what feels off). I'm just concerned that it'll end up like my ancient Delphi or Visual Basic projects, where it was impossible to understand what's going on, because everything got tangled up in a ball. This is opposite of data-driven approach that I don't really know a name for... "shape-driven"?
I look at examples like https://htmx.org/examples/sortable/ and I just can't shrug off the feeling that with such design the frontend has no idea about what's going on, and while it's fine if all I ever need is a small sorted list (that I can pull back from DOM - which acts like a weird pseudo-database), if it grows it becomes error-prone, difficult to comprehend and maintain.
I suspect this is because HTML was always about documents, and never about interactive applications, so there's this fundamental impedance mismatch when one tries to build an application in a browser. I thought the solution was to build a new abstraction replacing HTML - with things like React being intermediate steps, still using HTML/CSS for rendering, and canvas-based GUIs being the way to go, unburdened by the document-based foundations anymore. In other words, I'm not really convinced that Hypermedia is a suitable foundation for a lot of the things people actually build online.
Htmx surely has appeal in simplicity, but doesn't this simplicity brings back all the complexity people tried to get rid of all this time? Is there something I'm missing? Should I possibly think of the frontend as a terminal-like system that can run small programs but is not an application so it's never aware of what's going on? Or is it something else?
My apologies for the confusion, or if I wrote something weird (I sure babbled a lot). I'm just trying to keep up with the world and understand it.
(And, of course, no doubt, one can write crappy incomprehensible mess of a codebase using any technology. Maybe all my issues is that I have no idea how to write good Htmx code that wouldn't bloat and rot over time?)
Kinda? Where HTMX sits in my head is on a different evolutionary path starting from server rendered pages back in the 1990's. Instead of doing full page renders, HTMX lets us update discrete portions of the DOM from server rendered content... and that's all. It's like heavy client JS apps never existed. IMO, the key here is that the browser is assumed to be mostly just for display, and the backend is still expected to be inside the user interaction loop.
The last time I tried to do anything with HTMX, the technology practically resisted any attempt to add any substantial state management on the client-side (which is kinda/sorta by design). As you mention, complex controls that do this like fully-featured tables, are a poor fit. It's possible, but not elegant or easy. Meanwhile, fetching an updated fragment from the server to do those kinds of jobs on user input, is trivial. It's super inefficient for bandwith, but way easier to code and maintain (IMO). To me, that's the core tradeoff here.
The database is the Model.
The server is the update function.
The HTML template is the view function.
HTTP requests are the Msg.
Database/API calls are the Cmd.
The problem with this model is that recreating the whole UI every time is slow and clunky.
Elm and most JS frameworks fix this by running the `Model` and `update` function on the user device and doing tree diffing. This is reasonably performant if you do it well, but it's also hard to do well (see: every website ever these days) and introduces complexity, particularly because the client-side `Model` almost always needs to be synchronized with a database or some other "canonical" model.
As pragme_x touched on in a sibling comment, what htmx does is not an iteration on the framework model; it's an alternate solution to the original problem. What it does to avoid the clunkiness is let the server to return `Delta HTML` instead of `HTML`, and for the slowness, it leaves the vanilla-JS escape hatch open for things that can be done without altering the Model (database). This model also has its flaws, especially if you need to use that escape hatch a lot, but it's also a lot simpler conceptually and keeps the `Model` and `update` function in a trusted computer, meaning you don't need to marshal and validate stuff between two models.
> how to write good Htmx code that wouldn't bloat and rot over time?
- Don't try to perform fine-grained updates if you don't have to. It's fine to replace a little more than you absolutely need to, and htmx takes care of some of the things you might worry about like preserving focus. For example, in the "delete row" example, it might be more robust to replace the whole table.
- Use htmx for anything "side-effecty", i.e. anything where a network request is compulsory. Relegate JavaScript to "micro-interactions". I consider a code smell in an htmx application any time I need to add new elements to the DOM via JavaScript, most of it should be manipulating classes, attributes and styles.
- For those micro-interactions, the "component" model heralded by the big three JS frameworks doesn't work as well here, since components have their own state, which is another "shadow-Model". Instead, try the RSJS methodology (https://rstacruz.github.io/rsjs/) with "behaviors".
- To wire up that JS to your app, reach for custom events. The `hx-trigger` attribute is the "port" that translates JS-based interactions to Msg.
> I suspect this is because HTML was always about documents, and never about interactive applications
This is a really common refrain and it peeves me, but I don't have a good rebuttal to it yet so I won't weaken my comment by trying to make one. I don't have good explanations for a lot of things about htmx and hypermedia, actually. The code of htmx is mostly complete, but the theory is still WIP.
What does it do? After reading a large chunk of the article, I have no idea. No, wait it "enables behavior".
Maybe it's only relevant to people that are already familiar with it. But it would seem that a hacker news front page would be a great opportunity to let more people know about your product.
and if you want a more in depth treatment, our book (free online):
It's on the front page every other week…
https://react.dev/blog/2024/10/21/react-compiler-beta-releas...
The modern way is to use LLMs to auto generate all this code and do some small corrections in the process. So you wouldn't have to worry about the underlying tech and would only be concerned about the core functionality and actual mechanics of the product rather than being interested and spending efforts on memorization of the specific instructions for the machine. The whole evolution of the programming languages is a process in that direction and new technologies that were embraced by the newer generation like React and Vue.js is the way to go. You can't run geosites forever.
A foundational fact by definition does not need to be constantly scrutinized as if it were not. Rather it is something that can be relied upon stably until such a time that a change in a core assumption forces us to reevaluate the foundation if and when that scenario occurs.
Well, yeah. Sometimes the status quo is good. Sometimes you don't want to learn how to do simple async page updates for the thousandth time.
Because many of us here have been there, done that. Over dozens of years. With dozens of libraries.
It's a hamster wheel. It's boring. It's pointless.
In the end, if your website/app does what HTMX is good at, just use it.
I learn dozens of new things every day as a solopreneur SaaS guy. I don't want to relearn how to make async page updates ever again, unless there is a very, very compelling reason to do so.
it sounds a lot like correcting the work of a junior developer and it's definitely not what I want to do for a living.
> new technologies that were embraced by the newer generation like React and Vue.js is the way to go.
IMO, anything that requires a build step to the browser runtime is at best a temporary solution waiting for a web standard and at worst a regression.