commented: reposting my comment from the other site: Hey, I created htmx and while I appreciate the publicity, I’m not a huge fan of these types of hyperbolic articles. There are lots of different ways to build web apps with their own strengths and weaknesses. I try to assess htmx’s strengths and weaknesses here: https://htmx.org/essays/when-to-use-hypermedia/ Also, please try unpoly: https://unpoly.com/ It’s another excellent hypermedia oriented library Edit: the article is actually not nearly as unreasonable as I thought based on the just-f*king-use template. Still prefer a chill vibe for htmx though. commented: Hi! I've checked https://htmx.org/essays/alternatives/ and though you mention unpoly there isn't really a comparison of it to htmx. I know it is not easy but could you try to tell us why we could choose one over the other? In any case, thanks for htmx, I have yet to try it but I am looking forward to. commented: Unpoly is more of a framework, with support for higher level concepts like "layers": https://unpoly.com/up.layer And it has best in class progressive enhancement support. htmx is lower level and is focused on generalizing hypermedia controls: https://dl.acm.org/doi/pdf/10.1145/3648188.3675127 I would expect unpoly to be less work for the features it integrates conceptually, whereas htmx might be more flexible due to the amount of control you have over how hypermedia exchanges occur. Unpoly's creator, Henning Koch, is a great guy too. commented: Thanks a lot! commented: Personally, the framing of htmx as a middle path between HTML and React never worked for me. I'm in the "just use HTML" camp, and for a long time htmx looked like yet another JavaScript library. What did work for me was the Hypermedia Systems book. It convinced me that the HTMX approach is consonant with the kind of Web I advocate for. commented: I'm a big fan of fixi, which is a middle path between HTML and HTMX https://github.com/bigskysoftware/fixi commented: I really enjoyed that book. I worked through it in public with django here.. I liked HTMX before I read that book, but working through the exercises with some tools I like to use really helped see how the authors/maintainers think about HTMX. commented: I like to see HTMX as a prototype for things we may want to add to HTML. Probably not all of them, but that's why we prototype and try things to find out what's most valuable commented: claudeslop :/ commented: You’re absolutely right! And honestly? That’s not just a callout — that’s a whisper of brilliance. /s I’m a bit surprised that even with such a distinctive style as the inspiration for this site, it still leaks through so much AI slop style. Author says “I made it using a lot of AI” lest anyone doubt it https://youtube.com/watch?v=2P0CZPZzoZg&t=15m2s commented: As soon as I read "but let's be real" my heart sank. We need a "slop smells" on some reasonably-official page that automatically updates the list. commented: https://en.wikipedia.org/wiki/Wikipedia:Signs_of_AI_writing commented: Note that the "React (or Vue, or Svelte, or Angular)" criticism is actually just React. None of those things are true of Svelte. The entire tree is 18 dependencies and the bundle is probably around 50kb. Builds are in the milliseconds. There is exactly one way to do state management, as of Svelte 5. Effects are compiler/language constructs, not functions; either they work intuitively or your code doesn't compile. Same with the pathological 'ecosystem' cases mentioned later in the article; you don't need a library to style your components, React makes styling hard but Svelte does not. So you should also try Svelte! It makes everything better for essentially free. If you already have a backend picked out, you should use HTMX or Datastar with it instead of a frontend framework; if you do not already have a backend picked out, SvelteKit makes a great backend. commented: I liked Svelte 4, but in Svelte 5 everything is turned into proxies, which is crazy. I imagine the performance hit of that must be huge. But worse than that is the fact that you can't deal with JS objects anymore, jsonify them and so, they all get automatically turned into proxies and everything is a mess. I've switched my allegiance to Solid. commented: JSON.stringify not working with Proxy is mostly a thing of the past, try it in your dev console and see. And it's only for 'dumb' objects and won't do that for classes - the point is to treat objects as a bag of variables, which is what you were generally putting an object literal in reactive state for. SolidJS inherits about half the React design flaws and acceptably solves the other half. It's still insane to compose functions WinForms style when you could be using the DSL you've already got to compute layout updates beforehand. JSX style cannot ever be faster than Svelte (Svelte 4 lagged behind SolidJS in benchmarks but Svelte 5 beats it) because Svelte does not have to do any DOM diffing or unnecessary DOM object construction ever unless you use an escape hatch. commented: Wait, Solid also doesn't do DOM diffing, right? What I like most about Solid is that functions runs predictably and objects aren't turned into proxies. JSX is not great but not bad either, specially because no "className". commented: https://news.ycombinator.com/item?id=46313750 Hey, I created htmx and while I appreciate the publicity, I’m not a huge fan of these types of hyperbolic articles. There are lots of different ways to build web apps with their own strengths and weaknesses. The article also show "hello-world" level examples, which obviously don't need a framework like React. Write me an article that shows me how to build with HTMX a visual scripting editor like Scratch, or Unity's Visual Shader Editor, or Unreal blueprints. When you have a lot of local-state, a JS framework makes sense. But sure, a CRUD app showing tables of data, like 99% of dashboards out there, with Websocket or Server-Sent Events, HTMX is fine. If you don't need websocket or SSE, then you might be fine with HTML/CSS without HTMX. Browsers are good at caching and full page reloads are almost instant nowadays. commented: Write me an article that shows me how to build with HTMX a visual scripting editor like Scratch, or Unity's Visual Shader Editor, or Unreal blueprints Did you read the article? This is already called out specifically. commented: But sure, a CRUD app showing tables of data, like 99% of dashboards out there, with Websocket or Server-Sent Events, HTMX is fine This is actually the point of the article. It says you shouldn't use HTMX for something like Scratch. commented: What I find most disturbing about htmx is that the reactivity and inclusion primitives are quite low level, with little to no security involved. The declarative syntax essentially turns somewhat unexpected attributes into meaningful, dangerous functionality. The simplistic (and really useful) inclusion of remote HTML through hx-swap invites XSS and other injection bugs. commented: You’re loading remotely from your own server. That server can already inject. commented: Sure, but frameworks like React make injection impossible by default, requiring you to say things like __dangerouslySetInnerHTML to even have a risk. We had these sorts of safety mechanisms on the server side too - Rails does this, for example - but given HTMX is server-agnostic, lots of people will be trying to use it without a server-side framework that solves this problem. commented: I don’t see how that’s a HTMX problem. It’s a potential problem whenever you use HTML templates on the server. commented: Ah. is htmx limited to same-origin requests? commented: By default, yes, but you can turn that off. Beyond that it has to follow the same rules as any webpage of course. commented: This is all common sense but the htmx people have painstakingly documented it: https://htmx.org/essays/web-security-basics-with-htmx/ commented: Good link. Thanks. commented: I was thinking about this when the "setHTML" API was posted. htmx adds many more attributes that can be used for XSS, and so "safe HTML" as per that apis definition is not necessarily safe when htmx is loaded. commented: Right, that's why you want to build an allow-list, rather than a block list. The setHTML defaults are going to work for htmx. In fact, the implementation of innerHTML could use a somewhat permissive configuration, like let sanitizer = new Sanitizer({}); context.setHTML(input, { sanitizer });. Passing an empty dictionary to the constructor essentially allows everything except script. commented: Like what htmx attributes are not safe with the setHTML API? commented: i was wrong, i had a vague memory that htmx changed the semantics of an existing attribute but that's not the case. might have been a plugin. commented: The search box example doesn't handle < or > escaping at all commented: The problem is that unlike with a front-end reactivity library, you can’t host a HTMX site on a static site host. commented: If you use a static site host aren't you forced to always do cross-domain requests from the frontend? Also you can't store secrets securely and have to use much more complicated workflows. Htmx advocates for simplifying the implementation quite a bit. commented: But you can't really do that with React either, can you? I mean, you can host the .js files and such on a static site host, but you still need something to host the API, right? commented: I've experimented before with htmx and alpinejs for a static website. You can actually get quite far. commented: If you have alpinejs there's no need for, and no particular benefit to, htmx. commented: They serve different purposes. HTMX is great when you need to round trip from the server to update something or get more of something. Alpine is great when some front end state needs to be updated but no server round trip is needed or desired. commented: I use the two together regularly, and I like it, but there are some sharp edges. Specifically when the element triggering the request is in a table, or when the response that comes back has alpine attributes on it. They haven’t been awful to work around, but I’m thinking about using alpine-ajax next time I expect that I’ll need to interact heavily with alpine in fragments returned from the server. It seems like the sugar that makes alpine feel like htmx when a round-trip is needed, with less fiddling around client state. commented: <div x-data="{content: ''}"> <button @click="content = await fetch('/some/html').then(res => res.text())"> Push the button, Frank. </button> <div x-html="content"></div> </div> For more advanced cases you can use morph. commented: Sure you can. With a service worker commented: And with the upcoming htmx 4 you won't even need that, you'll be able to just hook in your own fetch() function and tell htmx to use that. The fetch() function can become effectively a router that can return content from the page itself or even fetch it from remote sources. commented: I like the idea of htmx, but I wonder what is the expected flow on the server. Are you supposed to have a different completely independent template for each button? That's gotta become a templating hell eventually, no? commented: It‘s basically the same as any other webapp, just that you render partial HTML documents instead of JSON. If you use „real“ CSS instead of Tailwind, you can get by with very universal templates consisting of bare-bones HTML. Besides, you can organize your SSR-code in components, too. It‘s different, but not templating hell by any means. commented: It's not strictly about HTMX, but in a Rust codebase I use maud for templating and have as many functions building html things as needed. I have functions returning buttons, forms, etc. with the same classes, etc. . And I have functions making whole pages with elements of pages being arguments to it. So I reuse html just like a I reuse code. I'll have render_page, or I'll render_navbar. For more complex things, I'll add a a builder pattern with bon.rs to make things customizable, etc. Everything is typed, and I can tell that to render a navbar, I need to pass a user session, no room for typing mistakes, mismatched tags, etc. The requests handler just returns a whole page or just a given element, or even one or the other based on htmx header. It's quite easy and natural actually - reusing code and passing values is ... the most basic there is in programming. Not sure why web devs keep inventing so many layers of abstractions there. Especially trying to maintain a separate template in a separate file, using separate templating syntax, etc. seems completely counterproductive. Use the code, Luke. You already have a programming language, why invent another one just to look at something so ugly as raw html. commented: You don't need separate templates for every button, you can define them at whatever granularity makes sense. Look at how it does swapping. The algorithm is pluggable and you can make sure it preserves element state for everything you need, so you can swap a full "article" or "card" or whatever without the user noticing. I think it's nice how the paradigm encourages creating a nice set of independently renderable components. commented: Two ways to remedy that: use template fragments so you can render a whole page or just a part of it use hx-select to pick just part of the response to swap instead of its whole body commented: these are good answers, and the general explanation is that there isn't a 1:1 correspondence betweeen the data and presentations like in an ORM. Template fragments and filtering sub-trees can't help if you have infinite interaction flows possible between the frontend and the backend. commented: Oh no a template for each different kind of page we render. How will we survive this glory commented: You can use JSX or similar technologies on the server so that template partials are as easy as defining a function. See eg https://github.com/yawaramin/dream-html/tree/todoapp/app .