Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
htmx 2.0.0-beta1 (htmx.org)
139 points by eatox on March 17, 2024 | hide | past | favorite | 85 comments


I am interested in learning about how something is being used and in what context, instead of what it has to offer. Can anyone tell me if they are using HTMX in a proven environment, like a user-facing environment?

I think adopting HTMX as a framework would be difficult to switch from a React, Vue, etc. environment. I think using it inside internal tooling or a hobby project will not be able to justify its merit.

I understand that it is just a simple framework and it addresses an industry-related issue, but migration is a lot of effort. Does HTMX really provide enough value to justify the engineering investment required?


I used htmx to build a now in production multi-step payment form that's currently in use by several hundred thousand people per month. It's been great, but not perfect and I would say a less well trodden path to get the edge cases right. I would absolutely say it's been a simpler overall solution for us as a small team than a full js client side framework would have been. Things that were hard to get right were setting up loading indicators, error display, keeping step/form state on browser history back/forward, tab sleep restoration after htmx navigation(especially tricky), and injection of third party form elements that had to be injected/remove and re-injected on back/forward between steps. I would be surprised if these sorts of edge cases weren't already handled by a popular js-frameworks but can't say for sure. The site load is very fast and we haven't even rolled out client side js validation on forms the server validation responds so fast. We are planning to use more htmx across other apps at present, so overall positive hypermedia for the win.


Super balanced & informative writeup, thank you. Can you tell me what you mean by tab sleep restoration?


Last year chrome started discarding background tabs to save memory, probably should have said discard rather then sleep it's been a while since I worked on that. Our user base keeps tabs in background often in mobile devices and we saw some reports of it. https://arstechnica.com/gadgets/2023/02/chrome-110-will-auto...

When you do an htmx navigation to a new page, a discarded tab will "restore" only the last htmx fragment loaded, not the entire html page with style tags. Fix is to use unique url on push that isn't in local cache which forces a server reload on tab wake from discard.


Try adding the response header:

    Vary: HX-Request


Yep, probably browser caching:

https://htmx.org/docs/#caching


Next time I work on it, will try to see if that resolves it.


That worked for me. Thank you.


I‘d also like to know what you mean by tab sleep restoration.



Htmx is what you want for making websites.

This means, that almost all uses of react and friends are wrong, a waste, or an unnecessary complication.

So, if you are serving HTML, then htmx.

When you reach for react? If you are making an app of the kind that you should have use a non-web thing (because is now necessary to bend with major complicated hacks HTML to make a clone of Photoshop).

(and in short amounts like creating complex widgets like maps, selects, etc).

---

I work for eCommerce, and there is terrible to use React: It is too easy to make "hacker-friendly" websites when using it: INSTEAD, you MUST validate, format, process, render, and display all on the server side.

For me, I retain all the logic on Rust, display HTML, and just put some extra interactivity with htmx, that because at the server-side is the same as without, means I CAN'T INTRODUCE A SECUIRITY BUG.


Curious what part of React you think makes it "hacker friendly". React can be done very simply, and I see no part of it that makes it any friendlier to "hackers" than HTMX.

Seems that HTMX requires unsafe-eval?

https://github.com/bigskysoftware/htmx/issues/2260


SPAs require implementing safety checks on both sides in 2 different languages. Many junior devs believe the client code is trustworthy and put important validation only in the client. I’ve worked with many codebases like this. If there’s only one place to specify validation, it should always be the server. So server side frameworks have this built in to their model and thus are less susceptible to this whole class of bugs.


>SPAs require implementing safety checks on both sides in 2 different languages.

Nodejs is quite popular. One language works on front-end and back-end. Like any language, security is up to the developers.

>Many junior devs believe the client code is trustworthy and put important validation only in the client.

Who is letting "junior devs" make these decisions? It sounds like they deserve to be hacked.


> SPAs require implementing safety checks on both sides in 2 different languages.

This isn't exclusive to SPAs. For example, I am a .Net dev, and I have both front-end and back-end validation in most of my applications without ever using any SPA frameworks.

If I am in a pinch for time, I sometimes just drop front-end validation completely, and let the server handle the validation and then have the front-end handle the server validation responses accordingly.


Actual hackers, the ones who try to hack your e-commerce site.

For such things, if you're not doing everything Server Side to Render fully validated and sanitized data safely, you should be.


If you do server-side rendering of your React application, then it would be very similar to htmx from that perspective.

