Join me while I learn HTMX and talk at you about it
Twitter: @htmxlabs
Alright. So I'm joined today, by Henning. And actually, I don't know how to pronounce your last name, so I figured I'd ask you here.
Speaker 2:Perfectly fine.
Speaker 1:Coke or Cach or something else?
Speaker 2:It's Koch. It's like Koch in German.
Speaker 1:Alright. So yes, I'm joined by Henning Koch and, basically you are the creator of Unpoly JS. And Yeah. Yeah. So I so I wanted to, you know, check-in.
Speaker 1:This is sort of, you know, people may be familiar with, it as a JavaScript. Do you consider it a framework or a library? Just off the, you know.
Speaker 2:I think it's a framework because we call your code. You don't call us. But it plays very nice with your code.
Speaker 1:You don't call us.
Speaker 2:With your own if you have another external dependency or something, it's not possessive about the DOM or something. So you can make changes to the DOM without unpolu blowing up. Yeah.
Speaker 1:Yeah. Okay. And so so it's kind of a, you know, one of the sort of hypermedia approaches. Yeah. I think of it as sort of, you know, similar to to HTMLX, in in the world of JavaScript kind of, you know, frameworks and libraries and stuff like that.
Speaker 1:So, yeah, I guess my my first sort of thing is just kind of, like, you're calling from Germany right now? Or where are you where are you calling from?
Speaker 2:In in Augsburg. This is in Bavaria, Germany, so in the southern part near the Alps. Okay.
Speaker 1:Yeah. Nice. So so how did you kind of, like, I guess, just just some quick background on, like, what's your sort of programming? You know, how'd you get into it? How long have you been working on stuff?
Speaker 2:Okay. So I've been doing web development work since, I think, the late nineties or something. So I started basically with CCI scripts and Perl and eventually discovered Ruby in the early 2000. Yeah. And, this is something that I've been doing since.
Speaker 2:So Ruby is, like, my, my first love as far as, languages go. And, this is also what I do in my day job. So, I'm I'm heading development at Magandra. We are a race consultancy in Germany. So we're doing a lot of, bespoke web applications built on Ruby address.
Speaker 2:But, of course, we also have, like, a big front end, part, like, every ambitious, application has these days.
Speaker 1:Yeah. So I know, you know, Rails has kind of their own and I work in Laravel in general and PHP in Laravel, and and they have their own server.
Speaker 2:That's nice. Yeah.
Speaker 1:You know, Livewire is sort of their version of, you know, non react, hypermedia style. Livewire is a little different, than I would say on Poly and HTMLX. It's a little more integrated with the back end, with the PHP. But I know Rails kind of has their own thing too. So are you did you sort of, you know, I guess where did un poly come from?
Speaker 1:Did it sort of is this something that you came up up with and sort of have sort of been building over the years? Or is it sort of like there was other stuff out there and you wanted something your own version?
Speaker 2:Okay. So so it's a pretty, pretty mature framework. So we, so we I started building this like 10 years ago. I think tomorrow it's 10 years ago. I took my 1st commit.
Speaker 2:And, back in that time, there wasn't, like, a very good Fortnite story for rails. They have this hot wire turbo thing now, but that's only, like, 3 or 4 4 years old. Yeah. Back then, we had turbo links in rails, which was, like, a very basic way to do in page navigations, but nothing fancy. You can only swa swap swap, like, the the whole body.
Speaker 2:And I think this was my main motivation and I'm, like, if if there's any origin library, that would be Turbolinks.
Speaker 1:So, like, so, you know, Turbolinks existed, but it was kind of so I I was programming around then in the same time period and I remember we had PJX was another one that was kind of like I tried out and but the the desire was to, you know, basically not have to do a full page reload every time somebody clicked. You know, that was kind of my, you know, and I started getting into some of the front end frameworks and experimenting with Angular and stuff like that. But, you know, I do remember sort of wanting to have a solution to, like you don't wanna necessarily rewrite your whole app, but you do want to, you know, load tabs by fragments and stuff like that. So was this kind of like so you you just started building your own, like, for your own projects kind of thing?
Speaker 2:Yeah. I mean, this was also the time where we, like, tried to find a better way to do front end. We also went all in on Angular for a while, but then, like, Angular 1 went end of life and you basically had to rewrite everything for Angular 2. And there was, like, the point where we did, like, this big retrospective and, like, it took a good look, an honest look, if we're really happy with what we built. And, because we always always thought once we get into these heavy SPA frameworks, like, like, everything would be structured and easy, but it it wasn't like that.
Speaker 2:Like, it
Speaker 1:Right.
Speaker 2:Was like a lot of code, a lot of dependencies, like complicated control flow. And, that was the point where we, like, revisited the idea of rendering on the server again. But we didn't want to do this, like, bespoke at every project anymore because every project has this this old jQuery snippet at the time where you, like, fetch some URL and then when you get the response, you, like, replace some fragment on the page. But Yeah. I mean, there are, like, like, a 1,000,000 edge cases you don't cover with that.
Speaker 2:And also, a lot of use cases you you could do if you invested a little more time into doing this properly and having some structure and standards around this. And that's what's, like, when we came up with Antoli and the idea of expanding on this concept of only updating fragments. And we realized that a lot of pain that we had with these original server side MPAs where everything is a slideshow just went away by, replacing fragments, like like losing scroll positions or losing, like, some transient state on the page, like an unsafe form or something. Like, most of that goes away entirely. And, like, when we saw that there the the the sweet spot was neither, like, a full MPA and neither, like, a full SPA is was, like, something in the middle, and that's that's unplay for us.
Speaker 2:And we expanded on that since then a lot. So I didn't think I didn't think I I, would be working on this 10 years later when I started it.
Speaker 1:I mean, it's a it's it's a so, you know, part of what I'm just kinda, like, interested in, it's it's a bold move to make your own framework, you know, when you're going into this stuff. I mean, I guess if the alternative is just kind of like creating a new solution for every project, then it seems like, okay, better to make an internal framework. But it's still kind of like, you know, you so you're working with clients presumably, from a bunch of different companies or or, you know, is it, like, what was the kind of, like, decision process there? Like, are you did could you make the call? Or were you in the position to make the call?
Speaker 1:Or you pitched it to a team or something like that?
Speaker 2:Okay. So I could have made the call, but, like, from my experience, it's not a good idea to, like, prescribe something top down to your team because if they don't, they end up accepting it. So just, like, just be be, like, bad morale and, like, everybody. Yeah. So, basically, I I started playing with this, with some internal projects, in my spare time and then just, started to to, integrate this with a few client project I did at that time, and then I saw it being organically adopted, like, in the company.
Speaker 2:Like, I didn't push it too much. Yeah. And, yeah. And, basically, it it automatically came to a point where we now would do most of our applications with that stack. So it's raised in the back end and it's a pretty vanilla JavaScript friend with ampoule and a few, dependencies for stuff like, I don't know, multi select, date pickers, and so on.
Speaker 2:Yeah. I mean, we do have some React in some apps, like, for instance, if we have, like, a pretty ambitious component that does a lot of, like, heavy optimistic rendering or something, then that that's still something that where, like, the the React approach the client side approach, profits a lot from. But even in that, scenario, we mostly run this in a rectangle on the page and the routing around this is just a multi page app with OnPoly. Yeah.
Speaker 1:Yep. Okay. So, yeah. So maybe we can get into some of the specifics of what OnPoly is. So so I, you know, I I took a look, I haven't I haven't used it in a in a big project, you know.
Speaker 1:I've been using HTMX for a lot of stuff, and I think my experience is sort of similar where I was like, you know, okay. I'll try this out and, like, you know, and just kind of it becomes it it's such a revelation in some ways for me to build an app like this, where you're mainly just building it in, like, the most obvious clear way, and then just kind of, like, adding in, you know, in your case, on poly, but adding in these kind of hypermedia calls and, like, fragments and stuff like that. And it's like so, you know, I definitely, can see the appeal of where you're you're sort of it starts to take now I basically do every project with, you know, some version of this, because it just has made my life a lot easier when you're working on a lot of different projects.
Speaker 2:So yeah. I mean, I'm not the best, like, I'm not a HMX pro or something because we have our own thing. So, of course, we're aware of HMX and and I know Carson a little. And, I think everyone knows at least his marketing.
Speaker 1:Right.
Speaker 2:But, yeah, I think there are some parallels, even though this is like a parallel evolution. So in both worlds, we keep the servers producing the HTML and we keep most of the logic on the server where we can have, like, immediate access to our data, where we can choose our language and so on. I think, like, there are a few differences, if that's, like, a good way to explain it. In Ampol, the default is that, like, every HTML endpoint always renders a full page. And I believe this is like something that you can do in HTMLX, but it's not the default.
Speaker 2:I think a lot of HTMLX developers do only render fragments and, the reason is that, like, we have like a big focus on progressive enhancement, meaning that you build a multi patch app without any clientele logic first and then you enhance it by sprinkling custom attributes over your fuse. Those attributes look a little like hmx attributes, it's just that they have a different prefix. I think in HEMX it's like h x and for us it's up, so it's like up target or up follow, up submit, but it looks similar. The one thing that we get from that is, like, every endpoint is always something that works, like, directly without JavaScript and can always do a full page load. And since we, like what what we wouldn't do in AMPOLI is, like, this, h m x thing of every element can do everything.
Speaker 2:So this is not something that we do. So for for instance, everything that's a link is still a link or everything that's a form is still is still a form, which, like, has some benefits like being able to work without JavaScript or like having a better default accessibility story. I mean, you can do everything. You can do an ampoule, you can do an HMX also, but I think it's like it's more like it gives you the the low level tools and leaves it up to you to compose it. Whereas, ampoule is, like, very heavy on defaults, and it tries to be, like, smaller, by default.
Speaker 2:I think that's the like like a like a pretty fundamental difference in in philosophy also.
Speaker 1:Yeah. I think that I think that sounds right to me. What just kind of that general thing of of you, you know, the HTMLX feels a little more low level, and just sort of one of the first examples. So, you know, on the on poly page, is was, kind of just being able to, pop up a dialogue, which, like, is not part of HTM. You know, if you wanna sort of do that in HTMx, you know, you you can obviously figure out how to open it, how to do dialogues and but that's not built in in any way, any sort of kind of interaction with with that sort of, stuff.
Speaker 1:And so so, you know, just trying one of those examples out, like, that was the first difference I noticed was, like, the idea that, you know, you have, like, a link and you wanna open it in a dialogue. Yeah. So you click it, you know, I checked, okay, we have this, you added this attribute of, you know, up layer. So this is concept of layers, which I think is really interesting, which which you express through dialogues. So it's like a built in browser thing, so you know as far as I know there's like complete support for it.
Speaker 1:But you from your front end you say like you have a layer and wherever this link is I want it to pop up on a new layer. And so then it kind of overlays it, puts it into that dialogue and, you know, shows you on that next layer. And then if you refresh, so it's actually also changing the, you know, it's actually going to that link up in the URL bar. So, you know, let's say you're like you're looking at the details of a project, it's going to that link and you now have, you know, that project opened in a dialogue. If you refresh you so this is what was unusual to me.
Speaker 1:I was like, well what's gonna happen when I refresh? Because I, you know, coming from from, h t m x and sort of some of the other ones, my first thought is that it just loaded a snippet, you know, a fragment of HTML, And when I refresh, it's gonna have some way to handle it. But what it does is it just loads whatever went into that dialogue in the full screen because like you said, everything is an HTML page. Right?
Speaker 2:Yeah. I mean, you can you can configure whether you want, like a layer to have its own URL or not. So we usually do it if the content that's shown in the dialogue is actually a full page that can work on its own. I like, coming back to your, like, basic CRUD example. Basically, for instance, we have, like, like, a model called projects, and it has, like, a name as attribute.
Speaker 2:And then we start building, like, a basic MPA, which cannot have dialogues, basically. So you'd have, like, a, like, an index of all your projects, and then you have a button called new project, and then that that just switches to a new screen. And you start with that. And what you can do with, like, this up layer attribute you mentioned is you say that this new project, button that you have anyway opens in dialogue. And, like, since it all would also work, like, in a full page, you can choose to update your l with the location.
Speaker 2:But, what employee does then after this is, since it's fully aware of layers and what goes in with layers, it can isolate all the interactions into the layers. So for instance, if you have if the new project form is a multi step interaction or if that new project form has validations that would require user to submit the form multiple times, it will always be contained in that overlay until you explicitly say I want to close it. And, you can even do stuff like with a link that opens the new project form, you can say I want how long you want to keep that overlay form open. For instance, you say, the new project form is done when you have reached, like, any show page of a project because then you have completed the, the creation process or you can wait for some events to be emitted on the overlay element. So then we can even do it in a way that the, project form does not need to know whether it's currently being displayed in an overlay or in a full page.
Speaker 2:So, like, this is like some of the the benefits we get when the framework actually knows that this interaction opens a new overlay as opposed to we're rendering a fragment that happens to draw a box that is styled like an overlay.
Speaker 1:Yeah. It doesn't know anything else. It that's this, you know, if you just start doing a fragment you're you're expecting something else to know all the details of what the context is and everything like that. So so I thought this like concept of layers, you know, just kind of looking over it was really interesting. I haven't I haven't really thought of web development in that way.
Speaker 1:I will say, like, I've I've been working on, you know, mobile programming to some degree with with flutter and and just in general on mobile, they have something called context And you could sort of think of it as the layer. It's like it it's a it stacks these contexts on top of each other. And so each page knows which context it's in, so if you hit the back button, you know, it knows, okay, now we're leaving this context, We're going to the previous one. We're popping. And I've just haven't really seen this much, in sort of, web development context.
Speaker 2:May maybe we have, like, something for something like context. So these overlays, they have a mode that meaning, like, how do they look and feel? Like, the the default mode is just an modal dialogue, but then there's a mode for it, like, a drawer that flips in from this, that that moves in from the right side. And we also have a a mode called cover, which just, like, covers the entire screen. And maybe that's something like your context because, for instance, if you have a mobile, you have a, like, a settings menu where you can make a few configuration for your account then return to the origins reaction.
Speaker 2:You can probably just, like, move in a cover overlay, do your state changes, and then, like, return to the original interaction without the configuration screens knowing about the previous interactions because it's just stacked on top. Yeah. I moved the original interaction and it never actually left the page.
Speaker 1:So is this like, you know, I will say one of the examples that I I tried the the one of the first examples I tried was was to do that pop up. And at first it it just it didn't work. You know, I had a link, I gave it up layer equals new, and you know nothing happened when I clicked it. So I was trying to figure out, okay, like what am I missing here? And you have to add somewhere in your in your, DOM up main, right, for that to work.
Speaker 1:So is that is that what gives it its sort of layer context? Like, each layer has an up main. Is that sort of an accurate thing or is that
Speaker 2:is that sort of what that's I mean, you so whenever you update a fragment or open overlay, Amplify needs to know which fragment to extract from the response and which fragments are only to discard because we only use fragments. So if you you can you can just give a CSS selector to to target, like like, you can do up layer main and then up target, I don't know, hash my fragment. If you don't have a target it just will try to find the dominant content area on your page. And in HTML 5, that's like a main element. You can use a main element or you can, use, like, an app main attribute that you mentioned if you don't want to use a main element.
Speaker 1:Okay. So main. So actually you have like a tag main on your page a lot of times.
Speaker 2:You can use the tag main or you can use the app main attribute on any on any element of your choice and that's like the thing that amply falls back when you don't give an app target.
Speaker 1:Yep. So one of those has to be on the page for it to sort of have any idea of what the context is. And then if you open a layer, is it, is it using the new layers up main to kind of like say like okay this is now my root within this layer? So that if you then open for instance a second layer on top of that, like is is it does it sort of, I guess like how is it keeping track of layers? Like if you're if you are kind of trying to, like, does it think of each layer as a as a full HTML page?
Speaker 2:It's it's like, every layer has a, like, a root element. We we cannot have multiple, like, HTML documents on the page because, like, this stuff on the top with the head and the HTML, that that can only be there once. But, you will usually have, like, one layout container or something, some layout container element or, like, a main element. You can also, like, do do different, like, root elements for the root page and the overlay. For instance, the overlay, sometimes you want to exclude a a navigation bar.
Speaker 1:Yeah. That's a good example.
Speaker 2:But especially you basically, if you in your example, if I were to stack, like, 10 layers on top of each other for some reason, each of these layers, would, like, have their own roots, my element. And when you make any interaction within a layer, like, for example, follow a link or submit a form, then it will, like, again, find the main element in that response and replace the main elements main element with the fresh one from the server.
Speaker 1:Yeah. Yeah. I mean, you know, I just it's funny because most of the time these layers you're just gonna use them to pop up a dialogue and do some work and save it and close and stuff like that. But I just it's something I haven't really seen before so I just think it's kind of an interesting, like, you know Yeah. Thread to pull where it's like well, okay.
Speaker 1:So if you're thinking of the web as these layers, like, what does that what does that mean for you? So yeah. No. I think that's that's interesting. So let me see here.
Speaker 1:Let me something. When you're sort of targeting stuff, do you have a a cons so, you know, like you said, you can kinda like ignore navigation, because because you're returning every page as a full HTML, how do you kind of decide, like, what's the syntax for deciding? Okay. When I read so I'll just say in HTMLX, you have this concept of h x select. So if you do pull a whole HTML page back, from the server but you just wanna take out 1, you do h x select equals, you give it a c s s selector, and then it takes that fragment out and puts it into your target.
Speaker 1:So what's the version of that for sort of the default on poly?
Speaker 2:So like if you for instance, if you follow a link, you would have an attribute up target that also contains a c s selector c s selector and that selector is expected to be present in both the current page and the service response. Like, for instance, if you had up targets
Speaker 1:Okay.
Speaker 2:Hash fragment, then the an element with the ID fragment would be selected in the current page and then would be selected in the response, and then those 2 would be swapped.
Speaker 1:Gotcha. So it it's matching CSS selectors. Yeah. Does that sort of okay. Because yeah.
Speaker 1:So that was one of the first things, like, kind of like a shifting mindset was you have an example on your home page of, 2 cards, right? Like, they're flipped, you know, you see the back of the card and you can click to flip it. Right? So, you know, kind of just the the basic concept of this. And so so I did like an inspect element to see, okay, what's happening here when you flip this card.
Speaker 1:And it's kind of it's pretty interesting because it's like you have a single so you have 2 separate cards, but you have a single HTML page for the front of both cards, and a single HTML page for the back of both cards. And yet, when you click one of the cards, it's returning that card only flipped, and the other card is not flipped. So that's kind of, you know, this it's just, I was trying to wrap my mind I feel like that's probably a core thing about un poly, is wrapping your mind around that idea that somehow you were able to, when you clicked it, you told it to, you know, fetch the back HTML but only swap out the part of HTML of whatever I clicked on. Does that sound sort of what the what's happening there?
Speaker 2:Yeah. In that example, the one so both cards are, like, vanilla hyperlinks. It's just an a element, an a anchor element, and one of the cards has an uptarget of dot 1, and the second card has an uptarget of dot 2. And the first card also has the class 1 and the second one has the class 2. So for the if I click on the the second card with the class 2, it also has the uptarget class 2.
Speaker 2:So it finds the like in the new version of the respective element in the, in the response and that's why you only see one of those 2 cards flipped.
Speaker 1:Finds the new version of it. Okay. So because the because it it knows that it came from the click of 1.
Speaker 2:Let me see here. Because because the link you interact with had an up target equals dot 1 and that's the selector we look for in both the current page and in the response.
Speaker 1:Gotcha. Gotcha. So yeah, it's just I mean it's it's just an interesting way to kind of think about it. So like in general, you're building these pages and you might have, like, 2 HTML pages that are somewhat similar, but you're keeping in mind that you have these, you know, selectors, and you keep those selectors the same so that you can then kind of do clever stuff with them like not load the navigation because that's gonna the navigation is gonna match stuff like that.
Speaker 2:Yeah. Yeah. And you can also like compose pages like in in in interesting ways. Like for instance, let's say you have, like, a list of projects again, which we found from earlier. And, like, we have, like, for each project, you have your your own URL that shows details about the project.
Speaker 2:And now in a multipage app you would just have like a list of projects and then it links to the data page of project 1. The next link links to the detail page of project 2. So now without like changing anything about the back end you could say let's do this in a way that we show these detailed pages inline in the index. Whenever I click on project 2, it would just, like, expand that row in the table to show the entire project within that list. So that's like a screen that doesn't really exist in the m p I back end.
Speaker 2:Yeah. But I can just, like, by choosing my up target attribute, I can compose them on a different page. Or, again, with the layout example earlier, I can choose to open that, detail page in an overlay. So I can keep, like, in the back end, I can keep this context of the list with the scroll position. I'm on page 3 and have scrolled down, I don't know, 300 pixels, and I can just, like, keep that and, like, open that in an overlay.
Speaker 2:And, like, that's, like, a nice way to have on the one side, we have, like, an MPAA back end that fully works with our JavaScript if you wanted to,
Speaker 1:Yeah. But you
Speaker 2:can, like, compose it in different ways, so we don't have this jarring effect of every link blows up the entire page and you lose all your navigation state and your scrub positions and so on.
Speaker 1:Right. So so in the case of, like, you you have a long list and you need to get the details, you would have kind of like a an empty placeholder div or something, like, below each item and then you set that as the target, would that be kind of
Speaker 2:have an empty place or or you replace, like, with a list item element itself, like one of those 2 Okay. Yeah.
Speaker 1:Yeah. Replace the list item itself with the detailed version. And then if you were to so that at that point, you can decide, do I want to set this project to my URL, or do I want to, you know, just just, have it not set? Yeah.
Speaker 2:Because then if
Speaker 1:you if you set it to the URL then you refresh, it's like you're gonna get whichever last one you expanded, which might not be what you want.
Speaker 2:I mean I mean, again, there's you can decide it, but with, like, with everything we have, like, a very strong opinionated default. Like in this this case, the default would be whenever we update a main element, then it's, also by default a new history entry because, like, this is like like a substantial piece of content that you're switching to. You're probably, like, replacing the dominant content area, so that is usually a good idea to have its own URL. But if you were, like, only in the example with the cards, like, only flipping one card, but
Speaker 1:Yep.
Speaker 2:You're still, like, on this deck of cards type of screen, then I wouldn't flip to the URL of, like, an individual card or to to the backside of the card. So that that doesn't make sense. Like yeah.
Speaker 1:Okay. And do so do you set a default for that or, like, is it so, like, I don't remember seeing a default in the card example. So, like, what would have happened if I refreshed or let me see here. So I I think maybe the card example doesn't change the URL. Let me see here.
Speaker 2:I I I think not because it's not updating a main element. It's just updating an element with, like a custom selector dot 1 or dot 2. So we, like, keep the history as it is. You can always override the defaults, but this is, like, we have and this is probably something that I, like, got from my time in, in in Wasteland is, like, to have, like, very strong defaults for everything. Yeah.
Speaker 2:Conventional concuration and so on, which I know a lot of people don't like at all. They just want to have everything explicit, and they don't want to have any magic ever. But, yeah. That's also maybe a different philosophy here. Yeah.
Speaker 1:Yeah. Well, I mean, I would think of it as like, you know, you have 10 plus maybe 20 years, you know, experience building web apps. So it's like when you sit down to make a web app, like, you probably have a pretty good idea of what defaults you want to use. And they probably make sense, you know, particularly for, you know, your sort of use case. And and I guess, like, in general, what what sort of apps are you building?
Speaker 1:Like, what's the sort of, like, is it, you know, you said it's for an it's an agency that, you know, you're part of, but, like, what's the kind of, like is it all over or is it certain types of apps?
Speaker 2:So, since we do bespoke web apps, it's not one type because if it's, like, if it's, like, a basic CMS, people would just use WordPress and be done. So people go with that when they say, for instance, they need a custom CMS or, like, like a custom ERP system that needs to have some process automation interface or have some digital project product. So so it's, like, all over the place, all industries, like, all types of apps. Sometimes it's, like, a very ambitious front end, which is visible to the public. Some sometimes it's just like, like, an internal like, millions of of back end screens, where there's not so much focus on on design and more about, like, features for power users and, like, a small closed circle of users.
Speaker 1:Yeah.
Speaker 2:I think something that, like, I think Ampoli lends itself in particular to those back end interfaces. I mean, it can do, like, heavy front end stuff as well, but I think, stuff like I told earlier with the layers and so on, this is something that you can do if you have some control over the UI. If you do a fully bespoke fully bespokely designed front end. Sometimes you click, you you you need to customize everything and then you cannot, like, use so much of the default that we have for you.
Speaker 1:Yeah. Yeah. Well, I mean, I have I did see, like, you've on Poly or you, you know, you've put some work into transitions and sort of, you know, some front end goodness. So is it, you know, where do you sort of see on Poly in in terms of, like, you know, the the front end UI experience? Like, do you have kinda, like, fun with that, like, building that stuff out?
Speaker 1:Or is it sort of, like, you know, like, do you feel like you're moving closer to where you will sometimes use React? Is that sort of the goal is to push on poly to make it smoother or is it What do you sort of see for yourself on building those transitions and other things?
Speaker 2:Okay. So like, since I have like one foot in both the un poly world and also a little in the React world, Yeah. I feel like both approaches, like, have to deal with this network gap. So and they have to deal it in different ways. So for instance, when you have a React component, like, it's always a pain to not have synchronous access to your data.
Speaker 2:So you have to, like, fetch stuff and think about what's happening what's going to happen if the user interacts before you have the data and so on. You have to bridge that gap somehow. And with, with the hypermedia approach, you you have things that you that the front end doesn't know about, and you need to somehow wait for the server. And I feel like both approaches have been, like, flirting with techniques from the other side. So in React, you have stuff like a server component where you say, okay, it's it's just too much of a pain or it's too slow to run stuff on the client.
Speaker 2:So we, like, have to move that that part to the server again. And, in the hypermedia world, you have stuff like hmx or unpoly that also, like, tries to to push the boundaries how responsive and how snappy your interface can be without actually having the template to render a new state. So in the in the new 3.10 release I'm working on right now, we have stuff like, arbitrary loading states. We can, like, make arbitrary changes to this page while requests are loading, and you can even do stuff like optimistic rendering with it. With, like there's a little duplication left, but there are cases where you can actually update the page without waiting for the server.
Speaker 2:And I think that's that's, again, one case where we try to, use, like, the techniques from the dark side or something from the other side. Because we all need to deal with that network app. It just doesn't go away. And Yeah. So I think that's that's that's, like, one reason why there's no longer, like, the the the one true way to build a web app.
Speaker 2:Because it used to be that way that there were this very sharp distinction between the the multi page and single page approaches, but I see that like fading away more and more.
Speaker 1:Yeah. I would agree. And and it's, you know, I'm trying to like sometimes I feel like I'm trying to get at the root of like what is like what's the ideal here where like because obviously there's like there is this benefit in the react, approach of, you know, if your entire app is just like a local browser client side thing, then, yeah, you know, I guess there's, like, sort of this, you get immediate feedback on some things. Right? But, like Yeah.
Speaker 1:That's just not the case in real, you know, I mean, in my opinion, I'll just, like, quickly throw out, like, why I kind of, like, have moved away from that. Like, I think first of all, you're putting a lot on the browser. You're loading a lot that just doesn't need to be there, including information that you suspect they're gonna need or you need to be careful with, you know, how you sort of load information into the client if you're trying to, keep a lot of it there. And then you're putting everything into memory. You have this huge virtual memory, like, just pile.
Speaker 1:Like, you know, there's the DOM and then there's your virtual DOM which has like hooks and it has like just a whole bunch of event listeners. And and my experience is that actually that's pretty slow. Like you're you're giving your browser a lot of work to do, and you're loading everything upfront because it all has to be your virtual dom has to be built before you can really do anything. Whereas with HTML, you know, you can give it a little bit of HTML and then just when you click then you do something. So I'm obviously on the on the much more on the, you know, pro of the back end side.
Speaker 1:But it's like I do understand there's certain things that, you know and like you said, you sometimes reach for React. So when are when are those times? Like what what's an example of what are these kinda like where you feel there's a component? And I there definitely are them. What's an example of one of those you think?
Speaker 2:Okay. So I have a good example here. So, some time ago we built, like, a, helpline chat where, like, people could, like, get advice about, STDs. So it's, like, a very sensitive topic. Yep.
Speaker 2:And so the requirement for us first, it's a chat. So it needs to be real time because you're looking you get a, like, a anonymous adviser and you can chat them with them in real time. Okay. That's like the first thing that doesn't I mean, we can do it with polling or or a service and events or something. But it's a pain.
Speaker 2:Okay. Then there was another requirement that since it's so sensitive, what's being discussed in that chat, it should be, like, end to end encrypted. The server should not know anything about the chat content. So okay. One more argument.
Speaker 1:Interesting. Okay.
Speaker 2:And and it's also something that that we we we didn't we just didn't want that data on our server. Like, because it's but, like, just just in case that bad karma to Yeah.
Speaker 1:Well, I
Speaker 2:stuff like that.
Speaker 1:I'll just stay right on the bat. If you're not keeping something on the server, it's I guess it does make sense to do a client only solution.
Speaker 2:So I think, both the real time thing, the the expectation of the user to to see messages immediately without waiting, like, for the server to respond, the end to end thing. That was all things that play to the strength of React. Yep. But on the other hand, when you do, like, a React app that doesn't do optimistic rendering at all, that doesn't that that basically doesn't work offline at all, not even a little bit, where every meaningful interaction basically waits for a JSON endpoint.
Speaker 1:Right.
Speaker 2:Like, what are you doing? It's just it's so much code. It's so much code, for, like, no benefit. So I think just be honest and, like, play to the strength. If you're going to build a React app, build a app that uses React, and, does all these things like optimizer rendering and so on.
Speaker 2:And if you're doing if you're doing an hypermedia app, like, like, enjoy the fact that it's going to be, like, much less code. Enjoy the fact that it's probably going to have fewer dependencies, less complicated control flow, and so on.
Speaker 1:Yeah. No, I think that makes a lot of sense and it's like, I think that's the big thing is like there's this kind of like, you know, ultimately for most apps, you know, what you just gave is an interesting example that's not like that. But most apps, like, you're getting data from the server and, like, that's a good thing. You know, that's like how it should be because your server is, you know, presumably, you know, safe and has an idea of what data it can give and what data it can't give. So you're gonna have to go to the server.
Speaker 1:So it's like I think this is like a fundamental misunderstanding of, like, oh, well, like, in React, you're still going you're still running you're still doing a JSON request. Like there's nothing faster about getting JSON than there is about getting HTML, you know. I mean, I not that I'm not sure exactly like I guess I I haven't, you know, gotten the full sort of React version of that. Like, what's the case for React in those situations and and maybe there's just kind of like a front end, like or like when you click something getting that immediate feedback, maybe that's kind of the thing. But, you know, I I think people who are like you said, the gap has been bridged.
Speaker 1:We now there's all kinds of things now for that kind of immediate feedback and and sort of letting you know that something's happening on the front end. Does does unpoly sort of handle that in a you said, like, unpoly basically kind of goes for as many defaults as possible. So, like, I'm just gonna in my head picture it as like something similar to, you know, an h t m x style or a turbo, or what is it, hot wire now, they changed their some of their stuff around. But, you have kind of curated the interactions and given even though you can still access sort of the low level stuff, you've curated a little bit more and given some of the main defaults for stuff. Does that sound kind of
Speaker 2:Yeah. So, like, in the right world, there's this convention of a configuration thing, which means, like, if if you tend to do the same thing in the same way all the time that that like, don't don't do it. Don't put it in the code. We will just choose it for you. And you just you just put it in the code if you want to do it to be to to be different.
Speaker 2:And, so, basically, every like, for instance, we had this link that's going to be handled by Anne Polly that's It's going to have an up follow attribute, but then there are like, I don't know, 50 other attributes that like modify the way the link is being followed. Like stuff like, are you going to animate the change? Are you going to, where is the focus going to be when you update a fragment? What's going to happen to the scroll position? And so on and so forth.
Speaker 2:And all of these things have like a created default, but you can override all the defaults. Like, you can you can you can override at the link. You can also, like, configure the defaults globally. And if you're still not happy with this, we have, like, a very extensive JavaScript API. So everything basically, all the attributes, that we have are just implemented in a way that, like, I don't know, on click, call this JavaScript function that we also expose to use to you.
Speaker 2:So if you're not happy with the way that we wire up things, you can always, like, build your own, attributes. And we actually, like, have this registry, where you can, like, add your own custom logic where you say, like, every time something with my custom attribute goes with the DOM, please activate the service button in it so you can, like, expand and build your own dialect of Unpoly if you want. But if you don't want it, we have, like, a very opinionated default how we think or how it works for us, how it works for us. That's a better way to say it.
Speaker 1:Yeah. No. But that's nice. So so you sort of you start off with like the minimal code in your, you know, in your opinion for most of the time you're just gonna wanna add like a couple things and then you do expose if you need it this kind of other layer of of stuff. And so one thing I noticed that's, you know, right off the bat different from something like HTMLX or maybe some of the other ones, it also includes a CSS file.
Speaker 1:So what's the what's the CSS file? What kind of stuff does that kind of encapsulate?
Speaker 2:So it's like it's it's it's very, very minimal. For instance, because we talked about the the layers earlier, we had we need to have, like, some very basic styles to, like, open a overlay, and this is basically just a white box. Or Right. I don't know. Like an like an add we have, like, an attribute to expand a link to a bigger surface.
Speaker 2:For instance, you have a link in the table, and you want to make that the whole table row is clickable, then we have an attribute for that, and that just changes the the the mouse over cursor to this hand pointer. So stuff like this. So we we try to not be so we don't have we try to not have opinions on the CSS side because that's just too different across projects. There's, like, no common way to do CSS.
Speaker 1:So it's not really it's not design stuff necessarily. It's more like browser UI expectations of like, you know, functionality.
Speaker 2:Yeah. It's maybe like 30 lines of CSS. That's very, very many.
Speaker 1:Okay. Okay. Interesting. Nice. So yeah.
Speaker 1:So what do you sort of think is, you know, I think you mentioned it in 3 point you're working on 3.1 or 3.10 right now. Yeah. And, you know, what what sort of, like, big picture? What do you sort of see, like, for the framework? Is it you said it's sort of moving you're continuing to bridge that gap into front end world, and that's kind of, the next, the next phase or whatever.
Speaker 2:So in 3.10, the the the main focus is, doing offering some way to do optimistic rendering, like, where you can do, like, temporary changes of the page while a request is loading, which is, like, reverted when the the request ends for any reason. I mean, looking further, I think something that I have, like, my eye on for, like, a breaking change is to use try to use, like, web standards more because we have built a better form of many web APIs into the framework right now. But it's it's really hard because, like, the a lot of web standards leave so much to be desired. Like Mhmm. Stuff like because we could talk so much about about layers.
Speaker 2:I mean, of course, there is this dialogue element, but it's like it's like a mess. It's like a complete mess. Now how it looks, how it stacks.
Speaker 1:At default, you can either click off it and close it. Right? Is that sort of a
Speaker 2:Yeah. And and then you go into the the cross cross browser inconsistencies and so on. And, so we see a lot of stuff that's in the last 10 years, I've I've seen a lot of stuff being added to the web platform, but that that that's kind of like things we have in the framework. And sometimes we can replace stuff from, from our userland code with with web standards for instance. Like 10 years ago we had this, colon has pseudo selector, which is, like, super useful and we we polyfilled that actually for for, up target attributes because it's, like, so useful to refer to an element by the selector of its child.
Speaker 2:And
Speaker 1:Wait. Sorry. So let me let me just, so the browsers added the has, you said? Like that was like Did
Speaker 2:did did did did you know the the colon has?
Speaker 1:Yeah. You know, honestly, I've never used it in CSS.
Speaker 2:I
Speaker 1:think that I've used it through Tailwind, you know, because that's how you do the groups in Tailwind. Right? Is that because I like if you hover over a whole l if you hover over a whole element, you want one particular CSS within that to change. Or if I I don't
Speaker 2:know about tailwind, but for example, let's say you have multiple groups of form elements on the page. And with groups, I mean, like, this triple of you have an input and a label and maybe an error message. And those are always in a container like form group or something. But those containers, they don't have an ID I can target because it's always like the class form group.
Speaker 1:Yeah.
Speaker 2:What and so how how are you going to target a form group with that contains a particular input? Because the input does have a unique selector. It has a name, maybe has an ID. So I can say, I target a form group colon has input name email. And then Gotcha.
Speaker 2:You target the container by the selector of its child.
Speaker 1:Yeah. Okay.
Speaker 2:That is something that we we polyfilled, like, like, 10 years ago, but but but but was actually became available, over the last 2 years, across all browsers. And now we can reuse that.
Speaker 1:So you built our own at the time?
Speaker 2:Yeah. Yeah. We had, like, our own CSS selector engine. Interesting. Yeah.
Speaker 2:But but basically every single web framework, web platform feature, like, has, like, some significant drawback that you need to accept if you want to use it. So there's something like like I'm trying on right now and see how it would feel because what we would get is, like, we would have, like, maybe a little smaller file size of the library, but then again, we would, like, could no longer cover a lot of edge cases that we do now. And
Speaker 1:Yeah. I can imagine that's tricky because the browsers, you know, we've I've talked about that on here and kind of talked with, Anthony Alaribe about it, but browsers are getting, you know, better and better, and so they they do have more of this technology that's kind of built in. So it seems nice if you can leverage it, but if you are just using what they give you, you know, that's also, you know, maybe not quite as powerful as being able to get in there and program your own in a lot of cases.
Speaker 2:Yeah. I sometimes feel that that that the standards process is like inventing a lot of things from first principles instead of extracting it from what's out there. And they often end up, like, not giving developers what they need. So developers says, hey. I want x, and then there's a standard process, and that's okay.
Speaker 2:You wanted x, but here's y because we think the y is better than the x, and everyone still has no way to do, I don't know, templating in in, in web components, but we have stuff like, I don't know, shadow DOM style encapsulation that few people ask for. But
Speaker 1:Right.
Speaker 2:Yeah. That's that's the kind of frustration I have with with using the platform sometimes. Yeah.
Speaker 1:Right. Well, you're deep into it, like building your own versions of stuff. So it's like most people don't sort of see that from a a farther out perspective where they just see the end result of it, but it's interesting to, like, actually be digging into it. So so I well, one thing so you mentioned, you know, you're working on an optimistic UI possibility, you know, just kind of having some support and stuff like that. So, how would that so, like, you know, optimistic UI, I thought of that as kind of like a tricky thing because it's you don't necessarily always want it.
Speaker 1:And I think the quote that I, you know, that I think maybe it was Carson, but it's like, you know, there are the example, like how optimistic do you really want it to be? Like, if the server, you know, if you if you're assuming something's happening, and you say tell the user that something has happened, you know, that's very optimistic. But then you go to the server and there's something happen, you know, your your reservation doesn't go through, like, you don't want to be too optimistic ahead of time. Yeah. But you wanna give them something.
Speaker 1:So, like, what do you envision? And I just think of it when I think of a server side, like, the server has to be the ultimate thing that that is the source of truth and that gives you the information that you want. So what you when you talk think of optimistic UI, do you think of like a placeholder that's like got a little spinner? Do you think of like, you know, what the text might be? You know, like what's the sort of what's your vision or version of of how that could work in un poly?
Speaker 2:Okay. So it's not a vision because we're we're going to release all of this next next week or something. Next week.
Speaker 1:In some far distant future.
Speaker 2:May may maybe 3.10 will be out when this podcast is is published.
Speaker 1:Yeah. Depending how long
Speaker 2:it takes you to download. So I think you all first thing, you always want to signal that the app is working in some way. That can be something as trivial as a spinner or disabling the submit button or something. Because, I mean, the default, like, loading indicator process, they're not great and they are not appearing in a single page interaction, so you need to do something. Like, for instance, we have this, like, default progress bar on the top, and you probably want to have, like, some spinner image when you press a button or something.
Speaker 2:That's something that I would always do. But then, I would use optimistic ray rendering in in cases where I can expect the transaction to go through. For instance, like, if you have a chat. K. But when I'm Yep.
Speaker 2:When I'm writing you a message, I know that message is going to reach you. And that also some expectations people have from using, like, their messenger apps on their phones and and PCs. So, why not immediately insert, like, the the bubble with your message in the list that you already have. Like, that that's Yeah. That's not so much work.
Speaker 2:Of course, you need a way to, so I think you need 2 things to make this ergonomic for the use, and and and, I care a lot about, like, having, like, minimal APIs and having an an an economic API. The one thing is you need to, have some way to revert the change in case something unexpected does happen. Because, like, once every moon, the message doesn't go through because, for instance, you're offline or I don't know. You have deleted your account on or something. And then Yeah.
Speaker 2:We cannot leave this message bubble on the screen. So something that we do, we have a way to describe these temporary changes in a way that automatically get reverted when the request ends. So in your in the chat example again, I would like describe the insertion of the chat bubble. That's just like a one liner, but, AMP only tracks the change to the DOM I did and if the server responds anyway, it could be a successful response, an error response or maybe no response at all, a timeout, then that gets reverted before it gets overwritten with the server response. In the second success case it would just be overwritten by an identical chat bubble and I would not see any flash of content of of state change at all.
Speaker 2:But in the case where the server responds to an error, the my temporary message bubble would be removed automatically before the server shows before the error message from the server is shown. Yep. And I think the sorry. Do you want to
Speaker 1:Well, no. So I I'm well, okay. So I'm just like I'm trying to picture writing that code and, you know, the one of the big difficulties is when you submit that chat, you you have some text, right, some text input. So are you defining a a template which is maybe the same on the server and the same on the client? Like, do you do you define like a a div or like, you know, let's say the chat box is like like the apple one.
Speaker 1:Like, it's like a green little, you know, so so you you have to make it look the same as what's gonna come back from the server. But you have to make it empty so that, you know, it can be used in the same way and new text each time you type a message in can be placed in there. So what's the kind of like just logistically, like, I'm just trying to imagine you define like a an optimistic template that your data is gonna go into with placeholders. Is that sort of what you're thinking Or what you're how you worked it?
Speaker 2:Okay. So, so in our version, that optimistic change is called the preview. The preview has a name like add message. And in that add message preview, you would have access to the entire render pass including, like, any form data that is being submitted, so you already have the text. And then you need to, like, make an element that contained the text.
Speaker 2:I mean, if it's a trivial element, you can probably just, like, do a diff and put the text on that as that. But if it's like a more complicated component with a lot of, HTML, that would be a lot of duplication. Right? Because you already have the template on your server, and now you have it a second time on your client, and we don't want duplication. We want to reduce it as much as possible.
Speaker 2:So in that case, you could, when you deliver the the the the chat channel with all the messages, you could, like, render out a template as you said. Could be, like, a template element that contains, like, the scaffold for a new chat bubble, like, a new message bubble. And in the preview, you can instead of, like, passing in your HTML, you can also just refer to any template by a selector. And that's also like a very simple way to do stuff like placeholders where you're like, I don't know, like this handball style, like, I don't know, curly curly brace text, closing closing curly brace Slot
Speaker 1:of some sort.
Speaker 2:And then you put put put that in. Because that's like the second connecting component that you need is you need to reduce the duplication. You are going to have some level of duplication when you do optimistic rendering in a server side approach.
Speaker 1:Because it
Speaker 2:kind of does not have access
Speaker 1:to the unavoidable. Alright.
Speaker 2:It's like But I think there are there are ways to, reduce it by for instance, if you have a template, you the server can run the template, and then it can maybe reuse some partial HTML that it has. Anyway, just with placeholder in it. I think the other way that we're going to use this is, like, to to to use optimistic rendering in those cases where the duplicate either the duplication is low or where the extra effort adds a significant value for the user. Like for instance, like if I have a like a high value screen where every conversion matters and I know that snapper response times increase my conversions. Maybe I can accept some duplication.
Speaker 2:But there are also cases where the duplication is naturally low. Like for instance, I guess you you have like some form of calendar app, like Google Calendar or something, and then you can in the app you can drag, like, an event across days. Right? Yep. So that drag and drop code is going to be on the client anyway, because if you need to do you need to do some like, like, you need to have, like, 4 or 5 event handlers just just for basic drag and drop.
Speaker 1:Yeah.
Speaker 2:So if you have already built the drag and drop code on the client, then you have this final event handler that registers the the the drop of an event in the new day. And that page at that point you already have all the participating elements in your hand. You know which events being being dragged. You know the the target element is going to be dropped onto. And then it's just a one liner to write the preview function that moves the event rectangle into the right correct day while we're waiting for the for the server.
Speaker 2:Interesting. So in that case We we have we have a way to, describe that move across the DOM in a way that it it can be revert automatically in case the server responds with, any unexpected content or even with expected content. So you don't have to deal with the reverting case. And I think that's a case where it's we can be opportunistic and just add the single line of code to make sure that we already render a state while we're actually waiting for the server to respond. And that again is a case where we don't usually have validations.
Speaker 2:There's no obstacle to moving an event into a new day. And so we we aren't usually going to see an error from the server in that case. But even if you say I want to convey that this is not a final change, there are, like, ways to, like, add a class to the event that says pending or something and then you list. I don't know. Like, reduce the opacity is always, like, you convey that this is a temporary change, and it would still feel, more snappy snappier than, like, just, freezing the calendar until the server responds in 200 milliseconds or so.
Speaker 1:Yeah. I like that. I mean I think you're you're that totally makes sense. You know, I was thinking of this sort of optimistic, you know, where you usually are turning one version of something into another. Like you're turning a form into an element that's then gonna have a different style.
Speaker 1:But, you know, the the easier like the more straightforward is you're moving one element to another place and you're right. You have all the information you need to just drop that element into its new location temporarily, you know, and and then apply something to it if you want to. So that's sort of like the so that's like a Trello board. So and you were talking about drag and drop, is that is is drag and drop so drag and drop is another thing that I see a lot, as like, okay, we're gonna we're gonna need a react to style we're gonna need an SPA style, you know, to to build a Trello board, to build a calendar thing, something like that. I know there's a drag and drop API on the web.
Speaker 1:Is is that something that on Poly that you guys have that you've worked on at all in in terms of that stuff to make that particular story you just described a little easier or or how does that sort of work in your mind?
Speaker 2:So there's there's no, so we don't wrap the drag and drop API from HTML. Yeah. We we we need to pick those, we need to choose the extraction that we see being implemented in the same way in multiple projects and we haven't seen this in drag and drop so much. Right. But like the way you would build it in in ampoule is so maybe you have some you probably have some container that wraps for instance your month in a calendar app that's called, I don't know, dot month.
Speaker 2:And then or, I don't know, dot calendar or something. And you and you and you say, I want to register a new compiler, which is our way to activate JavaScript on existing elements that says, whenever an element with class month goes into the DOM, run this JavaScript to initialize the default HTML drag and drop handlers on that element. And that's that's, how I would approach this problem.
Speaker 1:Yeah. No. And this and this would be just like a, you know, add event listener type thing Yeah. In JavaScript. It says a But,
Speaker 2:I mean, there's there's so many edge cases, you know. For if you want to if you want to reorder stuff, it's that's, like, it's important if you're, like, in the upper half of the element because that's, like, a different track a proposition and so on. So that is that something that that I don't want to I don't want to become a drag and drop library because I already had
Speaker 1:Yeah. Those are too many Too
Speaker 2:many things I'm rapping. Yeah.
Speaker 1:But being able to do like what you just said with the optimistic, you know, having a having a solution to being able to at the end of the drag and drop, not just because what I mean what happens by default is like you finish your drag and drop and then it goes back to where you started from And then you wait for the server and then it drops. So you get this weird, like, I dropped it. It's gone. Where'd it go? What's happening?
Speaker 1:Did I mess up? Oh, it's back. You know, now it's from the server. Now it's live. So just having, you know, some solution to that, makes a huge difference, I think.
Speaker 1:So I I think that's a that's a nice, that's gonna be a nice addition, I think, in general. Do you use any of the, like, view transition stuff that's kind of, I don't know if to say if it's new in the browser, like, is that something you've thought about? Because just the the approach that un poly takes seems to be, you know, matching up css selectors and kind of adding to the dom, replacing from the dom based on a lot of defaults which, like, if you're giving it the same selector it's pretty safe to say you want to be replacing that, which makes a lot of sense. And I think that's kind of also the directions that browser have been going with this view transition stuff. So even in an MPA, now theoretically, and I haven't I have not played with this myself much yet because I just, like, I guess I just don't care that much about transitions, but, you know, if you have 2 separate pages and you assign view transition you put view transitions on, it will and you click from one to the other, it will theoretically if you had 2 things on one version of the MPA and have the same ID, it will transition from one to the next.
Speaker 1:For instance, get larger or something, you know, if you expand an image and the next page has the same image with the same ID bigger, it'll, like, get bigger there for you. So have you messed with any of that stuff yet?
Speaker 2:So we have, like, we have we have a different, animation and morphing API that's, like, predates future the free traditional API by by by, like, quite some years. Yeah. That would be basically just we have those, we have both we have the old and the new element, and we just visually lay them on top of each other, and then we can stuff like cross fading or, like, the the one thing slides out from the left and the one other thing goes in from the right. Or that's something, like, we can do. What we we cannot do as well as the Fusion Edition API is this automatic morphing of, like, this shared element where, like, a thumbnail that grows to the, I'm not sure how well we're doing.
Speaker 1:I will say, like, I've seen a demo of it, but I've never I've never actually, like, got it to to function correctly.
Speaker 2:So it's it's it's another thing that, like, like, because I already told you that, like, something that we, like, eyeing for, like, word for is, like, replacing a lot of stuff with, like, built in capabilities. Yeah. But, I mean, the future edition API has has some, limitations. Like, you cannot have multiple of them at once. Like, exit animations are hard, stuff like that.
Speaker 2:So, again, it's a thing that would save us some JavaScript, but, like, would cover, like, fewer edge cases than we have right now. So
Speaker 1:Tough to get rid of those edge cases. You worked hard for those edge cases. Like, edge cases build up over a decade and they're pretty great by the end. Like, that's Yeah.
Speaker 2:Like, I mean, yeah. I mean, it would it would be a breaking change. But Yeah. Yeah.
Speaker 1:That's a tough call. I don't know. So who else is, like, you know, Unpoly, is it, like a GitHub, you know, open source project that people contribute to? Or is it something just kind of on the Unpoly site and people just kinda download it and use it? Like, where do you sort of see it?
Speaker 1:Or or what is it? I I actually don't don't know if it's something people contribute to.
Speaker 2:Yeah. So we have a pretty extensive documentation site on unpoly.com. It's also an open source project project. Right now, the maintainers are, like, mostly myself and, like, to a lesser extent, some of my colleagues. Like, we have some, like, contributions, of course, but those tend to be, like, more bug bug fixes and documentation changes and so on.
Speaker 2:Like, I also have, like, this some also someone, Adam, who helps me, like, like, triage, issues on GitHub, which has become quite a task.
Speaker 1:Mhmm. Yeah. What sort of issues do people come across? I mean, is it like is it like those edge cases kind of thing? Or is it like, you know, I mean, just sort of in your opinion, like, when you look at the project, like, big picture, like, what sort of stuff is is coming up for people?
Speaker 2:I mean, on the one hand, people will always have edge cases, like, I don't know. Someone enters the URL with, like, with with 3 slashes and something crashes.
Speaker 1:So if something ends ends their URL with 3 slashes? Okay. Yeah.
Speaker 2:For instance, that's something I I I didn't think about. I
Speaker 1:mean, is it legit? Is that is that a real way to end a URL?
Speaker 2:It's not the browser will make a request and our code runs, so we probably need to deal with that eventually. But then again, people have actually ideas that grow into larger changes. For instance, the whole optimistic, rendering thing, like, came from an issue, like, called allow custom navigation feedback. Because we had we had a way, like, to, like, add classes to the target element that was loading for quite some time, but, they Yeah. That makes sense.
Speaker 2:Ran ran into some, limitation with that. And, then that actually grew into, the idea. Is there maybe a way to do something like optimistic rendering? And that grows into, like, a, like, a 4 month project, in the library. Yeah.
Speaker 2:But overall, I think, by now we have, like, covered, like, a lot of ground. So the the issues tend to grow a little tamer over time.
Speaker 1:Yeah. I mean, I think, you know, that's one thing that I I have, you know, noticed about about HTMLX and also some of the other, you know, libraries that are are and and frameworks that are doing similar stuff to on poly as well. But it's like the core stuff, there isn't a need to sort of change that much all the time, you know. Like, I mean maybe you can, you know, you're adding new features and stuff like that, but it doesn't seem like you have this kind of, unless you decide to go deep on the browser stuff and do a big rewrite to incorporate more browser stuff, like the the core stuff is pretty much the same for a lot of versions. Right?
Speaker 2:I mean especially if you, like, have some, like, prior experience in the space, like, for instance, with HMX, it it it grew out of an earlier library called Intercooler. So they the cars had some experience. It's it's I mean, it's it's h max 2, but, actually, it's probably, like, 4 or something because the intercooler was before that. And, I mean, we're also on a major version 3, and, we did some like, drastic cost corrections, with, ampoule 2 and then 3. But by the time you're on, like, major 3 or 4, that's like a time where it I think it's realistic to go into a place where you where breaking changes become fewer.
Speaker 2:I think it's completely unrealistic to have this when you start out. Like, if you have zero experience in a space and start to have any ambitious, like, non trivial API design, you are going to make mistakes. I mean,
Speaker 1:Not even mistakes, you know. It's like, or just like you you find a better path, you know.
Speaker 2:Yeah. Yeah. I mean, that's that's like when you when you start like the initial design, there's there's no time where where you're going to have like less experience about the space than at that point. So it's, it would be sad if you don't load anything and you are going to eventually, break stuff. But but but we right now we've managed to stay on the 3.x line for quite a while and we we found, I think, a good way to deal with breaking changes.
Speaker 2:But we have this separate protocol called, like, ampoly migrate that you can, like, load into your app and that actually contains that that adds support for old APIs going back to ampoly 1. So, the way to upgrade it is you
Speaker 1:That's an interesting approach.
Speaker 2:You bump you bump the bump you bump the version, and you load the migrate script, and that just, like, prints warnings or errors for everything that you're using in the old style. And then you can, like, like, just update the call sites.
Speaker 1:Is that something you came up with, or have you seen that in other in other, upgrades? I've never I've never seen that before. That's a cool idea.
Speaker 2:I think I think jQuery has this jQuery migrate thing.
Speaker 1:Okay.
Speaker 2:For people who can't upgrade right now. Yeah. I mean, at at first, we just we had this issue of, like, these old deprecations growing more and more and taking up file size. So the the colleague had the idea to extract his own file. And, yeah, it's been working quite nice, especially if you have, like, some kind of end to end testing, and you can just, like, make sure that, like, any warning just, like, fails fails the test suite.
Speaker 2:So it's a pretty nice
Speaker 1:way to
Speaker 2:deal with breaking changes.
Speaker 1:Feels very organized to just, like, okay, I'm gonna add a file temporarily, my migration file, and then that's gonna cause problems or show me the problems. And then by the time I'm finished, I will remove this file. I won't need it anymore. That's nice.
Speaker 2:And it also, like, eases the pressure on the API designers. Like, because, like, we know that we have this way to lessen the pain for the users so we can, like, probably live with a breaking change sometimes. Yeah. We have that totally
Speaker 1:things in the world is, upgrading to a new version of something and having just no clue what I'm in for. Like, look at my I have an app, it's got, you know, a 150 pages on it in different places. So what what's gonna break here? I have no idea, so that's a nice I like that, I like that approach. Nice.
Speaker 1:So I mean, yeah, I think, you know, I think just overall I I I think it's super cool that you put this up online and, made it available to other people. I think you could have easily just kept it internal and worked on it and had it, you know, help your business and stuff like that. So I think it's, just super cool. We took that taking that step and putting it out there for the world and getting people to use it. It's an awesome approach.
Speaker 2:Yeah. Thanks. I mean, I really suck at marketing. I don't do this kind of podcast very often because when I have the choice to do marketing or write more code, I always choose more code. So basically the only marketing that this library had was Carson.
Speaker 2:Like, he's like because he's he's he's such a nice nice nice guy, and he always promotes, like, all the hypermedia libraries in the space. Yeah, every time he tweets, we get, like, I don't know, we get, like, a 50 50 additional stars from from people who discovered us. So we so so our marketing department, especially Carson.
Speaker 1:Right. That's awesome. Well, no. I mean, you know, you're you're doing the work and and building the product into something really nice. So it's like when people get a chance to see it, you know, they like it.
Speaker 1:So I I think that's awesome. So yeah. Well, I just you know, anything else you want to, plug or, you know, mention before we go
Speaker 2:I think we've covered a lot of ground. I think it's it's okay. Thanks for your interest. I know this isn't an on Poly podcast. It's an NatureMax podcast.
Speaker 2:And, it's
Speaker 1:No. But it's it's tangential. And Yeah. And, I think it's all you know, the thing is, like, what I really believe is that, you know, people should find the approach that matches with the way they think and the way they, you know it's like everyone has this mental model of the web and of their projects, and the closer you can find a tool to your mental model, the just the faster you're gonna build stuff. And so, I mean, you, for instance, have built the tool to match your mental model perfectly.
Speaker 1:So, you know, that gives just huge benefits. But, you know, for me, h t m x matches up really nicely. On Poly also is in the same vein, you know, I use Livewire. So, like, I use all these projects for different things, and I just think it's, you know, it's something that is, people should find what matches for them. Try stuff out.
Speaker 1:It's super easy to go. You can go to the on poly, you know, website and, like, do a couple of the examples. The one gotcha that I will say because I I did it myself is to I don't think it said anywhere that you have to have the something labeled as up main or use the main tag, but it seems like some of the stuff won't work unless you use that. So just keep that in mind if when you're doing examples. Yeah.
Speaker 2:I think I think the onboarding process could could, like, profit from from from all of. So, like, documentation, I think it's like it's been, like, the most painful part of the project. But we, like, we have a lot of documentation, but it's it all grew out of, like, an API reference, and that's not a great way to, like, get into it. And, like, I know we should, like, do some bad tutorial, like, maybe a video. That's something that that I have on my list.
Speaker 2:Definitely.
Speaker 1:Yeah. No. I mean, hopefully, that can be done in a fun way for you, you know. I mean, it's it's if it's a chore, then it's hard to kind of justify, but, you know, if you find a fun way to show off on Poly through a video or or, you know, a blog post or whatever, you know, I think that's something like that. Just find something that's fun for you and actually fun for you to build and that makes life a lot easier.
Speaker 2:Yeah. I mean, something that I struggle with is, like, because you always need to have the back end component. Like, if you want to demo or, like, a single page app, it's, like, it it always works, like, with just having, like, a static piece of HTML on the page or some JavaScript. Yeah. But, when you want to demo, like, an MPA based approach, you always need to think, like, how am I going to build the back end in a way that it works for all my readers who are going to have different backgrounds somewhere, like, be PHP people, like, know people, Ruby people.
Speaker 2:So that that's something that, that's been challenging.
Speaker 1:Yeah. But, like, what you've done though is, at least on the examples that are there is use HTML, I think. Right? And that is pretty good. I found one of the problems definitely for that.
Speaker 1:I've had, you know, so I'm working on right now and building this, you know, hype CP page, which is a bunch of right now it's just HTMLX, but, the goal is to build up a bunch of examples. And it's the same thing where it's kind of annoying to have to show people here's the file that's gonna be loaded. Right? Like what's the good way to sort of because it's a lot of info. It's like an info dump to show a huge HTML page, you know.
Speaker 1:And so it's like, you know, it's nicer if you just have the code snippet, but it's like you need to still say, like, okay, but it's gonna load this file and put it there. And so, like, just finding a way to show that, I have found, is a little tricky.
Speaker 2:Yeah. I mean, the the the static HTML works for, like, simple stuff like links, but, like, something that we didn't talk today a lot about is, like, complex forms, which is also something that, like, we have a lot of features for. And when you have, like, a form, you need to have, like, some some back end endpoint that processes the form data. And then I need to have some kind of server side code, and I need to have, like, a few template and maybe some, small sample of JavaScript. And that starts to become very hard to convey to users.
Speaker 2:I mean, I can flip I can quickly switch from one to the other, but that that tends to confuse readers who want to get into this. So that's something that I'm thinking hard about right now.
Speaker 1:Yeah. Well well, one of the advantages I think you have, is that because on poly, does do a lot of the defaults for you. Like you like you said, you've set a lot of those defaults. I just this is just my personal opinion, but I I think you could record, a series of pretty short videos to demonstrate kind of each, you know, really just a simple version of each. And then of course, like, you know, people who wanna get into it can get into it and learn about all the different options and all this sort of stuff.
Speaker 1:But, like, because you've already thought about what those defaults are, you don't need to get into anything, just just showing what on Poly does, you know, I think that's valuable just just by itself. Even if you don't go into all the details, like, they can look at the website. Clearly, there's a ton of work and API thought and all this other stuff that goes into it. But just seeing the basics and having getting that mental model in place, I think that would be really valuable for people.
Speaker 2:Yeah. That's good feedback.
Speaker 1:So alright. Well, thank you very much for joining. I I really appreciate you taking the time
Speaker 2:Yeah. Thanks for having me.
Speaker 1:To talk.