Join me while I learn HTMX and talk at you about it
Twitter: @htmxlabs
So I just wanted to put an idea out there today because I've been reading on Twitter. There's a whole bunch of stuff about, kind of a battle between the server side rendering and the Javascript's, client side first rendering. All sort of started by this tweet, which I'll include in the show notes, that was basically saying like, this is completely unacceptable, look how slow this is, and there's a little, you know, drop down. You click, nothing happens. You wait, you wait, and then the server, you know, then it loads this, content inside the drop down.
Lazarus:So and then like you find out, okay, this is like on a throttled network and a lot of people have pointed out, not only did the original poster not mention that it was a throttled network, you know, if you do this same thing you run some throttled network through a VPN in Australia or whatever, with something like Google Calendar. So so the original thing was a a screenshot of the Hey, email app and the calendar aspect of it. So someone did the same thing with a Google calendar, putting the same throttling on and it's, you know, there just was nothing. It's just it doesn't that's all front end client side stuff and you click something and it just doesn't work because ultimately it has to load something from the server. There's no way around that.
Lazarus:So if you have an extremely slow network that takes 3 seconds to do a single request then, yeah, some things are gonna be slow. But people were sort of using this as an arg like, basically like this negates any of the positives of, you know, a server side setup. So that's kinda what's been going on. And and that just made me think about, you know, that's kind of that's something that HTMX is you have sort of some ways around this, you can handle it in a nice way, but ultimately you are getting things from the server. If that connection is very slow, you're gonna wait for stuff.
Lazarus:And it doesn't h t m x doesn't try to, like fake that something is there or that some that everything's fine, that the network is fast. Right? It doesn't it can you can add stuff to show, okay, here's a re a request is happening. It has the special classes for the indicators. It has a checks indicator.
Lazarus:You can add loading things, you know, but ultimately it's not trying to it's not basically doing what they would call an optimistic UI, where you could click in, you know, the the example of this would be a a drop down. It has to have data from the server inside the drop down. Right? Otherwise, it's fine. You would just load it ahead of time and it would just pop up and that's fine.
Lazarus:So there must have been some case in this particular instance where the data that was inside the drop down had to be loaded from the server. So let's just use that as the constraint. So an optimistic UI in this case might guess at as to what that data is or if it didn't already know what it should be from the server, It would maybe put put those like, you know, you could do a loading state that has like those pulsating gray images that tell you like something's about to go in here. So that would sort of be considered an optimistic UI. A more optimistic UI is if the JavaScript client side front end knows fully what should go in there because it contains its own model of all the business logic and all the, essentially what you would get from the database inside it.
Lazarus:And this is sort of what a lot of react style view Vue JS style apps do. You front load all that information, you front load all that JSON and everything, so that when you click on this drop down it doesn't need to get it from the server. Or if it does need to get it from the server, it already has a guess. It already has a local version of what it thinks that will be. And then maybe it goes to the server to verify.
Lazarus:And that's kind of the optimistic idea. It it's optimistic that it has the right information, but it still needs to check. The more common version of the optimistic UI is like a Trello board. You may have seen that you've got, let's say 4 columns to do, working on, to review, and completed. And you just create a to do on the to do.
Lazarus:It's a little card. When you're ready to start working on it you move that card, you just click and drag that card over to the, working on column. Right? If you just let the server side do that, you know, you can have a drag thing, but you then need to wait until the server comes back with a response and redraws the page to show that it's there. So after you click and drag, when you let go, your little box disappears while the server request happens.
Lazarus:Let's say that's a slow server request, then it comes back and then it puts it in the right place. That's not an optimistic UI. That's just server side rendering. You know, I would call it, you know, h t m x kind of, that's how you would probably do it by default without a lot of thought put into it. You would just, you know, have that set up.
Lazarus:Optimistic UI would be everything is on the client side. When you drag that over it just in the dom moves it over. Right. It's just there. Now it's in the new dom.
Lazarus:It's actually a virtual dom that it puts it into. But you are in that when you drag it, it's there, and and then it sends your server request to say, okay, put this there and then, you know, basically, optimistically, it's gonna work. It's fine. You need to move this from one place to another. If the server says, no, actually, you know, you're timed out or there's something wrong with your authentication or that to do card has been deleted since the last time you checked, then you'll get maybe some error message and then the card will have to go back to where it was.
Lazarus:But most of the time, it's just gonna send a request to the server saying here's the thing that's supposed to happen. Did that work? The answer is gonna be, yeah. Sure. That's fine.
Lazarus:So it's basically just sending like a verification after the fact. But for the user experience, you just clicked it and dragged it, moved it over, everything worked fine. You never see the server stuff happening in the background. You never see the check. So to you it feels like, that's all happening, you know, real time, front end.
Lazarus:That's a good experience. And this is really like this is the core of a lot of this is why the front end, first kind of team exists. Like they feel like this is the ideal UI, all this optimistic UI. And, you know, I don't necessarily think that that is the, you know, ideal in all situations. I do think there are times when the optimistic UI is is very good, very useful for the user.
Lazarus:You know, what's the trade off there? The trade off is you're putting your entire app into the client side, into the front end most of the time to make this happen. And you know, you can start sort of working with Alpine JS and, and HTMX and some other stuff to to try to get some of that optimistic UI. And I have not really done much of that because honestly, most of the time you don't really need it. I've I don't think for a lot of the stuff that I work on for the sort of business applications, you know, if you click something and you get a little loading spinner and then it updates, that's fine for me.
Lazarus:That's fine for most of the things. And usually, most times that is not it's not slow. It's not a, you know, you can get immediate responses, especially if you're just having these little snippets of HTML moved around. And and you can add little niceties to it. You can add transitions and stuff like that.
Lazarus:So I don't see, you know, I don't see that as 99% of the time, I'm not fighting for that optimistic UI need in the way that I think a lot of people who have think of that as the that's like your starting point. You have to have that optimistic UI experience or else, you know, why bother making an app for users to to do. So I think, you know, that to me feels a little bit like the core of this sort of discussion, server side versus client side. Other people may disagree with that, but that's kind of the the big benefit that I see from the client side and the big limitation that I think people put onto the server side where they're like, well, I can't, I don't want to be limited. So why would I ever go for something that limits me?
Lazarus:Right. So that that kind of makes sense. So I guess what I'm what I'm wondering right now is, is there a is there a fundamental limitation, or, is there some reason why opt like, is there an incompatibility between an optimistic UI and something like HTMX? Like at a fundamental level, are those 2 things completely at odds or is it more like, well, HTMX lets you kind of work around that and maybe someday we'll also provide that. You know, I don't know the answer to that.
Lazarus:And this is why I'm not I'm not trying to, I just kinda wanted to to think about it out loud and and, you know, maybe get some maybe talk to somebody else and get some feedback, for what people think. So it's almost like this optimistic UI, you could think of it as like the final boss of h t m x. You know, if h t m x beats this, it beats the game. Right? Because this is the thing that holds back server side applications in people's minds.
Lazarus:Whether it's fair or not, DHH had a lot to say. He's the the guy who created, you know, Hey, the company that that created Hey, and Ruby on Rails. You know, his opinion on HTML over the wire, which is this sort of HTMLX, He has his own hot wire, LiveWire, there's a bunch of them. Phoenix Live View. So all these things that kind of fill this space of this exchanging HTML over the wire rather than dealing things with JSON and doing things with the virtual side, and the front end.
Lazarus:So they all kind of, you know, there was a big sort of argument over what is necessary. But my one I'm just wondering, is that incompatible with all these things? Is an optimistic UI with all these sort of niceties of that of that? Is that incompatible because with this kind of hypermedia as the engine of application state, that hate us or whatever you wanna call it, hate us. That's the idea that you can't do something that is not part of your DOM.
Lazarus:So, you know, your DOM is your state. That's your application. There's no hidden things. There's no background virtual model that's actually deciding what's happening. Your DOM is the application state.
Lazarus:So does optimism make sense if your DOM is the app application state? Do you want to have, you know, in that example of a Trello board, you know, you drag your thing over, you now have sitting there, the Dom now has a card in the wrong place. Like your server is your source of truth. Your server decides what should be where, what actions you should have. Right?
Lazarus:So do you want is it okay to have just a piece of your dom that might have buttons in it, it might have an edit button, Is it okay to just have that exist, in place without it being verified by the server? You know, if you start clicking that and doing stuff, it's optimistic. Sure. But what if it's wrong? Right?
Lazarus:So how do you handle that case? And and maybe this is like a core limitation slash just, you know, I don't even wanna say limitation because, optimistic UI is is not necessarily always a good thing. You know, for that reason, you could do something on your front end and then start clicking around like crazy. And all of that is worthless because, oh, it's actually, it looks like it's there. Your optimistic UI was very optimistic, glass half full.
Lazarus:Great. But you can't actually do anything because it's not actually saved like that on the server. So you start then clicking through there, it's not gonna work. So maybe it's better to have it not be optimistic. And instead, you know, that that could be, you know, what do you do instead?
Lazarus:So you can sort of disable things. That's maybe one way to handle that. You could maybe, you know, just do the sort of grayed out kind of thing to indicate that until the server has checked it off it's not okay. So let's see, where am I going with this? I guess if the data is supposed to be coming from the server along with everything it needs, how can you really guess what that is?
Lazarus:Can you guess? You know, we don't wanna end up in a situation where we have to mirror the client and the server and keep them in sync. You know, that's one of the nice things about doing it with something like h t m x and where you have the the server side is you know, what's on the client side is is what's on the server side. You know, they match for a reason. So can you guess what it's gonna be?
Lazarus:I don't know. You know, that's what they try to do, with the virtual dom and with and with everything like that. So where does that leave people who like HTMX, but also want to have the possibility of optimistic UIs. You know, they have the stuff that's already there, the loading states, the spinners, and that does take you a long way. The next step is adding some Alpine JS or some vanillajs in little ways.
Lazarus:But what's what's like the neck like, is there some equivalent? Is there, like, an extension that could be built? You know, like, are there sort of the h t m x scientists who are looking into this? Like, are they looking into what optimism looks like with HTMX. And I have no idea.
Lazarus:I don't I don't know. Like, conceptually, I'm trying to figure out are they at odds fundamentally? Is it just like this is not going to happen or is there a nice way to do it? And and let me just think. So how could you do it?
Lazarus:So how could you do it? You have let's say we're doing a Trello. And it's probably someone's probably done this with HTMX just to, like, you know, show show what can be done. I have no idea. I have I have not looked this up.
Lazarus:I'm just talking out loud. So let's say you wanted to build a Trello board with h t m x. What would you do? Okay. You've got your 4 columns.
Lazarus:You have your card. There's probably like a nice javascript, I'm trying to think if there's a built in I think you can use draggable. I think that's something that's just like built into the browsers. I'll have to like, look into that later, but I feel like there's a draggable. So you could put draggable on your element.
Lazarus:And when you drag it into the next column, like, what could h t m x do? And let's just assume this is we're not using anything else. We're not using Alpine yet. It could, you know, have there could be, like, I guess an extension or if it wasn't part of core h t m x, there could be some sort of extension that, you know, maybe you've defined a target in your so so on on the event draggable. So on like drop, on drag drop.
Lazarus:I This I'm not looking this up, so just just, bear with me. Let's assume that we have a draggable thing on the browser, right, built into the browser. It also triggers an event. Okay. With HTMLX, you can tap into any event.
Lazarus:Right? So we're good. We're good on that. We do HX dash on star, h x dash on, drag drop or whatever that event is called when they let go. The target is going to be, what is the target gonna be?
Lazarus:Maybe the target is the whole list, that seems a little too a little too vague. But okay. It's gonna be there's gonna be some sort of get. So it has to because it has to send a new request to the server to update the whole list. So maybe we update everything, you know, let's just keep this like pretty broad here.
Lazarus:So the get okay. Actually, no. It's not a get. It's a post. The post is to update which column or the status of that particular card.
Lazarus:Okay. This is better. And that's going to return with the specific column. It's gonna the target is going to be this specific column. Okay.
Lazarus:We don't wanna put it into where it's dropped because we don't know where they're gonna drop it yet. So you can't set the target yet. So the h x post is going to be, you know, update this this, this card. Gosh. But how does that even know?
Lazarus:How does that even know where you're dropping event is event is going to have information about where it was dropped. Right. So that is going to have to be sent with your request. Okay. So it's going to be sent.
Lazarus:So you're going to have, so in your HX on, you're going to have the drop event, and then you're going to have to send that information of the event to the request. When the request is received, it will have the information about which place it was dropped to. So that's where you're going to set your, set your variable, you know, set your your database to say, okay, this this Trello card, this card is now dropped into this status. And then from there you could probably do, like, instead of having to set the target ahead of time, you can either set the response header to do retarget, h x retarget, and set the target like that. Or you could do the h x swap o o b and set an ID for each of the columns.
Lazarus:Right? So each of the columns has a unique ID and when you want to update one of the columns you just do h x swap o o b, you send the snippet with just that column back. Okay. So so that's our setup. So we are just, I'm just gonna recap because I have it sort of in my head.
Lazarus:We have our trello board. Each column has a unique ID. Each item on there sends a post with that item, that card ID, and the trigger is on the drop. And we get that event out of that drop, out of that out of that not the trigger, the h x on, which is a little different than the trigger because the trigger just has some default ones. H x on lets you use any event.
Lazarus:So the h x on also is able to pull, when you're able to send in your variables, the values of where that was dropped. So you can send the element, you can send the ID, probably you would send the ID just of the target. So the target, the, you know, the column that it's in, that's gonna be essentially your status, because each each of those 4 columns represents a different status. So the problem with this is that after you drop it it's just gonna disappear, I think, you know, when you use draggable. I don't think it, like, puts the thing in the new place.
Lazarus:How would it know all this stuff? Right? So by default you would now be, waiting for it to get sent to the server. Let's say you're on a slow connection. It looks like nothing has happened.
Lazarus:You've dragged it, and now it's over there. It disappears, and then you wait for the server, and then when the server loads it loads to that column. Updated. And actually unless we load the other column too, then it's still gonna be in the other column. It doesn't by default delete from the other column.
Lazarus:So we're gonna have to add something to either update both columns or to delete the event, you know, or delete this, card after the draggable event. So there's kinda different ways we can handle that. The easiest one would probably be to just send back the updated html for both columns using h x swap o o b. So, you know, in our response, the before column and the after. So whatever status it was before, we send that column.
Lazarus:Whatever status it was after, we send that column. So how would optimism work into this? Like in the 8 in you just using something with h t m x not using alpine. And that's really tricky to think of because, you know, we do sort of know what that card is gonna look like after it's in the new column. So it seems like it should be hard, but but in general, we don't know how our server is gonna render stuff.
Lazarus:Right? We're we're requesting just here's the target where we're putting stuff. We don't necessarily know what the server is gonna send back. In this case, we do know because we're moving one thing from one place to another place. So what would it look like in HTMLX to add something like optimism to say, okay, here's the target that we want this to or wherever this goes.
Lazarus:So maybe this is like a a, you know, linked to the draggable. Maybe if it has draggable on it, then you assume it's not going to change. Right? Is that kind of a fair assumption? You're dragging something from one place to another.
Lazarus:It's not gonna change. So in that case, optimism could be, okay, you know, we have a little bit of a JavaScript code maybe an HTML HTMLX extension that if draggable's on it, it can just straight up copy that HTML and put it to wherever it was dragged. Right? And when the request comes back, it removes it. So what's gonna happen is the request comes back and it removes it, but then the request has the new data in it that has the actual thing, and so it replaces it.
Lazarus:So as long as it happens smoothly, the user doesn't see anything. It looks optimistic. So this is kind of a special case for draggable, and I'm just I'm I'm literally just free styling right now, so feel, you know, don't don't take this as, like, I know what the hell I'm talking about. But that seems like it would work. Right?
Lazarus:And maybe it's only works because it's draggable, you know, if if you do something like save. Yeah. Okay. So here here's a more difficult example. You have a form and you click save, and you want it to just, like, you know, if you're using all client side stuff, you can optimistically assume everything in that form is gonna save correctly and go over to your list of items, you know, your your to do list or whatever.
Lazarus:So the problem with this is you cannot do the same thing that we just did. We're draggable. We just assume all the HTML's the same. If you're saving a form, those are like inputs and text areas and drop downs and selects. That's gonna be a totally different format than your visual, you know, once it's been saved.
Lazarus:So you cannot just take the same HTML and move it over. So what could you do if you had some sort of optimism in HTMLX? You could let's just say I'm just like thinking here. But what if you defined a format or maybe not so much a format, but a a temp yeah. You could define a template, I guess.
Lazarus:An invisible template. So you know, you you have an empty div and your optimism plugin, h, you know, h t m x optimism, you could as you could say which template to look at. You give that template an ID. Call it like optimistic template, new item or something. So this is a format, a a and then you'd have to have, you know, place holders in that template for the different inputs, for the different selects.
Lazarus:So how you define those, maybe a little tricky, but maybe you just put a little JSON thing that's like or maybe there's some defaults, you know, you you give your template the ID's, or the name, or or some sort of attribute on each on each, field or on each, div or or element in there that matches to something on that form. And so what it will do is when you click save, if you have this h t m x optimism, plugin or, extension or whatever, it you know, you define h x optimism template equals, and then you have your ID for the template. It looks at that, fills all of it, and, like, copies that HTML and puts that I guess you'd have to go for a target as well, so your your optimistic target puts that where it should go. So immediately when you click it fills out that template, puts it in place, then it does its regular h t m x thing and gets the response back and fills your, you know, fills it out for real. And so the goal would be to have your template match exactly what it's going to be when it comes back, so that, ideally, you would not see any, you know, blip or there would be there would be no apparent delay.
Lazarus:And that's the goal with optimism, you know, no apparent delay. So those are sort of 2 scenarios, the draggable and the form that, like, seemed kind of theoretically possible for probably all kinds of problems with what I just put out there. But if we think of HTMX as, like, you know, this is a framework that you know, a library that, I've been using for almost everything recently and and because it's well suited for a lot of stuff that I do. And it mixes very nicely with all the different client projects I have, gives me some nice opportunities. You know, if there is a limitation of optimistic UIs, and if I have a project that really wants optimistic UIs, My question I'll just end with is just the same.
Lazarus:Like, are optimistic UIs the final boss of h t m x? Or is it fundamentally incompatible with the idea you don't want actually to have an optimistic UI? And I don't know the answer to that. And by final boss I mean, like, okay, if h t m x beats this, they beat the game. Right?
Lazarus:Like, in my mind, HTMX has so many advantages over some of these front end solutions, but that's one that anybody can point to and be like, well, if they can't do this, then I can't build my Trello app. You know? So that's fair. That's totally fair. And, you know, I don't think you always need that.
Lazarus:But if htmx has an easy solution to that, has something like that, do they, like, beat the game? I mean, like, do they is h t m x then anybody can use it for anything. You don't have this kind of, oh well, you know, I can't do that because I'm I need to have this client side thing. So, I don't know. I just think it's interesting.
Lazarus:And, I don't know. Let me know what you think. If you, you know, hit me up on Twitter or something like that, if you have any thoughts. You know, the podcast doesn't really have any feedback. It's mostly just me saying stuff.
Lazarus:So, it's always interesting when I when I hear from people. So, alright. Have a good one. Bye.