If it’s is purely a SPA, then all business logic would be behind secure APIs, so I don’t really understand your point.


That sounds like an irrational fear of front-end.


Nothing specific to React but having both client-side and server-side validation means that any deficiencies of server-side validation will be concealed and go unnoticed (until exploited by an attacker).

In contrast, server-side validation only means any validation deficiencies are more likely to be discovered during legitimate usage since the client-side validation is no longer covering up for it.


I think you have it backwards. You _first_ do server-side validation, then you add client-side validation _as an optimization_, so that invalid requests are not even sent.


My point is that once you do that any subsequent deficiencies in your server-side validation become invisible during normal usage (because the client-side validation will prevent you from even trying).


I’m guessing the issue is devs putting business logic constraints in the client and not duplicating them in the server


We use htmx (mostly via our django-livecomponents) on our production website, for several public facing features. We've initially replaced numerous small things that were built with Alpine before, and once we've gained confidence we rewrote our whole messaging app from reason/react app.

Fun thing, customers find the new version (htmx/django-livecomponents) to be more responsive than the old version (react+REST). New version is less lines of code and easier to hack on die to fewer context switching.

Give htmx a try, it's worth a shot!


> django-livecomponents

Sounds cool. This one?

https://github.com/om-proptech/livecomponents


Yes :)


This feels like the wrong way to look at things. It's not that it's "difficult" to switch from React/Vue to htmx - it's that it's easier to build with htmx in the first place. I wouldn't throw out completed code, but I'd seriously consider using it next time you start something new.

The general philosophy is that "React etc are great for some things, but they are being used way outside of their sweet spots". There will always be a gray area - and your existing habits and skills are also a factor but for some of us - the "SPA framework" approach always smelt fishy for typical web builds.


I'm using HTMX with Django for totem.org[0]. My over all experience is good.

I'd say the main thing I like is testing. With a JS framework I have to have tests spread over both JS and Python, with HTMX I can mostly just focus on Python tests and assume the HTMX is going to work correctly. There's a good, stable testing story for Django, so I know the tests I write won't have to be rewritten all the time when dependencies change. I just don't write many JS tests because stuff changes so fast.

The main downside I have with it though, is I just can't seem to remember how to use it. Every time I need HTMX I have to look at code I've written or go to the docs. There's just too many options with names that are confusing (hx-select, hx-swap, hx-swap-oob, hx-target?).

Aside from that, it's also a pretty large dependency. I'm also using Solidjs to mount web components (which is a pattern I love) and HTMX is a majority of the JS bundle. That was surprising to me. Maybe version 2 will be smaller?

[0]: https://github.com/totem-technologies/totem-server


> The main downside I have with it though, is I just can't seem to remember how to use it

I've noticed the more I use HTMX, the more I tend to end up needing to use the JS API too.

For example, if I have an HTML table with inline editing, and I need there to be validation on what people are entering. So, I have HTMX firing when people save their changes via a button, then I need to use the JS API for conditional logic e.g., if valid, then update table. If invalid, then display some kind of message or whatever.

HTMX has been working great for my needs, but the more I tend to get into the weeds of the JS API, I cannot help but sometimes question whether I am truly gaining that much more over using plain AJAX requests. However, HTMX is definitely more concise, so that's a nice benefit I suppose over a unmaintainable slew of AJAX requests.


> So, I have HTMX firing when people save their changes via a button, then I need to use the JS API for conditional logic e.g., if valid, then update table. If invalid, then display some kind of message or whatever.

Couldn't that be handled server-side as well? I have my validation logic server-side, and it either returns the updated table row (or other element), or it returns the form again with validation/error messages, fields highlighted where the error occurred, etc.


> The main downside I have with it though, is I just can't seem to remember how to use it. Every time I need HTMX I have to look at code I've written or go to the docs. There's just too many options with names that are confusing (hx-swap, hx-swap-oob, hx-target?).

Perhaps this could be smoothed over with snippets or an autocomplete extension for whichever text editor is being used?


Maybe. I think it's just a high-level library for a specialized domain. It's not like imperatively coding JavaScript, spelling out each action step-by-step. The fact that I just need a little of it to do a lot means I just don't need to use it that much, and then I forget how.

