#321: HTMX - Clean, Dynamic HTML Pages Transcript
00:00 Have you wanted to add more interactivity and liveness to your web application?
00:03 If you built it using Flask, Django, or some other Python web framework,
00:07 that thought probably didn't fill you with joy. And that's because it might mean you need to
00:12 change a bunch of your code and rewrite a significant bit of your application
00:15 using a full-on front-end web framework like Vue.js or React.js.
00:20 In this episode, we meet Carson from Big Sky Software. He's the creator of HTMX.
00:25 This front-end JavaScript library lets you leverage the server-side aspects of your Python web app
00:31 and add amazing interactivity, but keep the logic on the server near the database and implement it in Python.
00:36 You're going to love it. This is Talk Python to Me, episode 321, recorded May 25th, 2021.
00:43 Welcome to Talk Python to Me, a weekly podcast on Python, the language, the libraries, the ecosystem, and the personalities.
01:02 This is your host, Michael Kennedy. Follow me on Twitter where I'm @mkennedy,
01:06 and keep up with the show and listen to past episodes at talkpython.fm, and follow the show on Twitter via at Talk Python.
01:13 This episode is brought to you by Sentry and Your Base, and the transcripts are brought to you by Assembly AI.
01:19 Please check out what they're offering during their segments. It really helps support the show.
01:23 Carson, welcome to Talk Python to Me.
01:25 Thank you. I'm really happy to be here.
01:27 I'm very thankful that you're willing to go a little bit outside the lines of a normal Python development
01:33 to talk about something like HTMX.
01:35 You know, I'm extremely happy to see HTMX getting picked up, particularly by the Django community in Python,
01:42 and so I was very excited to come on here.
01:44 Yeah, I'm really excited to have you here.
01:46 It is such a cool technology, and I think so often the JavaScript story is,
01:51 oh, you're doing this other technology that you like.
01:55 Let us tell you how you should drop that and go do JavaScript, right?
01:58 And what I feel HTMX brings is whatever technology using Django, Flask, even some other thing like Rails or ASP.NET,
02:07 whatever it is that you already got working really well, here's a really cool way to extend that.
02:12 We're going to dive into that.
02:12 So I think, you know, I've had people reach out and say, oh, I'm a JavaScript developer.
02:18 Let me come on to your podcast and tell people about how cool Node is.
02:21 I'm like, well, I'm not really sure that's the best topic for a Python-focused podcast,
02:25 so I'm going to decline your invitation, but I was really happy to get a chance to have you on the show
02:30 because I think there are many people out there who are nervous about JavaScript.
02:36 They're not yet learning JavaScript.
02:38 They know they need some interactivity, and they feel that means they have to abandon what they've already learned
02:44 or what they actually love, and I don't think that's the case.
02:46 And we're going to dive into that.
02:48 So I think HTMX plus Python web frameworks is a beautiful thing.
02:52 But before we get into that, let's just start with your story.
02:54 How did you get into programming and, yeah, start there?
02:58 Sure.
02:58 Well, I've been programming for a very long time now, and I started programming in college back in 94.
03:04 Actually, before that, I was programming on a Mac and HyperCard, which is a very old technology, which I love.
03:11 The web before the web.
03:13 Yeah.
03:13 Like local web.
03:15 I can talk about that.
03:16 If we talk about HyperScript at the end, maybe that'll come up again.
03:20 But I started programming in college and then very early on started programming for the web back when it was CGI scripts and Perl and stuff like that.
03:28 And then I moved into Java during kind of the original .com boom and did a lot of the was in the Java world for a long time and eventually moved into Rails.
03:39 And so I've been programming in Rails now for the most part.
03:42 I do.
03:43 I program in a lot of different stuff, though, mainly Java and Rails.
03:47 And I have to admit to your audience, please don't judge me too hard.
03:50 But I haven't used Python very much in anger.
03:53 I've used it for local sort of sysadmin scripts, but not for a bunch of web development.
03:58 So but, you know, Rails and Django share a lot of things in common with one another.
04:03 And they're both great server side pieces of infrastructure.
04:07 And I always felt like it was a shame that they were kind of being left.
04:11 They were being ignored to a large extent by the by the bigger JavaScript frameworks.
04:16 One term that I try and coin, there's a lot of different stacks out there, right?
04:20 Like the lamp stack and so on and so forth.
04:22 And one joke stack that I've made up is the Howl stack, which is hyper.
04:27 Howl? H-O-W-L?
04:28 H-O-W-L.
04:29 Okay.
04:30 So HTML on whatever you'd like.
04:32 So use HTML on the front end and then use whatever you'd like on the back end.
04:37 Nice, nice.
04:38 HTMLX is really empowering for this, right?
04:40 I mean, that's kind of the philosophy in some degree.
04:42 I mean, you get a joke stack, but like literally that's.
04:44 Yeah.
04:46 It's a joke, but it's kind of true.
04:47 So.
04:49 Yeah.
04:49 Yeah, absolutely.
04:50 And how about now?
04:51 What do you do day to day?
04:52 So day to day, I teach part-time at a university.
04:54 My passion is actually programming languages.
04:57 So I teach that as well as some other classes at a university part-time.
05:01 And then I also, I work for a startup as well that I've been working on for a long time and
05:06 which uses Intercooler.js, which is the predecessor at HTMX.
05:10 The story with HTMX was that, well, we can go into it in a little bit if you'd like to,
05:14 but that's what I'm doing now.
05:15 So kind of a mix.
05:17 I find myself doing a lot of different stuff.
05:19 Yeah.
05:20 That sounds like a really nice mix.
05:21 I love universities.
05:22 I love university campuses.
05:24 Maybe it's a slightly different story today with COVID, right?
05:28 But I think we'll kind of get back to it.
05:30 But some of my fondest memories are just, you know, spending time dreaming about ideas,
05:35 walking around various campuses.
05:36 Yeah.
05:37 It's a good energy.
05:38 The kids aren't quite as beaten down.
05:40 Some of the, when you're in the corporate sector, I mean, you see a lot of these posts
05:44 on Hacker News and so forth, just old guys, older guys and gals that are just sick of the
05:49 sick of the grind.
05:50 And so it's nice to be around younger kids that are maybe not quite as jaded and there's
05:55 just an energy and, you know, it's a beautiful environment.
05:58 Yeah.
05:58 Keeps you young being around that crowd.
06:01 I do think that's awesome.
06:02 So I want to start our conversation by taking a little bit of a step back.
06:06 And I think we've circled around this a little bit, but when people are working in some technology,
06:13 let's focus on Python, but it could be Rails, like you had said before, and they've got something
06:18 working really great.
06:19 You come to some part of the site and it's like, well, this should be really interactive.
06:23 Like I want to click on this thing.
06:25 And depending on what I select here, I want that dropdown to select that other thing.
06:29 Or as I search here, I want it to actually just fill it as I type.
06:34 I don't want to have to type in the search text, hit enter, see what comes back from the
06:38 server.
06:38 Oftentimes that is sold as a, well, your site is going to be more responsive if it's running
06:45 on the front end.
06:45 And sometimes that's sort of true, but I feel like a well-designed website can be really
06:51 responsive.
06:51 Like I don't really feel like the speed thing is the story, but this interactive like navigation
06:55 thing where it resets where it is, like that is a real challenge.
07:00 And so often people get pulled down this path, right?
07:03 Well, you want to have that experience.
07:05 So is it Vue.js or React?
07:08 What are you going to do?
07:09 And then 10,000 lines later, a front end code, you've winnowed down your backend to
07:14 just a couple of simple HTTP API methods.
07:17 Then also something that serves up like a HTML static page.
07:22 And then the question becomes, well, why are we doing Python or why are we doing Rails at
07:27 all?
07:27 Why don't we just do Node on the backend and we just have that as our entire stack?
07:32 I feel a lot of times people either end up going down that path and throwing the baby
07:38 out with the bathwater type of thing, right?
07:40 Like you have this really cool server side ORM and a bunch of stuff happening that you really
07:45 love from your server side, say Django or whatever, but you kind of already gone.
07:51 Like you're just so close.
07:53 You're just like, well, let's just, we're already mostly writing JavaScript.
07:55 Let's just write JavaScript.
07:56 So I think that's one side of the story.
07:58 And I think there's real pressure on the other web frameworks and Python and other spaces
08:02 for that.
08:03 The other side is people who are not doing that, but they feel bad.
08:06 They're like, I know I'm doing it wrong.
08:09 I know I'm not using React.
08:10 I'm just using Django, but this is all I know.
08:14 And I just not ready or we're just not a big enough team.
08:16 How's that sit with you?
08:17 What do you think about this?
08:18 Yeah, I didn't like that.
08:20 That's exactly the pressure.
08:21 I don't like it either.
08:22 That's why I'm so excited about HTMLX.
08:24 That's exactly the pressure that I felt on Rails.
08:27 I liked Rails.
08:28 Ruby is a programming language I'm so, so on.
08:31 It's fine.
08:32 It's got its issues.
08:33 But I liked Rails quite a bit.
08:35 And I just disliked that pressure to adopt something else on the backend that came with using these
08:41 more complex JavaScript frontends.
08:43 And like I said earlier, it was just a shame.
08:46 And the other aspect of that is when you go to that model, when you go to the Vue.js or the
08:51 React model, your backend becomes pretty dumb.
08:54 It's just producing JSON.
08:56 You know, there's validation code.
08:58 And, you know, yeah, your validation code can now live on both sides, which is important
09:02 because the front end is not a trusted computing environment.
09:05 So you can't trust validations that are done on the front end.
09:07 You always have to redo them.
09:08 You just redo them again anyway.
09:10 That's right.
09:11 So there's just all these kind of, I don't think they're complete arguments, but just, it's just with the grain to start pushing JavaScript onto the backend, especially once Node really came out and gave JavaScript a good runtime on the backend.
09:24 And it's not a good thing.
09:26 And the reality is, is I hope we can demonstrate with HTMX today that a lot of very good UI or slash UX patterns from the web can be achieved using just HTML, using the original HTML model, the original RESTful model for the web.
09:44 I know that's kind of a fancy term, but just using the original model of the web, just kind of generalizing what we're already familiar with in our day-to-day development, links and forms.
09:54 That's where HTMX is coming from is this idea.
09:57 Wait a second.
09:58 Let's take a step back.
10:00 We don't need a super complicated front end.
10:02 We just need to improve HTML.
10:04 Right.
10:05 We don't have to push it all down to the front end.
10:07 Right.
10:07 We only need to push a little bit of that interactivity down, right?
10:10 That's right.
10:11 And that interactivity can be defined in terms that are very familiar to us from normal HTML.
10:17 So let's just take HTML and try and push it as a hypermedia or hypermedium, I guess I should say.
10:25 People get mad because hypermedia is plural, but I say it.
10:29 So, you know, that's where HTMX is coming from.
10:32 It's very similar.
10:33 You know, this frustration with the industry, particularly.
10:37 I don't think this is strong now because Python has had, I mean, you go and you look at the trends and Python is just crushing right now.
10:43 Yeah.
10:44 It's such a, not a resurgence, but such an acceleration from where it was.
10:48 Right.
10:48 You know, 10 years ago.
10:50 And I think if you compare that with five years ago, JavaScript was really the thing that was accelerating the most.
10:55 I don't think that's true today.
10:56 I think JavaScript is maybe plateauing a little bit.
10:58 There's still plenty of JavaScript out there, obviously.
11:01 But I feel like Python is really taking off because of, you know, big data and some of the AI tools that are available in Python.
11:09 And so some of the great older tools like Django and Flask that have been around for a long time and that do a good job.
11:15 So, again, just a very similar situation with you where I'm looking at this going, man, this stinks that you have to become either like a killer JavaScript front end engineer and then have two languages that are pretty complicated or abandon whatever backend you prefer in favor of JavaScript.
11:35 Yeah.
11:35 I'm 100% with you.
11:36 Let me pull up a couple of things.
11:37 One, here's that graph that you were talking about.
11:41 Yeah, that's exactly the graph.
11:42 Of Python going pretty wild.
11:44 Like, you talked about JavaScript plateauing.
11:47 So this is the stack overflow, you know, stack overflow trends for the major programming languages.
11:52 So this is really surprising to me and I find it quite interesting here.
11:56 Yeah.
11:56 Also, a couple of things from the live stream.
11:58 Nick Harvey.
11:58 Hey, Nick says, for me, it's a constant battle between all the benefits of server side.
12:03 Plus, I don't want the page to keep refreshing.
12:05 Yep.
12:06 I sympathize, Nick.
12:07 And that's exactly what HTMX is designed to help with.
12:10 The real bad part about the original web and browsers, we have to say, I think you made this point earlier, Michael.
12:16 Browsers have gotten better at making the page transition not quite as clunky visually.
12:22 So you can do sort of web 1.0 style apps and get away with it for a lot of stuff.
12:27 Yeah.
12:28 You talked about doing programming in 94.
12:31 And I remember the first mosaic that I saw that was the graphical web.
12:36 And I was just, my jaw was just dropped.
12:39 I'm like, this changes everything.
12:41 I've been using Telnet and like Gopher and all sorts of crazy stuff.
12:46 Oh my gosh.
12:47 And I'm just like, this is a new world.
12:49 I literally think I had to skip the next class I was supposed to go to because I'm like, I can't, I have to explore this.
12:54 This is unbelievable what I've just found.
12:56 But I remember it going clunk, clunk.
12:57 You could just see it building the page as it comes.
13:00 And that was, yeah, luckily it's not like that.
13:03 It's the big problem.
13:04 It is, you know, it's much better now, but it's still a problem.
13:07 And it's a big problem for many UX patterns.
13:09 You just, you don't want it.
13:10 And that's exactly what HTMX is designed to help with.
13:15 So you can stay within that original model of the web.
13:17 You can use whatever backend you want to produce your HTML, but we can get better user experience out of it.
13:23 Yeah.
13:23 Yeah.
13:24 So also RJ out there in the live stream says, I just discovered HTMX a few days ago.
13:29 Great timing.
13:29 This portion of Talk Python I May is brought to you by Sentry.
13:34 How would you like to remove a little stress from your life?
13:37 Do you worry that users might be having difficulties or are encountering errors in your app right now?
13:42 Would you even know it until they send that support email?
13:46 How much better would it be to have the error and performance details immediately sent to you, including the call stack and values of local variables and the active user recorded in that report?
13:56 With Sentry, this is not only possible, it's simple.
13:59 In fact, we use Sentry on all the Talk Python web properties.
14:03 We've actually fixed a bug triggered by a user and had the upgrade ready to roll out as we got their support email.
14:10 That was a great email to write back.
14:11 We saw your error and have already rolled out the fix.
14:14 Imagine their surprise.
14:15 Surprise and delight your users today.
14:17 Create your Sentry account at talkpython.fm/sentry.
14:21 And if you sign up with the code talkpython2021, it's good for two months of Sentry's team plan, which will give you up to 20 times as many monthly events as well as other features.
14:32 So just use that code talkpython2021 as your promo code when you sign up.
14:37 Yeah, so speaking of which, let's go ahead and let's get into it, right?
14:42 So we've set this up as a, it doesn't have to be either or.
14:46 It doesn't have to be either Django or Flask or React or Vue, right?
14:51 Like, it doesn't necessarily have to be that way.
14:53 And there's some really cool stuff going on here.
14:55 Like, let me just read this little introduction you got over here at htmx.org.
14:59 It says, htmx allows you to access AJAX, CSS transitions, web sockets, server sent events directly in HTML just using attributes so you can build modern interfaces simply.
15:10 Which is really nice.
15:11 And one of the things that frustrates me about these frameworks, like I do some stuff in Vue and like, I'm not against it.
15:18 I just want to put out there, I realize there are apps that are absolutely making sense to build with Vue or with React, right?
15:25 Are you trying to build a mobile app that is really sort of a progressive web app?
15:30 Like, oh, that should absolutely be in that.
15:32 Are you trying to build Gmail?
15:35 It should very likely be in something like Vue.
15:38 But most of us just want a sprinkling, like a little salt, you know, a little bit of niceness here and there to our app.
15:45 And in order to get that, these days JavaScript has moved so far that it's no longer this simple little language that you just include a tag and then to the file and you're good to go.
15:55 It's like you've got Webpack and you've got CLI tools and you've just got all this stuff to go, right?
16:01 So what's the getting started experience for htmx?
16:05 Yeah, htmx looks pretty straightforward here.
16:07 Yeah, it's a small, it's a no build library.
16:11 So there's no build step associated with it.
16:14 You just drop it in.
16:15 I mean, you can use a CDN if you want.
16:16 The starting experience for it can be as simple as just adding a single attribute or maybe two attributes would be the minimum thing.
16:23 And so it's not, it doesn't require a total rework of your front end.
16:28 And that's one thing, you know, one concept I like to talk about with my students is this idea of a complexity budget.
16:33 Your application has a complexity budget.
16:35 You need to spend it effectively.
16:37 And so with htmx, you can pick the parts of your app that need it and add interactivity to them.
16:43 And the remainder of your app can remain just a standard, you know, web app that works the normal way.
16:49 And because of that, you can sort of spend your complexity budget where you want to on your app rather than saying, okay, we're going to, we're going to react.
16:58 And now we need a react router.
16:59 And now we need GraphQL.
17:00 We need all this stuff to make.
17:03 Our next sprint is going to be the rewrite sprint.
17:05 Right.
17:06 I hope it's, you know, people would agree that it's, it's a lightweight library in that sense.
17:11 And that you don't, you don't need to do a whole lot to make things work within one particular.
17:16 There's some attributes like HX boost, for example, that you can just kind of toss on your, you know, on the body tag and it'll turn all the links into Ajax requests and all the forms into Ajax submissions.
17:27 And so it's kind of like a turbo links, if you're familiar with that technology and that sense.
17:32 So we, you know, there's, that isn't a big focus of the library, but it's there as well.
17:36 So hopefully relatively lightweight and the user experience.
17:41 I was going to say, so you basically include a script tag to link to HTMX, 10 kilobytes and it has no dependencies.
17:49 Yep.
17:51 Yeah.
17:51 RJL out there in the live stream says, I strongly believe that these JS libraries, speaking of view and react and whatnot, are overkill for the majority of CRUD apps that exist on the web.
18:00 Probably 90% of the CRUD apps are built within private corporations.
18:03 And I've been doing that since 94.
18:05 And then also does NPM and web pack are both a blessing and a curse.
18:09 Yeah.
18:10 Especially if you're a backend sort of person.
18:12 Yeah.
18:13 I never liked big, complicated build tools in any, you know, in any, even on the backend, I just, I'm not a big fan of them.
18:21 I like dependency managers, but beyond that, I don't want a bunch of stuff going on.
18:25 Yeah.
18:26 I'm with you on that as well.
18:27 All right.
18:28 So let's talk about the motivation that you got here before we get into some code, because I think it really sets the stage.
18:34 I mean, obviously we've, we've been studying the motivation here, but you know, you throw out some questions, some hypotheticals like, Hey, why should only anchor tags and forms be able to make HTTP requests?
18:46 Like if I click on an image, shouldn't it be able to make an HTTP request?
18:51 Why should click and submit be the only events that trigger them?
18:54 Right.
18:55 Like I don't know, mouse over or key down or something like that.
18:58 Right.
18:58 Probably key down for a smart auto-complete search.
19:00 Why should only get and post be available?
19:03 And why should you, why should they only replace the entire screen?
19:06 Yeah.
19:07 And that last one's really the crux for what Nick was talking about earlier, right?
19:11 Is web requests have to do this big, chunky, replace the whole screen.
19:17 If you have an action that only updates a small amount of that screen, why not just return the HTML for that small amount of the screen?
19:24 And then in that element that's issuing that request specify, Oh, put the return content into that thing.
19:32 And that's exactly that.
19:34 So HTMX has an attribute called HX swap that lets you, or excuse me, HX target that lets you say exactly where you want to place the return to content.
19:44 And then HX swap is another attribute, which lets you tell HTMX exactly how to do that swap.
19:50 If you want to replace the whole thing or just the inner content or append it or whatever.
19:54 So let me lay out an example here of a type of app that feels like it would need view or something.
20:00 I'm just going to pick on view.
20:02 It's like the catch all for all the major front end frameworks going forward.
20:06 So imagine I've got like a photo gallery of like five images up on the screen.
20:12 And I want to be able to click on that image and then have like a details of it.
20:16 Like maybe the exit tags or like where it was taken or other stuff stored about it on the server.
20:22 Maybe it's like a Wikipedia thing and like you click on the picture and it gives you some details about the picture below.
20:28 And you just want to keep that there.
20:29 And as you click on them, maybe even use an arrow keys or click around between them and have that happen.
20:34 That's the kind of thing you're talking about, right?
20:36 Like I could set it up so I could have an event where I interact with the image and it does a swap.
20:42 And explain to me what I have to write in order to get that bottom part to like reload.
20:47 Yeah, all you would do is on that image, you would say HX get and you would give it the URL to get that information from.
20:53 And that information would come back in HTML form.
20:55 And then you would say HX target.
20:58 And there would likely be a div down below that would be your details div.
21:03 And let's say it has the ID details.
21:05 So your HX target attribute in that case would be hash details.
21:10 And that tells HTMLX when this request comes back, take that content and jam it into the details div or whatever that has the ID details on it.
21:19 Yeah, so that bottom section.
21:20 And then if you want to, you know, depending on how you want to do that swap, the HX swap attribute lets you say inner HTML.
21:26 Default is inner HTML.
21:27 So it'll swap that into the inner HTML.
21:30 But maybe you want to replace the whole thing for whatever reason.
21:32 You could say HX swap outer HTML.
21:36 And then there's a bunch of attributes there.
21:38 And there's some syntax in there.
21:40 Let's see, control scroll state, whether or not something gets pushed into history, depending on how you want to do that and so forth.
21:47 And so there's a lot of stuff like that that lets you determine exactly how that swap is going to happen.
21:54 Yeah.
21:54 Fantastic.
21:56 So right on the home screen, you've got kind of an example that is commented.
22:03 Without the comments, it's four lines of HTML.
22:07 Right.
22:08 And that's the entire application.
22:10 I guess you probably would want to wrap that in like an HTML and a body tag.
22:14 But beyond that, right?
22:15 So what you do is you include the script and then you have a button.
22:18 And on the button, you have an attribute that says HX-post equals slash clicked.
22:24 Then you have your HX-swap equals outer HTML, presumably of the button.
22:30 Right.
22:30 So you could say click the button and the button would replace with like a map of where you are or a grid of results or whatever the heck the returned HTML from slash clicked is.
22:41 Right.
22:41 Yeah, that's right.
22:42 And it's HX-post, right?
22:43 Is that what you said?
22:44 Yeah.
22:44 HX-post.
22:45 I probably said it wrong.
22:46 But yes, exactly.
22:47 That's what I meant.
22:48 Oh, no, it's okay.
22:48 I just want to make sure.
22:49 Yep.
22:50 Yeah, yeah.
22:50 Keep me honest.
22:51 No, it's all good.
22:52 It's hard to do code visually.
22:53 My screen is flickering again.
22:55 So I want to make sure I'm on the same page as you here.
22:57 Yeah, yeah, yeah.
22:58 This is just a quick start at the homepage.
22:59 This is so neat because when people think about all the stuff they have to do, in order to adopt this type of dynamic page that you're talking about, what you have to do is you have to have a method on the server, a view method on the server that returns
23:17 HTML fragments.
23:18 Right.
23:19 Instead of returning, you know, the whole HTML body, whatever.
23:22 Like if my story where I said I'm going to put a grid of results, you have to have a server side thing that can generate HTML for a grid.
23:30 Right.
23:31 So you could do that with like a template like a Jinja or a Django template or a Chameleon template on the server and just pull the data out of your database, bind it.
23:41 And instead of returning, have your template contain a full bit of HTML.
23:44 It's like an HTML fragment.
23:45 Yeah.
23:46 Exactly.
23:47 Exactly.
23:47 In Rails, they're called partials.
23:49 That's the language the Rails community uses.
23:51 But it's just a sub-template.
23:53 And so typically what you would do in an HTML based application is you would have your normal templates and then they would include these sort of sub-templates or partials, again, to use the Rails terminology.
24:07 And so the HTML kind of pushes the factoring problem to the back end.
24:10 So you factor your templates out on the back end rather than maybe creating components on the front end is how someone more familiar with Vue might think about these things or React.
24:20 Yeah.
24:21 It's like the little component bit on the server side there.
24:23 Yeah.
24:23 Yeah.
24:24 So you do your factoring on the back end and then hopefully you're designing a good URL schema, a nice RESTful URL schema, and it all kind of makes sense with sub-resources and so forth.
24:34 Right.
24:34 So in this example, there's just a button.
24:36 It just goes to slash clicked.
24:38 But in my scenario where I had five images, the URL, like the hx-post could be slash detail slash one, slash detail slash two.
24:51 And when you render the original HTML, you can preload into those embedded pieces the right data to pass on when it gets clicked or it gets interacted with.
25:02 Right.
25:02 Yeah, exactly.
25:03 So that image is a resource.
25:05 If we're thinking restfully, that image is a resource on the server.
25:09 And so it has a URL associated with it.
25:12 Let's say images slash one.
25:14 Let's just say that.
25:15 And then images slash one might have a sub-resource of images slash one slash details.
25:21 And so you would, you know, you render that image slash ID slash details is what returns the details you were talking about earlier.
25:30 And you would probably use hx-get in this case because it's a, you're retrieving information without a mutation.
25:36 So post is probably not an appropriate HTTP verb or action to use.
25:42 And so you would get that and then, you know, slam it into the div below the images.
25:47 Right.
25:47 That's almost exactly what you would do if you were going to write a server-side only thing.
25:53 Right.
25:53 It would just pull up that details page and it would have a back button to get to the other ones or something like that.
25:58 Or maybe it would reload the whole page and then just stuff that in the bottom.
26:01 Yep.
26:01 So the experience of writing is almost, it's almost unchanged, right?
26:05 You get to fully leverage the server-side thing.
26:08 It is.
26:08 And that's a great point.
26:09 It's very similar to a link, right?
26:11 And the advantages here are that you don't have that clunky user experience.
26:16 You do have a smaller payload.
26:18 That tends not to matter that much.
26:20 People make a bigger deal out of that than I think is necessary.
26:23 Yeah.
26:24 But it really retains that simplicity.
26:26 And on top of that, you also have all these tools that have been developed over the last 20 plus years of web development that are suddenly available to you again, such as caching and SQL tuning on the backend and so forth.
26:38 All that institutional knowledge that we've built up about how to create good, fast web applications applies using the HTMX model in a way that is not as obvious if you're front end.
26:51 You know, there's a whole separate style of development for developing JSON APIs at this point that just doesn't have a lot to do with that original model.
26:59 And so we're relearning things.
27:01 How do you, you know, that's, that model is really RPC, remote procedure call, I think.
27:06 And so that is just a different mindset than the hypermedia infrastructure that we're used to as web app developers.
27:13 Yeah, for sure.
27:15 So you talked about this complexity budget before.
27:18 And one of the things I like about this is I can have already built my application and I can decide, you know what, it would be a lot better if instead of doing a full refresh for this part, we could just add some interactivity to this.
27:33 Right.
27:33 Right.
27:34 It feels to me like it's very easy to go to an existing web app and add this more dynamic nature to it.
27:41 Yeah.
27:42 In certain focused areas with HTMX.
27:44 Yep.
27:44 Exactly.
27:45 You know, that's, again, I advocate for that.
27:47 I think a good MVP written in the web 1.0 style can validate your app.
27:53 You can start getting feedback very quickly without this really expensive from in development terms, front end investment in your technology.
28:01 And then once that works out, you can start seeing how users are using your app and improving it from there.
28:07 And so it lets you delay committing your complexity budget deeper into the development process.
28:14 I think that's a big advantage of these lighter weight front end frameworks.
28:17 Alpine JS is another one that I think lets you do that to an extent.
28:21 You can just kind of sprinkle in when you want.
28:23 And in fairness, I have heard people say that Vue can also be used in this way.
28:28 So I don't want to say that's exclusive.
28:31 Yeah.
28:31 Yeah.
28:32 If I had to pick a rich front end framework, Vue is certainly where I feel really happy.
28:36 because while it does have the CLI stuff and it does have a lot of that style, it also has ability to just drop in a JavaScript file for Vue JS and then indicate here's a sub tag or some subset of my page.
28:52 And now that's the app.
28:53 Make this page go right there.
28:55 There's that nice aspect.
28:56 But yeah, I just feel like the, you still get to do all the important stuff on the server here, which is pretty cool.
29:03 Yeah.
29:04 Yvonne out in the live stream says, I heard about HTMX at DjangoCon EU.
29:08 Really like the project.
29:09 Fire, fire emoji.
29:11 Yeah.
29:11 We got a lot of mentions at DjangoCon EU and I'm hoping we'll get a bunch at the US DjangoCon as well.
29:19 And, you know, I'm not, again, since I'm kind of, I have to, again, admit a little bit of an outsider in the Python community.
29:26 You know, I'm hopeful that I can make more contacts and really help HTMX help Python developers stay in Python.
29:34 So, yeah.
29:36 Do this more.
29:36 Do you provide better user experience for your users, but also stay within the Python world.
29:42 It's, you know, obviously just, it's growing gangbusters.
29:45 So.
29:46 Yeah, for sure.
29:46 Well, if your screen is willing.
29:49 Yeah.
29:50 Actual screen on your, like actual monitor is willing.
29:53 Let's look at some examples.
29:55 So.
29:55 And I have to admit, I'm flying blind right now.
29:58 My screen is blinking on.
30:00 All right.
30:00 So, but.
30:01 Hopefully you're, I'll try to describe it.
30:03 Yeah.
30:03 I've got my phone up so I can follow along.
30:05 Yeah.
30:06 Perfect.
30:06 Sorry.
30:08 Linux.
30:08 No, no, no.
30:09 It's all good.
30:10 It's all good.
30:10 For just people listening.
30:12 It's not that like the screen sharing is not working.
30:14 Like the actual whole display is having trouble.
30:16 Yeah.
30:17 But luckily it's still going.
30:18 Yeah.
30:19 I know.
30:19 I switched to Linux two years ago and 99% of the time it works great.
30:23 But of course on this podcast.
30:24 Yeah.
30:25 It's fine.
30:26 It's all good.
30:27 Murphy waits for the maximum pressure.
30:29 Yeah.
30:30 Maximum pain.
30:31 It's a straight.
30:31 Exactly.
30:32 Let me just go through a couple here that I think would need.
30:37 I have pulled them up.
30:38 One of them was this active search because I feel like this is the type of thing that is
30:43 like really easy, but also really calls out for some interesting JavaScript thing.
30:49 So over here, you've got a page.
30:53 You don't have the outer shell bits, right?
30:55 Body.
30:55 Yeah.
30:55 But whatever.
30:56 You don't need that, right?
30:58 You've got a header that says what we're going to do is we're going to search.
31:02 Yep.
31:02 And then you have an HTMX indicator next to the title.
31:06 Yep.
31:07 Presumably when something's happening over an AJAX request, that thing spins.
31:10 And then when it stops, it goes away.
31:12 Is that what that means?
31:13 Yeah.
31:13 So the class HTMX indicator is a class that's dynamically indicated or excuse me, dynamically
31:20 added to your webpage.
31:22 And it allows you to start with an opacity of zero.
31:25 And then when a class is added to it, it'll transition to an opacity of one.
31:32 And so that's the best pattern that I found for having a request indicator.
31:35 And one of the problems that you run into in all, you know, even normal web requests, browsers
31:41 these days often don't do a very good job of notifying users something's happening, right?
31:46 And so this is particularly a problem when AJAX is in play.
31:50 There's no indicator to say, hey, something's going on.
31:53 And so HTMX provides infrastructure for doing that sort of thing for you.
31:58 And you don't have to do anything, right?
31:59 Just having this thing exist.
32:01 It knows, okay, if I'm doing a request somehow, some way, what's happening?
32:05 You do have to call out the indicator that you want to show.
32:08 Now, one thing I should say with attributes, they're typically inherited.
32:12 So if you had one indicator that you wanted to show for all AJAX requests, for example,
32:16 you could put the AJAX indicator attribute on the body of your web app.
32:22 And then all AJAX requests would then use that because it's as with CSS, attributes are inherited
32:29 and most attributes are inherited in HTMX.
32:33 And so you can hoist attributes up the DOM and have them apply to multiple things.
32:39 Fantastic.
32:40 So you can avoid repeating yourself using that technique.
32:44 Okay, cool.
32:45 So we've got that little indicator there.
32:48 And yeah, like you said, so you've got to indicate which indicator you want to use, but you don't
32:52 have to trigger it.
32:53 Exactly.
32:53 Then you've got an input, like a text input, and it has a placeholder.
32:57 It just says, please begin typing to search.
33:00 It has a HX-post, which is slash search.
33:03 Presumably it's posting the data of it as a form, right?
33:08 Yeah, it's posting it.
33:09 Yeah, exactly.
33:09 It's posting it and including the, by default, if it's on an input, it'll include that input's value.
33:15 Nice.
33:15 And then it has a trigger.
33:17 Yeah.
33:17 So the trigger is key up.
33:19 Yep.
33:19 Changed.
33:20 Yep.
33:20 That's two things, right?
33:21 Like, so if I command V it or like somehow like drag text into it or key up.
33:26 So the either event, is that what that's saying?
33:28 Changed is a little different.
33:30 So key up is the event that we're responding to.
33:33 And then change says only issue requests if the input value has changed.
33:37 Got it.
33:38 Okay.
33:38 So if I somehow hit.
33:41 So if you hit an arrow key, for example.
33:42 Yeah.
33:43 Yeah, exactly.
33:44 Okay.
33:44 Got it.
33:44 Arrow key.
33:45 The value doesn't change and you don't want to issue a request in that case.
33:49 Yeah, that makes sense.
33:49 The other thing you have is delay 500 milliseconds because, you know, it depends on what the event is.
33:56 Like click it.
33:57 It maybe doesn't matter, but like mouse move.
34:00 You're going to get a lot of those events, right?
34:02 You want to just wreck the server uselessly.
34:05 You want to say, okay, like, did it just flash, flash, flash the screen?
34:08 Like just wait till they've slowed down typing.
34:11 Right, exactly.
34:12 So this is called debouncing an input, right?
34:14 You don't want to, on every event, you don't want to issue a request.
34:19 That would be crazy and not a good user experience.
34:21 And certainly it would be very hard on your server.
34:23 And so what you can do is you can add a delay modifier to a trigger and say delay, wait until a key up.
34:32 So if a key up occurs, wait 500 milliseconds.
34:35 And if another key up occurs in that 500 milliseconds, don't issue the original request.
34:40 So you effectively wait for the user to stop typing before you issue a request.
34:44 And there's another option, which is a throttle, which might be more appropriate for mouse movements,
34:50 where you say only issue a request every, you know, one, every second or something, according to mouse moves.
34:56 Depends very much on what you're trying to accomplish with your UX.
34:59 Those are two different techniques for it.
35:03 This portion of Talk Python to me is brought to you by YourBase.
35:07 I'm excited to welcome YourBase as a new sponsor of Talk Python.
35:10 YourBase has a really cool product that will dramatically improve testing and CI of your Python applications.
35:16 If you could benefit from having pytest run your test 100 times faster or more, you need to check them out.
35:22 Here's how it works.
35:23 YourBase observes what tests interact with which part of your application code.
35:27 And the first time you run it, the speed is roughly the same as normal.
35:30 But the next time you run pytest is where the magic is.
35:34 YourBase knows which parts of your application code has changed.
35:38 If the code under test hasn't changed, why test it again?
35:41 So YourBase only runs the tests that have interacted with the part of the code that has.
35:46 If you change just a couple of functions, you only need to run the few relevant tests and all the others can be safely skipped.
35:53 This means skipping hundreds or even thousands of tests most of the time,
35:57 making your dev test workflow and your CI builds much, much faster.
36:02 All you have to do is install YourBase and run pytest as usual.
36:06 They'll take it from there.
36:07 Get your free trial by visiting talkpython.fm/YourBase.
36:11 YourBase test acceleration works with the tools you're already using.
36:15 So give them a pip install and see the difference right away.
36:17 Get started at talkpython.fm/YourBase.
36:21 The final thing is to set the target, which is a CSS selector.
36:27 So hash search results, which is the ID.
36:32 And you've got a table with the search results and that's it.
36:35 This is the, besides the server side that does the actual search response, this is the entire implementation of your dynamic search page, right?
36:43 Yeah, that's right.
36:44 So what is that?
36:45 It looks like four attributes.
36:47 You have four attributes to implement dynamic search or active search, I think is what Google terms it when you go to Google and start searching.
36:54 And this is a great example of something I think many web apps would benefit from.
36:59 And it can be achieved very quickly with just a small amount of HTMX on the front end and a small refactoring of the code you probably already have on the back end.
37:10 Yeah.
37:10 What I really like about this is if you've already implemented the search page to return a table of results, you've already written all this code.
37:17 Yep.
37:17 Everything is here.
37:19 Like you have a form.
37:20 You've submitted the form.
37:21 You've got a response.
37:22 You've rendered the table.
37:23 You probably show the form again.
37:24 Yeah.
37:25 Although those things are present, you just can turn it to a on key down, key up rather.
37:31 Yeah.
37:32 Basically make it much nicer without almost any effort.
37:36 Yeah, exactly.
37:36 And again, I think this is showing how HTMX is taking HTML as a hypermedia and pushing it forward, right?
37:43 This, you know, I think in an ideal world, this would just be part of HTML.
37:48 It's just taking this hypermedia concept and saying, let's go further with it because HTML is kind of stalled as a hypermedia and they aren't doing much with it.
37:57 So that's very much where HTMX is coming from.
38:00 And that's the philosophical underpinning of the library.
38:04 Yeah.
38:04 Super cool.
38:05 All right.
38:06 So one of the things I love about your examples, one, this whole library has a rich set of examples.
38:13 We'll go through two others.
38:15 Sure.
38:15 And, but one, the examples are there.
38:18 They're clear.
38:19 They're visual.
38:20 And you have a live one right embedded in the page.
38:23 I don't have to pull up like rebel or whatever to like go figure out, well, how's this really going to work?
38:28 I can just go here.
38:29 So if I want to see if there's a username, Michael, I just type, am I?
38:33 No, but there are, there's a username, Molly with M I in the domain.
38:39 And there's Jessamine, M I in her name and so on.
38:43 Right.
38:44 So that's amazing.
38:45 Yeah.
38:45 I've tried to focus on making things as visual as possible because I, you know, what I run into is people don't believe what you can accomplish with this library.
38:54 And so I really wanted to make it jump out and say, hey, you know, yeah, there's stuff you can do in Vue.js that would be tough to do in HTMX or react, you know, react or whatever you're using for your front end.
39:07 But nonetheless, there's a lot of stuff that would benefit a lot of web apps that can be done using this simpler model.
39:13 And if you're able to, you know, the question is, is, is it good enough?
39:17 And I think it is good enough for probably 90, 90, 90 plus percent of the websites that are out there.
39:22 I mean, it certainly would improve, you know, the vast majority of websites that were out there, just a little bit of HTMX.
39:29 Yeah.
39:29 It reminds me of what jQuery did for the web.
39:32 It doesn't remind me of jQuery, but jQuery for, I know probably a lot of people view jQuery negatively as like this sort of spaghetti code type of story these days.
39:42 But when it came out, it was like, oh my gosh, I can sprinkle in a few things and this becomes really amazing.
39:49 Yeah.
39:49 Right.
39:49 I get that feeling as well.
39:51 It's like easy to add to something that exists.
39:53 Yeah, that's right.
39:54 And, you know, this whole thing, we came, I came out of the jQuery world just like you did.
39:58 And so I think you're right that there's, with jQuery, there was always an incrementalist approach.
40:04 You could add things incrementally.
40:06 You didn't have to buy into a huge bit of infrastructure.
40:09 It turned into spaghetti code in the long run.
40:11 I agree with those criticisms of jQuery.
40:13 And so hopefully with HTMX, because of the way it's built, you're not going to run into those same issues.
40:19 I think there's some, conceptually there are reasons why that is.
40:22 So with HTMX, you tend to put the actions on the thing that does the action.
40:27 Whereas in jQuery, you would move things to a separate place.
40:31 It would be over in some job.
40:32 Right, like dollar document ready sort of thing.
40:34 They would be living somewhere else.
40:36 And that was kind of sold under this idea of separation of concerns, which is a design principle.
40:41 for software.
40:42 I've been trying to push this idea of locality of behavior, which is intention with separation of concerns.
40:49 And the idea of locality of behavior is that you want to put the things that a code unit does in the code unit.
40:56 So a button should say what it does.
40:58 It should say, I issue a post to this URL, and then I do this with the response.
41:03 And that's exactly what HTMX does.
41:05 And again, that's in contrast with jQuery, where you would hook up a click handler in some other place, and you would just be staring at this button wondering why it was doing what it was doing.
41:15 And so locality of behavior is what I'm trying to use as a terminology to describe this idea of putting stuff in line in the HTML to explain what this thing does.
41:25 And there are other tools that are doing this as well that are getting popular.
41:29 The two big ones are AlpineJS and Tailwind CSS.
41:34 Both of those, you put your stuff in the HTML.
41:36 And I think those two projects pair very well with HTMX in that you can kind of do everything right there in your HTML.
41:44 It can be a little overwhelming at first if you're not used to that style of programming, but it has a lot of benefits associated with it.
41:50 Yeah.
41:50 I've never, I haven't even heard of AlpineJS, so I'm going to definitely have to check that out.
41:54 But Tailwind I've heard of, and Tailwind's pretty interesting as well.
41:57 It's like sort of a replacement for Bootstrap, but not in the same sort of abstract style.
42:02 It's more like, say, like, you describe it as the way you want it to be.
42:06 Like, I want the font to be medium.
42:07 Yeah.
42:08 Rather than say this is the main text, and the main text is formatted medium-sized, right?
42:13 Yeah.
42:13 Exactly.
42:14 You inline things.
42:16 So when you're looking at a button, you can see why it has rounded curves or why it has the padding that it has and so forth.
42:24 I think people have started to recognize the separation of concerns, while certainly a good thing in some ways,
42:30 and, you know, a valid design principle has some disadvantages.
42:33 And the big one that I see is this sort of spooky action at a distance where someone can change a file somewhere else,
42:40 and suddenly your button doesn't work anymore or whatever.
42:44 Yeah.
42:44 Yeah.
42:44 Yeah.
42:44 I think, well, the separation in this scenario is hx-post is slash search.
42:51 Like, this describes exactly in the web sense of what a URI means to describe this is what I want this to be,
42:59 but it doesn't describe the implementation.
43:01 Right.
43:01 Right.
43:02 That lives in the server.
43:02 Yep.
43:03 And so I think there's an interesting philosophy there as well.
43:05 Yeah.
43:05 Yeah, there is.
43:06 And it's really that restful, uniform interface idea from the early web.
43:13 It's, you know, I keep saying this, but we're trying to take HTML and drive it forward as a hypertext.
43:19 Give you more power as a hypertext developer.
43:22 Yeah.
43:23 Super cool.
43:24 All right, let's take a few things from the live audience.
43:26 So we got Nick says, I love that this supplements server-side frameworks like Django rather than trying to replace parts of them.
43:32 Yeah.
43:33 Yeah, absolutely.
43:34 For sure.
43:34 Alec has an interesting fix for your monitor.
43:37 Okay.
43:37 Tudo app install new monitor.
43:39 Easy.
43:39 Yeah.
43:40 Since you're on Linux, right?
43:41 If I could get a terminal to show, I've got my laptop monitor over here.
43:44 I'm literally staring at a blank, at a black screen.
43:47 It flickers every once in a while, so I get a brief view.
43:50 Catch a quick view.
43:50 I'm not touching anything.
43:52 If it's recording.
43:53 It's all good.
43:54 It's working.
43:54 And then Nick also says, now we need an hx-python tag to run arbitrary Python in the browser.
44:00 Just kidding.
44:01 Don't do that.
44:02 With HTMX, I think that you've removed a lot of the pressure to have Python in the browser with HTMX.
44:08 And so I was optimistic, you know, all jokes aside, I was optimistic when WebAssembly was first proposed that it would break the dominance of JavaScript in the browser.
44:18 But my experience thus far, and I have to admit, I haven't looked at it in a while.
44:21 Is that WebAssembly has been so low-level that it's probably not going to help.
44:29 And maybe I can't tell if that was intentional or not.
44:31 Yeah.
44:32 But in my experience, there wasn't a good interop layer between the DOM and WebAssembly even.
44:39 And so, okay.
44:41 The vast majority of scripting I want to do is DOM related.
44:44 Yeah.
44:45 It's all about the DOM.
44:46 So let me give you my WebAssembly sidebar here.
44:49 And I'd love to hear your thoughts.
44:51 I hear two problems with WebAssembly.
44:53 One is this DOM story, right?
44:55 Like, this could be fixed, right?
44:57 WebAssembly could be evolved to have like a, like, and here's the DOM API.
45:01 Right.
45:02 In a real straightforward way.
45:03 I know there's a lot of separation and whatnot, but I cannot believe that it couldn't be figured out.
45:08 Yeah.
45:09 Two, the problem I hear about this is, well, you can have Python in the browser and things like PyIodide have actually done this to like compile the C into WebAssembly, the CPython runtime and the scientific libraries into a WebAssembly thing.
45:26 And then you can download it and you can do limited stuff.
45:28 It's limited because of the limitations of the DOM, but you can still run Python in your browser.
45:32 It just so happens it's a 10 meg download.
45:34 Yeah.
45:35 Right.
45:35 Here's what I would love to see.
45:36 I would love to see the major language providers, C++, Python, .NET.
45:41 You just go down the list, Java, Rails, provide a WebAssembly thing against some API and every major browser just builds that in.
45:51 So my Firefox comes with Python, Ruby, Java, and .NET.
45:56 These are all like 10 or 20 meg binaries.
45:58 Right.
45:59 The world would be like, then that whole problem of, well, do you download it?
46:03 What if you redownload?
46:04 What if it's out of, like, just they ship JavaScript.
46:06 Yeah.
46:06 If all they had to do is include a host of other features as WebAssembly, like, the problem would be solved.
46:12 But there's just a little too much friction along the way to make that happen, I think.
46:16 Yeah.
46:16 It really, the core problem there, I think, is the core libraries that, you know, that come with all these programming languages.
46:24 It's one reason why Rust actually does pretty well with WebAssembly.
46:27 It just doesn't come with very much.
46:29 Yeah.
46:29 And that's a reasonable solution.
46:31 If I was super passionate about Python, I might look at just writing an interpreted, and it sounds like there might already be an interpreted version of Python in the browser.
46:41 So, HyperScript, which is a scripting language that I'm working on as kind of a passion project that's loosely associated with HTMX, is a scripting language, and it works in the browser, and it's just interpreted.
46:52 And JavaScript is so fast in the browser now that you can actually get away with it.
46:57 So, as long as your Python wasn't, you know, trying to do scientific computing, you're just trying to do basic web scripting, you know, adding classes to DOM elements and so forth.
47:07 You want to do Vue.js stuff like stuff, but you don't want to write.
47:10 You want to create Python classes and then, like, hook Python functions.
47:14 Yeah.
47:15 Right?
47:15 Yeah.
47:15 That actually, you know, in my opinion, if I were going to take a look at that problem, I'd look at doing an interpreted language.
47:21 Yeah.
47:21 Interesting.
47:22 There is Sculpt, which is pretty interesting, and this runs Python in the browser.
47:27 So, like, the example on the homepage is like a little turtle on an HTML canvas.
47:31 Okay.
47:31 And this is all client-side.
47:33 But it's, it's like close.
47:36 It's not the same.
47:37 Right.
47:37 So, I mean, that's the same for all the languages.
47:40 Yeah.
47:40 All right.
47:40 Let's go back to this example here, because I think there's still a lot of really good things we haven't even touched on.
47:45 And we're, I mean, we're only on, what, four tags?
47:47 Yeah.
47:47 I know.
47:49 So, we talked about this little example here.
47:51 And as I'm typing, people can see the little searching.
47:54 They go and type.
47:55 They can see, like, in the H3, they can see the little searching bit.
47:58 Yep.
47:58 But all of these things, I think, are neat.
48:01 But you kind of wonder, well, what's happening?
48:02 Like, what's going on really?
48:04 Like, especially if this is a server-side thing, what's the HTTP traffic with the server?
48:10 And you added this little, like, built-in debuggery toolbar thing.
48:15 It's not a debugger toolbar.
48:16 It's a debugger footer.
48:17 Yeah.
48:18 A debug footer.
48:19 Yeah.
48:19 And as you interact with the examples, on every one of the examples, you can see, well, what is the initial traffic?
48:25 What is sent over?
48:27 And you click on it.
48:28 It has a history of all the requests that they made.
48:31 Yep.
48:31 What was posted over and then what was returned from the server.
48:34 Yep.
48:35 And it's super clear.
48:37 Yeah.
48:38 Like, you can go to the last one.
48:39 You can see exactly.
48:40 This is what's on this, you know, up at the top.
48:42 Yep.
48:42 And you look at the bottom.
48:43 Well, there's the TRTDs that make that happen.
48:45 Yeah.
48:45 Yeah.
48:46 Yeah.
48:46 Yeah.
48:46 I really wanted to focus on the examples to drive home just how easy it was.
48:50 And then also what you could accomplish with the library.
48:53 Yeah.
48:54 Quite cool.
48:56 All right.
48:56 Let's touch on a couple other examples.
48:58 I pulled them up because I wanted to highlight them.
49:00 Click to edit.
49:01 Okay.
49:01 Let's go look at click to edit.
49:02 That's a pretty good one.
49:03 Yep.
49:04 Again, I apologize.
49:06 I'm on my phone.
49:07 Yeah.
49:07 Yeah.
49:08 Yeah.
49:08 Yeah.
49:08 No worries.
49:08 So here what you've got is you've got a form and it's not form-like.
49:14 It's like just static text with divs and spans and whatnot.
49:18 So you've got first name is Joe, last name is Blow, email is such and such.
49:23 And if you hit click to edit, those things all become, well, the values become text inputs.
49:30 Yeah.
49:30 I could make Joey Joe and hit submit and in place, it becomes Joey.
49:35 That's right.
49:35 That effect.
49:36 This is a really cool example, right?
49:38 Like instead of having forms everywhere, you can just have HTML and like a grid.
49:42 And you could say, an example I would imagine maybe is a grid of responses.
49:47 And then you want to edit one of the lines of the grid.
49:50 Yep.
49:50 Like I want to edit this entry and then boom, those all become drop down flex or they become
49:55 date time pickers or whatever the heck you want to make them become.
49:58 And then they go back, right?
50:00 Yeah.
50:00 Like an editable row concept.
50:02 Yes, exactly.
50:03 Yep.
50:03 Yeah.
50:04 Yeah.
50:04 Super easy example of what's happening.
50:06 If you click edit, it returns the form HTML text.
50:09 When you submit it, it returns the div span version of it.
50:12 Beautiful.
50:13 Yeah, exactly.
50:14 So, you know, probably not going to the details of all the attributes that make this happen,
50:19 but there's an HX get to get the form.
50:22 That form gets swapped in to that little element.
50:25 You don't have a big page refresh.
50:27 You don't go to some other URL and then you can click save and it just does a put.
50:31 Put being the traditional way to update something or the standard way.
50:35 Know the URL and you want to make a change to it instead of a post you do a put because
50:39 that's restful.
50:39 Yeah.
50:40 Yeah, exactly.
50:40 And so you use an HX put and then when that put succeeds, you would render just the row again.
50:46 And if that put failed for validation reasons, for example, you would just render the form
50:51 with the error messages in it.
50:52 And this is very similar to the way you do standard, you know, web app development in the web 1.0
50:59 model, but you've managed to bring down your target to just this little form.
51:03 And so you don't have to do redirects and stuff like this anymore.
51:07 Interesting.
51:07 I hadn't really thought about the errors.
51:09 Yeah, I hadn't thought about the error response.
51:12 But for example, you could say return the form, but in your server side template, you could say,
51:18 well, this one has an error.
51:19 So what we're going to do is put an error message at the top and we're going to put an
51:23 error has error attribute onto the form element, which will make it glow red or something
51:27 like that.
51:28 Exactly.
51:28 And if you wanted, so one common thing to do is to, you have your error messages elsewhere,
51:34 right?
51:35 They're not down in that element.
51:36 I like inline error messages myself, but a lot of people like to show errors at the top.
51:41 And so HTML, HTMX, excuse me, has tools to do that.
51:44 You can use what's called an out of band response.
51:47 So you can have a content that is streamed down that specifies this is out of band content and
51:53 it needs to go somewhere else in the DOM.
51:55 Typically it uses an ID.
51:56 And so you could use that to put an error message, you know, up on the header if you
52:01 wanted to do that.
52:01 Yeah.
52:02 Another common way to do this one that I like, if you're going to have something like that
52:06 is to have some sort of growl library where it kind of.
52:09 Like a toast notification pop-up type of thing.
52:12 Exactly.
52:13 Something like that.
52:14 And so for that, what you might use is the HTMX has some fairly well-developed response
52:19 headers and one of them is HX trigger.
52:21 And you can use that to trigger an event with an argument.
52:24 The argument in this case would be the error message to show.
52:28 And then you can write a little bit of code on the front end to listen for that custom event
52:33 that you're triggering and then show toast message saying, hey, it's saved.
52:38 Oh, that's cool.
52:38 So there's a bunch of different tools in there depending on what you're trying to accomplish.
52:42 Yeah.
52:43 All right.
52:44 Out in the live stream, Apar says, hey from San Francisco.
52:47 Hey, welcome to the live stream.
52:49 Nick comment.
52:50 I'm curious how this compares to two-way binding with something like Vue.
52:54 Is the DOM reactive with an underlying data model so that they stay in sync?
52:58 The answer is no.
52:59 So HTMX adopts the original model of the web, this RESTful model where hyper, you may have
53:07 heard at some point in your programming career, the acronym HADEOUS.
53:11 It's a bad acronym, particularly these days.
53:13 But the acronym stands for hypermedia or hypertext as the engine of application state.
53:19 And so there is no backing model on the client side.
53:22 Rather, the model, the source of truth is the back end and the front end just sits there
53:28 and reacts to user inputs.
53:31 And whenever a user input occurs that needs to trigger a state change, a request is issued
53:36 to the server and then the updated state of that resource is returned via HTML.
53:41 Yeah.
53:42 And it kind of flows through this interaction.
53:44 That's right.
53:45 Right.
53:45 So let me give you an example.
53:46 So in this click to edit thing, when I click edit on the button, it knows it's on slash
53:51 context, contact slash one.
53:53 And I click the edit.
53:54 What comes back is a form and has HX dash put with slash contact slash one as the action.
54:01 Right.
54:02 So then when I submit it, it flows that it was row one or item one I was editing on over.
54:07 And then when it comes back, the response is, well, now it has the contact slash one slash
54:14 edit in that URL.
54:15 So it kind of flows.
54:16 Yeah.
54:17 This is actually super hideous.
54:18 There's many things that you find in these APIs and people adopting REST.
54:23 They're like, oh, we're going to take all the REST principles except for this hypermedia
54:26 as application state.
54:27 That we don't really care about.
54:28 But this, the more you talk about it, it really is.
54:31 Yeah.
54:31 Well, it is.
54:32 It's because people, this is a long conversation, but holy smokes, I've been arguing with people
54:36 on the internet about this for a while.
54:38 I don't think REST makes any sense when you talk about JSON because it does to some extent.
54:44 The HTTP verbs make sense.
54:45 Yeah, they do.
54:46 That's about it.
54:47 Other than that, right?
54:48 There's a lot more to this whole REST.
54:50 Maybe the representation, maybe the URL layout in some cases makes sense.
54:54 Yeah.
54:54 But when Fielding wrote his, Roy Fielding is where the term, his dissertation at University
55:00 of California, Irvine is where all this terminology comes out of.
55:04 And what he wrote, he was describing the web.
55:07 He was describing HTML.
55:08 He was describing the way Web 1.0 worked with that.
55:13 And a big focus on that was this idea of stateless HTML and hypertext as the engine of application
55:19 state.
55:20 That being one of the crux issues within the section that's about what's called the uniform
55:26 interface.
55:26 We don't want you to get too much into the details of that right now.
55:29 I'd be happy to talk about that maybe offline later, maybe in a different context.
55:35 But when you're in JSON, hypertext isn't the engine of application state.
55:40 There's a client-side model that is your application state.
55:43 And now you're in a stateful world.
55:45 And you're in some ways much closer to what thick apps used to look like back in the 90s
55:50 than you are to the original web model.
55:52 It's a different model and there are advantages and disadvantages to it.
55:56 I like it a lot.
55:57 I think there's a lot of power to it.
55:58 And so, you know, to make a long story short, no, there's no reactive aspect here.
56:04 The DOM is the source of truth.
56:06 The server is really the source of truth.
56:08 But the DOM, as far as the user is aware, is the source of truth.
56:11 And it's stateless, just like the original web model.
56:14 Right.
56:14 The view model is super nice.
56:16 I mean, you create these little JavaScript classes and they just kind of build up their
56:19 data.
56:20 And it's really cool.
56:21 And it binds with the DOM.
56:22 But like, what if someone refreshes the page?
56:24 Right.
56:25 Or something like that, right?
56:26 Yeah.
56:26 Oh my gosh.
56:27 It's a God.
56:28 Oh no.
56:29 Right.
56:29 So yeah, there could be drawbacks as well.
56:31 Reactivity is, you know, sometimes I can be a little too hard, I think, on just the nature
56:37 of the internet.
56:38 But, you know, reactivity, this notion of a reactive two-way binding, that's new.
56:43 It's relatively new.
56:45 There were UI toolkits that did something, did similar stuff, but not as deeply as the current
56:50 set do.
56:51 And so there's something new there and it is useful in a lot of ways.
56:55 But for a lot of apps, it's overkill and there are disadvantages that are associated
57:00 with it.
57:00 Sinking the two models is difficult.
57:02 And if you let your DOM be the source of truth, the server be the source of truth and your
57:08 DOM be a stateless representation of it, then there's a huge number of advantages that come
57:12 along with that.
57:13 Yeah, that's for sure.
57:14 Like if you have the same page open on multiple tabs, for example, like the database is still
57:19 in sync on the server.
57:19 Yeah.
57:20 All right.
57:20 Let's look at one more example.
57:21 Sure.
57:21 And we'll do a little bit of wrap up.
57:24 I'm a little hesitant to show this to people because I kind of hate this, but it's also
57:27 a very neat infinite scroll.
57:30 Infinite scroll can also be implemented as click to load.
57:33 So I too am ambivalent towards this pattern, but it's so common.
57:39 What I don't like about it is it's super hard to share it with somebody.
57:44 They say, okay, go to this part of the search result.
57:46 Like, well, where is it?
57:48 Like, well, keep scrolling down.
57:49 No, like hold down the page.
57:51 You know what I mean?
57:52 It's just like hard to share or to get back to you.
57:54 Anyway, it's a lot.
57:55 I don't know.
57:56 But infinite scroll is neat.
57:57 And so here you've got a table row that says hx-get slash context slash page equals to
58:04 our question mark page equals to is a query string.
58:07 And then hx trigger is revealed.
58:09 This is like as you scroll down, when it becomes revealed within the DOM, run this.
58:14 And then swap after end.
58:16 Yeah.
58:17 I guess.
58:17 What's that mean?
58:18 After end.
58:19 So what that means is so you would put this code on the last row, the last result of your
58:25 page of results.
58:26 And so what that's going to do is it's going to issue a request to the server.
58:31 And then when it gets that content back, it's going to append it after the end of this element,
58:36 the element that this is on this table row.
58:38 And so that new content, which is presumably going to be a new series of rows, is going to
58:44 get appended after the last row.
58:47 And so that's how you get that next set of rows.
58:50 And then on the last row of that, there would be, again, this when I'm revealed.
58:55 The response will come back with an hx-get on it, right?
58:58 Yeah.
58:58 So it'll come back with the hx on it, and it'll just keep going down the line until finally you
59:03 get to a point where you don't have any more.
59:04 And so you don't bother encoding one of these revealed triggers.
59:09 And that would just be the end of it.
59:11 So I agree with you.
59:12 As you are, I am ambivalent towards this.
59:16 I tend to prefer paging for exactly the reasons you talk about.
59:19 And I should note that there is an attribute called hxpush.
59:23 Is it hx?
59:25 hxpush URL, excuse me, that will push the URL of the request up into the browser's history,
59:33 like into the URL.
59:34 Okay.
59:35 And add it to the history.
59:37 So you can use the back button and all that.
59:39 And it does all that kind of automagically for you.
59:42 Does it allow deep linking?
59:43 Yeah, yeah.
59:45 Now, that being said, if that URL, you know, someone can copy and paste into a new
59:49 tab, for example.
59:50 And so you have to handle both the HTMX request to that URL, as well as the normal non-HTMX
59:58 request to that URL.
59:59 And those might be very different.
01:00:00 Yeah.
01:00:00 But if you did that, then it would support potentially deep linking into this sort of experience.
01:00:06 Exactly.
01:00:06 And so, and then I just finished that thought.
01:00:09 There's a header that comes in when it's an HTMX request, hx requests true.
01:00:15 And so you can check that header and say, okay, this wasn't an HTMX request.
01:00:20 So I need to render the entire surrounding for this thing.
01:00:23 Or, oh, it was an HTMX request.
01:00:25 So I just need to render this partial.
01:00:27 And that's a very common pattern to have a little if statement on a URL that needs to service both
01:00:32 of these to check the header value.
01:00:33 Oh, that's pretty cool.
01:00:34 Yeah.
01:00:34 Nice.
01:00:35 Okay.
01:00:35 So let's see.
01:00:37 Let me, I'm going to do it.
01:00:38 I'm going to scroll here.
01:00:39 Yeah.
01:00:39 Here we go.
01:00:39 There you go.
01:00:40 See the indicator and down comes some more.
01:00:42 Yeah.
01:00:42 Oh, fantastic.
01:00:43 Yeah.
01:00:43 Yeah.
01:00:44 There we go.
01:00:44 And you can obviously, you know, pull up the little debug butter.
01:00:47 Yeah.
01:00:48 And see those behaviors here, which is great.
01:00:51 Yeah.
01:00:51 And again, the backend agnostic.
01:00:52 So just, this could just be normal Python on the backend.
01:00:55 Nothing fancy.
01:00:56 Yeah.
01:00:56 Django, Flask, or Rails.
01:00:58 Take your pick.
01:00:58 Yep.
01:00:59 Whatever you like.
01:01:00 I mean, it could, I've been bagging on Node because I'm not a huge fan of it as a platform that I want
01:01:05 to work on, but it could also be Node, right?
01:01:07 Sure.
01:01:07 Like if people are out there doing that, it could be.
01:01:09 Yeah.
01:01:09 Hypertext on whatever you'd like.
01:01:11 Howl.
01:01:12 Howl.
01:01:13 Yeah.
01:01:14 All right.
01:01:14 So let me wrap this up with a little bit of concreteness here.
01:01:17 Sure.
01:01:17 So tell us really quickly about, there was Intercooler and now it's HTMX.
01:01:23 Just real quickly.
01:01:23 What is the story with this transition?
01:01:25 Yeah.
01:01:26 So I created Intercooler, which is the predecessor to HTMX.
01:01:29 HTMX is basically Intercooler 2.0.
01:01:31 And then I created Intercooler back in 2013, I believe.
01:01:35 And it was, again, I came out of the jQuery world.
01:01:38 And so it started off basically as a jQuery plugin.
01:01:41 And it grew to the point that I felt like, okay, I'm going to create a separate library
01:01:45 for this.
01:01:46 And last year when COVID hit, it had always had in the back of my mind that I didn't like
01:01:51 the jQuery dependency in Intercooler.
01:01:53 And so I just, you know, everyone was kind of at home.
01:01:57 And in order to avoid losing my mind, I said, well, I wonder if I could pull the jQuery
01:02:05 dependency out Intercooler.
01:02:07 And it turned out JavaScript's come a long way.
01:02:10 And I was able to do it pretty quickly.
01:02:12 And so as I was doing that, one other thing that I thought about, I really, you know, I
01:02:17 learned a lot as I built Intercooler.js.
01:02:19 And I developed a much firmer sort of theoretical basis for it.
01:02:23 It's like, okay, we're really, we're trying to drive HTML forward.
01:02:26 And one thing that had always annoyed me about Intercooler.js was that it was compared with,
01:02:32 you know, Angular was the big one when it was first out.
01:02:36 And then eventually React and then, and Vue.js.
01:02:39 And because it had that JS in the name.
01:02:41 And so there was, people would treat it as a JavaScript library rather than thinking of
01:02:46 it in these more hypertext oriented terms.
01:02:49 And I was astounded to find out that HTMX org was available in 2020.
01:02:54 And, but it was.
01:02:56 And so I grabbed it and I was like, this is a great name.
01:02:58 I originally called it something else, but came to my senses and said, you know, HTMX really
01:03:02 captures this.
01:03:03 We're trying to extend HTML.
01:03:05 So HTMX.
01:03:06 It's short.
01:03:07 It's available as a domain name and it captures what you're after.
01:03:10 Yeah.
01:03:11 Yeah.
01:03:11 So it worked out very well.
01:03:13 So I'm very happy with it.
01:03:14 Let me round out our conversation with a concrete example here for this.
01:03:18 So people might wonder like, where is this being used out in the world?
01:03:21 Right.
01:03:21 And I'm obviously, I think it makes a ton of sense, especially in these little like backend
01:03:26 internal corporate apps that don't get a ton of love, but could really benefit from this.
01:03:30 But there's also some popular ones like realpython.com out there is one of the most
01:03:35 popular ones, Python websites out there run by my good friend, Dan Bader.
01:03:40 Cool.
01:03:40 And I was just talking to Dan saying, I'm going to talk to you, Carson.
01:03:43 He's like, oh, I love this.
01:03:44 I actually use intercooler on the site.
01:03:46 Okay, cool.
01:03:46 So if you go over to the quizzes section, you can pull up one of these quizzes and you
01:03:51 hit start.
01:03:52 These sort of like test your knowledge things.
01:03:53 So here it says like, for example, in Python three, the maximum value for an integer is
01:03:57 two to the 63rd minus one.
01:03:58 Oh, that's so false.
01:03:59 And you click on it, it like reveals the check answer of the thing.
01:04:04 And then you go to the next question or you can expand the explanation.
01:04:08 How would you express a five, the base 16 integer?
01:04:12 I have no idea.
01:04:12 All right.
01:04:13 Not the point.
01:04:14 Not the point.
01:04:15 But this thing, this experience of going through these, these steps with the progress bar, because
01:04:20 there's a cool progress bar in HTMX and all that stuff.
01:04:23 Yeah.
01:04:24 Like this is a cool use case of that type of situation.
01:04:27 That's really nice and easy to do.
01:04:29 Yeah.
01:04:29 And there's a huge amount of code that's written out there, even in apps that are more dramatic
01:04:33 and need, need this reactive infrastructure in places, there are probably places within the
01:04:39 app where that's not necessary.
01:04:40 So, you know, one common thing I'll say is, okay, maybe HTMX doesn't apply to your entire
01:04:45 app.
01:04:45 Maybe you're doing concurrent editing of rich, you know, using canvas or something crazy like
01:04:51 that.
01:04:51 All right, fine.
01:04:52 But you probably have a settings page for that app.
01:04:55 And that settings page is going to be fairly standard forms.
01:04:59 And that's something where maybe rather than using whatever reactive component you're using
01:05:04 to manage the really complicated state, you could tear all that out, save that complexity
01:05:09 budget and just use HTMX just to sync with the server for your, for your settings page,
01:05:14 you know, but that even, you know, how many react, how many crazy apps do we use day to day?
01:05:18 For the most part I use, you know, I go and I read blog posts, maybe I, I check my email
01:05:24 and so forth.
01:05:24 And a lot of those apps could be improved pretty dramatically by just using some basic
01:05:29 HTMX patterns without adding a huge amount of complexity.
01:05:32 Yeah, I totally agree.
01:05:33 Totally agree.
01:05:34 All right, Carson, I think we're pretty much out of time.
01:05:37 Okay.
01:05:37 But let me always ask two questions at the end of the show.
01:05:42 Sure.
01:05:42 Two questions.
01:05:42 So I'll hit with them before we close it out.
01:05:45 If you're going to work on HTMX or do some other programming, what editor do you use these
01:05:49 days?
01:05:50 I use WebStorm.
01:05:51 WebStorm, right on.
01:05:53 Yeah, I'm JetBrains.
01:05:55 Yeah, go ahead.
01:05:55 I'm a JetBrains guy.
01:05:56 Yeah, same here.
01:05:57 I'm a big fan of PyCharm and basically the web side of its functionality is just WebStorm
01:06:01 as well, which is very cool.
01:06:03 It's super nice.
01:06:03 I encourage people to pay for their tools.
01:06:06 If you're a programmer, spend some money.
01:06:09 I mean, they have stuff for free, but they, they do tremendous work.
01:06:12 I know that what's the Microsoft editor has become very popular.
01:06:16 VS Code.
01:06:17 Yeah.
01:06:17 Yeah.
01:06:17 But I don't know.
01:06:18 It is what it is.
01:06:20 You know, it's a holy war situation.
01:06:21 So don't take me too seriously on this.
01:06:24 But if you're willing to listen to me, if you're willing to listen to a random guy on
01:06:28 the internet to at least take a look at the JetBrains stuff.
01:06:32 I like your idea of, you know, support and encourage the things that you want to see
01:06:36 more of.
01:06:37 Right.
01:06:37 For sure.
01:06:38 And then normally I ask for like a Python library that people are really interested in.
01:06:42 But in this, this case, let's, how about a JavaScript library or CSS library or something
01:06:46 like that, that you think people should really check out like something on NPM or tailwind
01:06:51 or whatever.
01:06:52 Yeah.
01:06:52 I like, I think looking at tailwinds and looking at Alpine JS, if I may, we didn't really get
01:06:57 a chance to talk about it, but Hyperscript is a scripting language.
01:07:01 It's kind of a natural language, scripting language for the front end, very front end
01:07:05 focused.
01:07:05 That's kind of got some interesting aspects to it.
01:07:08 But I think, you know, rather than recommending one particular library, I'd say just that this
01:07:14 idea of locality of behavior, looking for libraries where you're putting the code in the code unit
01:07:20 rather than having a bunch of different places.
01:07:22 And so tailwinds and Alpine JS are two that jump out at me in addition to HTMX as being worth
01:07:27 taking a look at.
01:07:28 I know there's a lot of Django people that are using that combination and are very passionate
01:07:32 about it.
01:07:33 Yeah.
01:07:33 Fantastic.
01:07:34 Yeah.
01:07:34 I know some people certainly passionate about it as well.
01:07:36 Nick out of the live stream says, view single file components, violate the separation concerns
01:07:41 and lead towards this locality that you talk about as well.
01:07:44 Yeah.
01:07:44 It's a great improvement.
01:07:45 Yeah.
01:07:45 I think front end components are kind of moved that way as well.
01:07:48 That's exactly right.
01:07:49 Now, you know, do I, that's, that comes with a lot of other stuff that I don't think is necessary
01:07:54 for a lot of web apps, but there's just this move, I think.
01:07:57 And so I'm trying to use again, locality of behavior.
01:07:59 And I've got an essay up on htmx.org slash talk.
01:08:04 You can look, there's a locality of behavior essay where I'm trying to push that term and
01:08:08 get people to adopt it when they're trying to explain to people why, Hey, why are you
01:08:11 inlining all this code?
01:08:13 Cause you know, they're like, Oh, this is the worst idea.
01:08:15 No, you can't.
01:08:17 And it's like, well, you can.
01:08:18 And most people and people are actually having experiencing productivity and maintenance
01:08:23 increase, you know, increases when they do it.
01:08:26 So.
01:08:26 Yeah.
01:08:27 I like your idea of the spooky action at a distance.
01:08:29 Right.
01:08:30 A little quantum mechanics in there.
01:08:31 Yep.
01:08:32 Cool.
01:08:33 All right.
01:08:34 Final call to action.
01:08:35 People are psyched about htmx.
01:08:37 Maybe they're psyched about not doing too much JavaScript on the front end.
01:08:41 What do you tell them?
01:08:41 Well, check out htmx.org.
01:08:44 Please start the GitHub repository.
01:08:45 That is my primary source of compensation for, for htmx at this point.
01:08:51 And, you know, we have a discord server that you can jump on as well.
01:08:55 If you have questions, Twitter is getting more active.
01:08:57 If you follow htmx, there's htmx.org on Twitter, which I run and it's getting more and more active,
01:09:05 but the discord is friendly at this point.
01:09:07 And, so I encourage people who are interested in this to jump on there and ask questions.
01:09:11 There's a lot of people that understand the library very well and, know a lot of different backends because htmx is backend agnostic.
01:09:19 Kind of each backend needs its own sort of expert to help out with it.
01:09:24 And so, you know, hopefully in a few years, we built up a good set of example libraries,
01:09:28 but at this point, if that's not available, then the discord is probably the best place to check out.
01:09:34 Okay.
01:09:34 Fantastic.
01:09:35 Well, thanks again for being here and thanks for creating this.
01:09:38 A lot of nice comments in the live stream as well saying, thanks for creating it.
01:09:42 So yeah, I think you're onto something here and I'm happy to share with people.
01:09:45 Hopefully it can superpower some of these Django flask, et cetera, apps without replacing them.
01:09:50 Yeah, I really, and I appreciate again, you, you know, taking something that's obviously outside the,
01:09:55 the normal Python world and, giving me a chance to talk to people about it because I do think it will
01:10:00 help people stay in Python longer before they, they feel like they have to abandon it for JavaScript.
01:10:07 Yeah.
01:10:07 We can remove some JavaScript guilt.
01:10:09 Yep.
01:10:09 Exactly.
01:10:10 Not doing the front and front.
01:10:11 That's right.
01:10:11 It's okay.
01:10:12 Awesome.
01:10:12 It's okay.
01:10:13 You don't have to use JavaScript for everything.
01:10:15 It's true.
01:10:17 All right.
01:10:17 Thanks again.
01:10:18 See you later.
01:10:19 Have a good one.
01:10:19 Bye-bye.
01:10:20 Bye.
01:10:20 This has been another episode of talk Python to me.
01:10:24 Our guest on this episode was Carson from big sky software, and it's been brought to you by
01:10:28 Sentry, your base and assembly AI.
01:10:31 Take some stress out of your life.
01:10:33 Get notified immediately about errors in your web applications with Sentry.
01:10:37 Just visit hawkpython.fm slash Sentry and get started for free and use the promo code
01:10:42 hawkpython2021.
01:10:44 When you sign up, your base test acceleration will dramatically improve dev test workflows and
01:10:51 CI builds of your Python applications.
01:10:53 If you could benefit from having pytest run your tests a hundred times faster or more, you
01:10:57 need to check them out.
01:10:58 Get started at talkpython.fm/your base.
01:11:01 Transcripts for this and all of our episodes are brought to you by assembly AI.
01:11:06 Do you need a great automatic speech to text API?
01:11:09 Get human level accuracy in just a few lines of code.
01:11:11 Visit talkpython.fm/assembly AI.
01:11:14 Want to level up your Python?
01:11:16 We have one of the largest catalogs of Python video courses over at talk Python.
01:11:20 Our content ranges from true beginners to deeply advanced topics like memory and async.
01:11:25 And best of all, there's not a subscription in sight.
01:11:28 Check it out for yourself at training.talkpython.fm.
01:11:31 Be sure to subscribe to the show.
01:11:32 Open your favorite podcast app and search for Python.
01:11:35 We should be right at the top.
01:11:37 You can also find the iTunes feed at /itunes, the Google Play feed at /play, and the
01:11:42 direct RSS feed at /rss on talkpython.fm.
01:11:47 We're live streaming most of our recordings these days.
01:11:49 If you want to be part of the show and have your comments featured on the air, be sure to
01:11:53 subscribe to our YouTube channel at talkpython.fm/youtube.
01:11:57 This is your host, Michael Kennedy.
01:11:59 Thanks so much for listening.
01:12:00 I really appreciate it.
01:12:02 Now get out there and write some Python code.
01:12:03 I'll see you next time.