I could see a better tutorial experience with live examples for common patterns. Something like SolidJS does (https://www.solidjs.com/tutorial/introduction_basics). That would be a good reference. Alternatively, a copy/paste pattern library, like what a lot of people are doing with Tailwind (https://daisyui.com/components/).


It depends on your options for managing state. If you can build a largely stateless UI, that can update from the server via a form submission or query parameters, then it’s a big win, both in terms of your code complexity and the complexity of the team you need to build it. You can still have lots of widgets on your page and even fancy CSS transitions to make it feel like an SPA if you really want. But if you’re making something very highly interactive or canvas based, with complex stateful UI components and gestures, then you probably have nothing to gain.

Anywhere I could conceivably get away with HTMX over React I would (and tbh I’d launch with no JavaScript at all before that). But if you’ve got a massive React codebase then you’re already in quite deep, both codebase and team structure.

All that said, some really high level apps are moving to WASM anyway, so I don’t know that an investment in React is safe for the long term.


Isn’t this really just going back to the server side templating days and using jquery to load html snippets?


The problem was that on the whole people didn't use jQuery to "load html snippets" and the architecture of jQuery tended to push people towards client-side spaghetti.

htmx encourages you to put most of the logic on the server and to keep the client lean and clean.


Yes, it's an implementation of the radical idea that we should deliver HTML (rather than a giant blob of JS) to clients purpose-built for rendering HTML.

See also https://hotwired.dev/


But without jquery, everything defined in html attributes, and hence the server responses can further define behaviour in their html attributes. Declarative, not procedural, if you want.


Yes it's that, but more. I enjoy the out-of-bound swaps and triggering hx events or specific targets of render via response headers.


I’ve been using HTMX on a greenfield project (not reimplementing something) and I’ve found it easy to work with and effective. Nothing magical, but simpler. Less effort, not more.

After being reminded of the importance of supporting low-spec clients[1] I’ve been testing without the HTMX library loading as well, and mostly that works like it should. I say mostly because I didn’t get the markup right everywhere yet.

I can see why some wouldn’t like it. But, it’s not a good/bad or works/doesn’t thing - it’s just different.

[1] https://danluu.com/slow-device/

Edit: typo, HTML -> HTMX


I help maintain a user-facing ASP.NET project running .NET Framework 4.5 that uses jQuery 1.0 for most of the UI. We launched our first new feature using HTMX back in November and it worked out pretty well for us and we plan to continue using it moving forward.

I also work on a React site and I wouldn't want to move away from it unless someone dared to utter the word rewrite.


The premise of migrating away from an SPA framework might make it seem weird, but I don't think that's the common adoption path.

There are a lot of server side templated web facing applications out there, and htmx provides a simple and gradual UX improvement with very litte investment.

It depends on what you deem "internal tooling" but a lot of b2b software isn't built to be flashy.


It’s possible to build quite dynamic user interfaces with htmx - even games :-)

—> https://zakuchess.com/

One benefit I found to it is that it allows developers to keep the business logic entirely on the backed side, without having to duplicate any effort on the frontend side.


I don't know if HTMX is an alternative to React/Vue/etc, it always struck me as an alternative to a purely HTML site, which I think 95% of web apps should be. I don't know what we get from avoiding full page loads that we don't then lose when we make sites janky and taking ages to load.


Well there has been this push forever to eliminate desktop apps in favor of just web apps. Now, imagine we do this crazy thing that most businesses are convinced they need to do and we do what you’re saying, which is make all web apps do page reloads. All of sudden (maybe not so suddenly) computing in 2026 is much more frustrating than it was in 1996 (86?).


I've mainly been a full stack dev for most of my career, though I do have a some experience in low-level domains. Lately, I have been mulling over if I want to jump into different field of development.

I know Rust is gaining traction, and I have always found languages like assembly, C/C++ to be more enjoyable than the higher level languages. So, I might try and take a stab at Rust and see where it can take me. I'm just so fatigued from all the web dev stuff. The whole field feels too scatter-brained to me.

Instead of trying to solve useful problems, I feel like much of web dev's frameworks are just focused solving an already solved problem with slightly differing and dogmatic opinions.


Well that is exactly right. These web frameworks, while they have their uses and have has some improvement on software engineering of web apps and have enabled sone benefits for users … largely the churn of these web frameworks with all these cute names are just reformulating the same technology over and over just with different opinions and aesthetics. People act like “technology changes all the time” but that’s not really what’s happening. We are “rediscovering” things so much in Web dev because we are still fundamentally doing, for the most part, what CGI programs did 30 years ago, pushing text back and forth with http verbs and return codes. Then, we make a huge deal when we get a web app to do something a desktop app could do 10-30+ years before.


I don't know if you've computed in 96, but computing now is orders of magnitude more frustrating than then.


Yeah … that’s why I put the “86” in the parenthetical but I think it’s worse then 1986 too. I worry about it getting more orders of magnitude worse!


For now I’ve decided to sit on React/Nextjs and actually focus on solving problems rather than playing the framework/UI library game that leads me nowhere.

I totally get your sentiment.


By “sit on” do you mean “keep using” or “avoid”?


Keep using… Apologies for the lack of accuracy.


You might want to check out https://hypermedia.gallery

Disclosure: I built it (without HTMX).


So, I absolutely love htmx, and this new version offers some incremental improvements that make things even better (unless you were using WebSockets or server-sent events, I guess, but the plug-in model doesn't look too bad?).

Unlike all-or-nothing approaches like React, htmx allows you to add just the right amount of partial updates to your web app, using just the technologies that were already there to begin with. I realize that this approach doesn't appeal to everyone, but being able to map simple requests to simple responses was an absolute life-saver for my projects many times over.

Migrating to a truly-truly minimalist approach (see: https://www.stefanjudis.com/notes/htmz-a-176-bytes-htmx-alte...) is still on my to-do list, but for now, I'm quite happy with the htmx status quo.


There's a kind of satisfaction I get when I browse hypertext that loads in less than 100ms that I never get with slower sites.


I'm just glad I was able to submit my patch before 2.0 released: "Add config option to ignore nested oob-swaps instead of processing them (#1235)"

Setting this config makes it easier to use 'template fragments' with oob-swaps, since you can set the hx-swap-oob=true attribute on the element and reuse it to render a whole page or just a fragment of the template. Very nice to use with Go template blocks for example.

https://htmx.org/essays/template-fragments/


There's a lot to like about htmx, but one thing that does not sit well with me is its opinionated design decision that it will only render content if its sent with a 200 OK (tech TL;DR: shouldSwap defaults to false for non-200 response codes).

Most sane services will only return a 200 OK if, well, things went OK. Most sensibly designed services will return 400 range if an error has occurred that has been handled gracefully.

I am aware that you can kludge a hack in the form of a JS snippet to force htmx to render content on !=200, but it shouldn't be that way IMHO.


> Most sane services will only return a 200 OK if, well, things went OK. Most sensibly designed services will return 400 range if an error has occurred that has been handled gracefully.

Yes, but you are not designing your MVC controller as a REST service, and are not trying HTMX to your REST API directly. This makes sense if you think of it from this perspective, like the classic MVC view-rendering controller behind your HTMX page.


Can you elaborate on this? I've seen HTMX and considered trying it out in some projects, but would like insight on how to best use it in a stack.


In htmx 2.0 we make response code handling a declarative situation:

https://v2-0v2-0.htmx.org/docs/#configuring-response-handlin...

A few people on the core team agree that htmx should always swap. It was perhaps a bad decision on my part, but it is fixable w/ a bit of config.


This is all handled in an extension:

https://htmx.org/extensions/response-targets

I don’t know what kludge you’re referring to, it requires you to add basically two attributes to your HTML, it’s really no hardship at all.


> This is all handled in an extension

And why should I need to load an extension to handle a 400-series ? That's just nuts.

The kludge is loading the following JS snippet on your page:

   if(evt.detail.xhr.status >= 400 && evt.detail.xhr.status <= 499 ) {
      evt.detail.shouldSwap = true;
   }


Every web framework has error handling features. These are HTMX’s. It’s two HTML attributes and you’re done, if you don’t want any of the additional functionality.


I didn’t know that, that’s interesting. I’d expect 100-199 responses to be able to render a result as well, at the very least.


All response codes should really be able to contain content that doesn't look terrible. A 404 can be a nicely formatted "not found" page that's consistently styled and looks like the rest of the app, for example.


> I didn’t know that, that’s interesting.

Yeah, it caught me by surprise first time I used htmx. I spent forever trying to troubleshoot why it wouldn't render the error message, then I discovered it was the old "feature not a bug".


Does general usage of HTMX require `unsafe-eval` in your Content Security Policy (CSP) to allow JavaScript eval? Or there's workarounds that still keep things simple?


Probably yes if you use the inline event handler feature it has.

https://htmx.org/essays/web-security-basics-with-htmx/#bonus...


From the link:

> Some htmx applications make use of inline scripting—the hx-on attribute is a generalized attribute listener that can evaluate arbitrary scripts (although it can be disabled if you don’t need it). Sometimes inline scripts are appropriate to preserve locality of behavior on a application that is sufficiently secured against XSS, sometimes inline scripts aren’t necessary and you can adopt a stricter CSP. It all depends on your application’s security profile—it’s on to you to be aware of the options available to you and able to perform that analysis.

Is hx-on required often? How clunky does it get to avoid hx-on everywhere?


Not unless you plan on explicitly executing sent snippets of JS, iirc


How much of a performance gain does htmx grant compared to other front-end frameworks? A talk from 2022 implies a significant benefit relative to React but in front-end development years that's an era ago: https://docs.google.com/presentation/d/1jW7vTiHFzA71m2EoCywj...


I'm not someone who usually gets excited by new major releases of frameworks/libraries but this one feels different. I got my start with CRUD PHP websites with jQuery. I've been using HTMX for the last year and it fills me with nostalgia while also allowing me to move faster when building UIs.


> DELETE requests now use parameters, rather than form encoded bodies, for their payload (This is in accordance w/ the spec.)

As someone who rarely use DELETE requests, what's the best practice for passing parameters and why?


I tend to make DELETE work without parameters, but allow them in the body (JSON) for non-essential but helpful options. And example is allowing a flag to override delete protections. I doubt this is a “best” practice but I’ve never had a problem with it, or been asked to change it for compatibility.


I do this too. And some resources require two DELETE requests - the first with parameters and the second one (after a minimum time) doesn't.


I think this is the relevant bit from RFC 9110:

> A client SHOULD NOT generate content in a DELETE request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported.

By way of analogy with POSIX, `cat` (GET) and `rm` (DELETE) both just take a file path, whereas writing or overwriting a file (POST/PUT) also require something (a request body) to write.


The resource to be deleted should be identified in the URL, so there is no need to pass a body. This is the same for `GET`.


This is how I've used DELETE. Something like DELETE /users/{uniqueUserId}. In ~10 years of building CRUD apps I don't think I've ever sent a body or query params with a request.


Some tools let you pass a parameter to indicate that you only want the request to take effect if the requested resource is in some specific state. For example, Google Cloud Storage uses headers to allow you to set preconditions that must be met before the action takes place. For DELETEs you can use this to say "delete this resource but only if its generation (sort of a timestamp) is exactly $foo", where $foo is the generation last known to the client.

https://cloud.google.com/storage/docs/request-preconditions


What about where you're not just deleting a single entity by id? Like, for instance where a user can bulk select multiple items and then choose to delete them all (like email for instance), or maybe deleting by criteria, like "delete all Entities created before time X"


My gut says I would use query params though I typically stick with 1 action effects 1 record. I can't recall any specific times when I built bulk item management into an app but I'd say that's a personal preference on my end.


Query params.

DELETE cannot have request body, just like GET cannot have a request body.

(Well, it's a syntactically valid HTTP message, but there's no semantic meaning to the body.)


Question: what is the proper verb to use with a query? I always thought of it as a GET and passing the query via the body. You are GETting information, rather than trying to add information.

For that matter I've never quite figured out when to use POST vs PUT. POST doesn't feel right for a query.


DELETE and GET can have bodies, the spec is just vague about it. Elasticsearch commonly uses request bodies for GET, treating it identically to POST. It's not always regarded as a good idea, but it does work.


That's why I said:

> (Well, it's a syntactically valid HTTP message, but there's no semantic meaning to the body.)

To quote RFC 9110:

> Although request message framing is independent of the method used, content received in a GET request has no generally defined semantics, cannot alter the meaning or target of the request, and might lead some implementations to reject the request and close the connection because of its potential as a request smuggling attack (Section 11.2 of [HTTP/1.1]). A client SHOULD NOT generate content in a GET request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain.

For this reason, Elasticsearch also accepts queries as POST.


Newretrowave fan here. Who would have thought that the creator of htmx listens to synthwave.


sick! i’ve been using htmx for a few personal projects & i have to say, it feels like exactly what i was looking for.

light, well documented, snappy, easy to work with - i love the idea of endpoints returning pure html instead of json - it feels obvious.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: