Brian: PodRocket is sponsored by LogRocket, a frontend monitoring, and product analytics solution, which is to say it's not really sponsored by anyone. It's sponsored by us, LogRocket and we're giving it away for free. The podcast is free. The product is not free. There's a free trial. We could split hairs about whether or not that's free to you, but anyway, that's it. There are no more ads. If you're interested and you want us to know that you came from the podcast, please go to logrocket.com/podrocket. If you don't care, logrocket.com works just fine. Thanks. Brian: On today's episode, Ben and Kate, talk to Caleb Porzio about Alpine.js, Where it fits in the space, and what to expect in 2021. Finally, digging into some of Caleb's other creations like Laravel Livewire and makevscodeawesome.com. Let's get started. Kate: So, hey, Caleb. How's it going? Caleb Porzio: Great. How about yourself? Kate: Doing well, Thanks for joining us today. Caleb Porzio: Thanks for having me. Kate: Just to start off, tell us a little bit about Alpine. Caleb Porzio: Oh, what can I say about Alpine? It's a small, minimal, simple frontend framework. It's a framework built for my needs as somebody who wants a little more than jQuery, a little bit less than React. Kate: Yeah. So I was doing some research and it is interesting because it has all these competitors and all these inspirations and stuff. And it's a competitor of Stimulus, maybe a little bit of Vue. It's been compared to jQuery. I guess kind of talk about where it fits in the space. Caleb Porzio: Yeah. Where does it fit? I mean, the pitch would be closest to Stimulus. Maybe I'll give you a little bit about where it came from and that's probably the answer of where it fits. So I started making backend PHP web apps a while ago. Came in at CodeIgniter and then Laravel and just sprinkling JavaScript around my frontends with jQuery when I needed it. And then at some point I got into Vue.js and started basically making SPAs with full backends and full frontends for years. And just started to feel the weight of the maintenance costs really of just going whole hog on JavaScript, basically writing so many things twice and managing to stay in two different places. And there's just so much to manage that really simple things became really difficult like uploading a file or anything like that. It just got kind of crazy. Caleb Porzio: So I started to long for those early days of simplicity, where as a single full stack developer, I could create quite a bit in a short amount of time. And I felt like I lost some of that. So anyway, so I'd begun this journey to find something a little bit more minimalistic. I started just using Vanilla JavaScript, kind of going on a JavaScript diet, but there is some benefit to JavaScript frameworks. And I thought Stimulus is for me when I read the front page of Stimulus. I'm like this, I love the Basecamp guys, I love DHH, I love everything they do. And so reading that page, I'm like, that's the framework that I want because he shares the same philosophy, but using it, it just didn't cut it for me. I think because I had been tainted by Vue, by Vue's templating system and everything. I had been tainted by templates that react to data changes. Just that declarative style of writing your templates that to me is so crucial. Caleb Porzio: And with something like Stimulus, I felt like I still had to write a lot of imperative code like jQuery. I had to do a lot of grab this thing, change this thing, listen for this event, then do this. And I really want the declarative nature of Vue where I can say the text of this thing is this piece of data. And then just worry about changing that piece of data and the template will update. So anyway, so I had just started really just writing down with a pen and pad, the perfect JavaScript framework. And I sort of landed on this hilarious, like, wait, I think I just want Vue just with half the stuff and I want to be able to just use it like I use Tailwind like right in the markup. I don't want to necessarily have to separate the markup from the behavior. So that's how Alpine was born, yeah. Kate: Yeah. That's awesome. No, that's great. So looking on Twitter, even you tweeted like, I love Alpine. And it does feel to me where even Vue is a little too heavy handed, we see it in our blog posts all the time, this versus this thing. There really is no competitor like apples to apples. And I do like to throw in the competition questions, but it just depends on what you need. Caleb Porzio: I'm a lover of Vue. I love React. I love a lot of the projects. I guess this is just the one that fits best for me. And it's more my style, but I really admire most of those projects that you mentioned and go through their source and worship their developers and all that stuff. I guess it is a competition in the sense that I don't like when people say it's not a competition because if you use Alpine, you're not using Stimulus. You know what I mean? So in that sense, it's not like we can all just hang out in the same... And everything's whatever, but I don't feel in competition in the sense that I'm trying to rob from their market share. So anything like that. You know what I mean? Kate: Yes. Caleb Porzio: At least in spirit. Ben: One of the things I'm curious about is the big distinction between frameworks like React, where you're writing JSX in your JavaScript files versus Vue. And it seems like Alpine, where you mentioned it's in the markup and so you're basically writing HTML, but then writing your JavaScript in the HTML markup. It seems like your opinion is that you prefer the latter, but I'm curious like, what do you see as the trade-offs, the pros and cons of each approach? Caleb Porzio: Yeah, definitely trade-offs. So I guess I'll say when I was using Vue, so I guess the way that I used Vue mostly, and I think this is probably pretty idiomatic is, you reference methods and data inside your template and you don't do much else inside of it like inside of let's say a v-text, I don't know. Like v-on or any of those directives in your Vue template, you can write full JavaScript expressions. You could bind a class name using a JavaScript expression, but one, it feels like going against the grain. Also, you can't access the window object. So you can't do lots of things like, I don't know, if you want to even just do a set timeout, you can't do that stuff right inside those expressions. So they feel pretty hand holdy. Caleb Porzio: So I wanted to create something that you're more free to do anything you want directly in the expressions because I started doing stuff like, okay, let's say that I have a piece of data called show and I want to have a button where I toggle show and I toggle a div or something based on that, like a dropdown. In Vue, I could create a method called show, a method called hide a method called toggle. I could create a variable called show and a computer property called hidden or something, where I would much rather just in the template, say at a V... I have to remember my Vue, v if show or if I want it to like hide it v if ! show or if I want to toggle it, show equals not show. So you can do that stuff in Vue and I started to do that and I was like, wait, this feels really good to me. Caleb Porzio: And so Alpine takes that further. So that's at least partially an answer that my philosophy with Alpine has been push more behavior into the markup because that's where it lives. That's where you reference it. So it's kind of the same thing as Tailwind. The same benefits that I found moving from something like Bootstrap to Tailwind, I feel moving from something like Vue, where you have separate properties, methods, all that stuff in a separate JavaScript, at least section, moving it right in the markup. And then the story for reuse being other abstractions like backend includes or something like that. Kate: Yeah, so Caleb, I guess that's a good segue like the rise of HTML centric tools and we've talked a lot on this podcast about everything old is new again, where either holding responsibility always shifts. Maybe speak to that a little bit kind of just as the tool has grown. Caleb Porzio: So I guess the thing I said before, and I'll probably keep saying, a lot of the move from CSS, things like Bootstrap component frameworks or even CSS methodologies like BEM or object-oriented CSS, stuff like that, the move away from that and into utilities like tachyons, Tailwind, whatever, kind of represents a lot of the same motives for moving away from something like, I'll just pick on jQuery right now because it's the... Yeah, I don't know, I'm just going to pick on it. From something like jQuery to something like Alpine, where jQuery, you might have an ID on an element and that's the only reference to that element. Then you have your jQuery somewhere else where you get element by ID or something. And there's a lot to be gained by co-locating HTML behavior with HTML. So I guess in all of those ways, that's the evolution that has happened in my own life and Alpine is a part of that evolution, but also even take it a step further and say that a lot of these tools like React and Vue, they use virtual DOMs and they create a layer of abstraction around the actual raw bare metal DOM. Caleb Porzio: And I wanted something that didn't do that, that didn't feel like that. And so Stimulus is very much like that. And that's a core philosophy I share with Stimulus is that the DOM is actually way better now. There're so many APIs that have come up that make our lives much easier than they were before, so things like DOM classList and dataset. Things like that, that just make things a lot nicer. But also, it's not like manipulating the DOM is slow, it's because at the end of the day, those big libraries that use virtual DOMs, they end up boiling down changes into a set of DOM changes. Caleb Porzio: They're still manipulating the DOM, but they're doing a lot of work on top of it. That's kind of a more insider's view. And I would love to go more into the technical underpinnings of Alpine, but I'll say from like an outsider's perspective, when you're using it. When you're using something like Vue, when you want to work with real DOM, like if you want to pull in like a pickadate library or Select2 or some sort of little library that uses the actual DOM, you feel like you have to subvert the system of componentry and virtual DOM nodes and you have to use refs and you have to ignore parts of the tree that, whatever. So I wanted a framework that was more rugged than that, that was more close to the metal. So I use MutationObserver so I can deal with other things changing the DOM. It won't break my fragile structure of virtual DOM that only I can manage. And it's a lot more performance because of that in the same way that Svelte is more performing. It's just like Svelte in that way. Kate: So another tool that we can compare to. Caleb Porzio: It's actually a lot like Svelte in a lot of ways under the hood. Ben: What were the downsides of that approach? Like one nice aspect of not necessarily the virtual DOM, but working with JSX is for folks who like JavaScript and would like to write their JavaScript in a functional way, you don't have to learn DSL. You can just use JavaScript that you know. And when you start to have complex logic for displaying and not displaying components or for rendering lists or things like that, there's one school of thought that that's easier to do just writing JavaScript in JSX though there's obviously downsides to that as well. But I guess, are there other downsides that I'm not considering to the approach you use in Alpine? Caleb Porzio: Sure. Yeah. That's a great question. So in React with JSX, it's just JavaScript thing. I think that's rad and I love seeing JSX as a templating engine where like in Vue if you want to do something you look up the directive for it. If you want to look for something it's V4, were in React there's this feeling of like, oh, I'm just using JavaScript. I can just dot map, which I think is really cool. So in that sense, yeah, that's great. And I also think I'm more just steelmanning the argument, pumping up the other side. One of the things I love about virtual DOM is you can have these ephemeral renderless components because the component abstraction is not DOM based. So you can create so many different abstractions. There're so many cool things you can do with a system like that, that I think is really cool. Caleb Porzio: And in Vue, you can do that stuff too. You could use JSX in Vue. There's still like an h method or whatever, render component. It's the same building up the same tree. So you could use JSX in Vue, the templating engine is just kind of gravy on top of that. So anyway, so the pros of an Alpine approach are that, well, one, like I had mentioned, it's close to the DOM. And so you get all the benefit of being right in the DOM. You can listen to native events in the browser. You're not listening for event abstractions. You can use the browser's event bubbling system. But I guess the best answer is actually that you use Alpine differently than those frameworks. Like Alpine is not responsible for my apps templates entirely. I'm still using it in a backend context. Caleb Porzio: So I think the sweet spot for Alpine is not to build out a full SPA at all, it's going to fall on its face compared to something like React or Vue. It's for people, if you're building a Rails app, an Express app, a Laravel app, a Django app, you're going to love Alpine because you love your backend templating engine and you get to sprinkle in behavior and it works really well. And also if you're working in static sites, that's the other place that Alpine really shines. It's like marketing pages, documentation sites, all that stuff. That's the fit. So it's a tool for a specific context. Ben: That makes sense. And is there a story for server-side rendering with Alpine because like marketing sites or documentation or things like that is kind of a core use case for when you might want to do some server-side rendering to speed up performance or improve SEO or things like that. Caleb Porzio: Sure. So I'm working on the Alpine dock site right now. So this is kind of a meta answer. It's a Laravel based app, so the site, all the templates are generated on the backend. So it's all SEO, it's all server generated in like the old school way, where templates are generated on the server in a backend language I'm working on right now. As you scroll, I want the sub navigation items that are in the Vue port to highlight. Just live scrolling and that's something where Alpine's perfect. I can just sprinkle Alpine in, listen for scroll events and highlight the proper headings. So I think that really is the best answer that I can give you. As far as server generated in Alpine templating, that's not really a concept, but you can prepare your markup to be ready on first pain, like on the backend. Caleb Porzio: So let's say if there's something that you want to toggle in Alpine solely, but from the backend it comes shown and you might get that little jink, that little blip that for a second it shows and then Alpine kicks in and hides it until you reshow it. So I guess there's a few different stories for that one. You could use x-cloak, same thing as v-cloak. You could just disable that section of the page until JavaScript loads. But that's what SSR is supposed to answer is that problem of like, why don't you have that stuff all ready to go and then hydrate it up, but you already have the markup in its default state. Yeah, so x-cloak is out for that. So with that, you could literally just add style equals display none. Like inline attribute onto the div in the backend and it will just be hidden by default. You could add a hidden class and it'll do the same thing because it just uses CSS to hide stuff anyway. It's not like managing a whole DOM tree itself. Kate: Yeah. Awesome. Maybe we could talk a little bit about, you touched on it lightly, directives and that sort of stuff. Caleb Porzio: Yeah. Like available directives in Alpine and whatnot? Kate: Yeah. Ben: Yeah. Caleb Porzio: So the core of Alpine is x-data. That really is the magic sauce. It's really simple and subtle. But it's funny because I feel like it's a given now, but I remember when this wasn't even a thought of mine and it popped into my head and I went, wait a minute, what if this framework was like Vue except the data like declaring a component was also a directive that you would just put in markup. And what if instead of referencing some JavaScript objects somewhere else, you just literally put in the data as a literal right there in the markup and then everything inside of that div or whatever element has access to the data in its template and scope. So x-data is god in Alpine. That's the sauce. Then there's lots of little handy ones. Caleb Porzio: Same kind of ones in Vue like x-show is how you toggle an element on and off. X-on, you're listening for events. And I added a few things because the driving force behind Alpine, initially, I was going on a JavaScript diet and I really just needed JavaScript for toggling stuff first and foremost. Like tabbed browsing type deal on a page, maybe steps in a multi-step form, dropdowns like profile dropdowns, stuff like that. I needed basically to toggle stuff. That was the primary thing I needed. And I thought, why is it so difficult to do this? And so I created Alpine in these directives, but also there're specific things that are annoying to do like when you click on a dropdown, you want it to show, but then when you click away from it, you want it to hide. And this is not trivial task. You have to dig in and use event delegation, browser events, and track the event target of the originating event and all this stuff. Caleb Porzio: And I thought, well, Alpine should be a framework that's built for these common needs. So there's at click, which is listening for a click and you can add dot away, which is basically the inverse of it. It's like listening for a click away from the thing that it's declared on. And then it'll just run whatever expression you put inside of it. So it's little extra modifiers like that, little niceties that I've added just to kind of speak to the experience of the everyday developer working with browsers in the DOM. Yeah, so there's listening for events, there's binding attributes, just like Vue you can bind any attribute, dynamically, classes, style attributes, disabled, whatever. Those are the biggies. And then there's a few extra small... Caleb Porzio: There's X4. I mean, that's a big one, looping. But the first iteration of Alpine had no concept of like a listing system and same thing with x-if. One way that differs from V4 in Vue is it uses a template tag, which again, just speaks to the nature of Alpine. It's like template tags are a thing in browsers. Like we have the thing in browsers that automatically doesn't show it on initial render and just stores that markup for you when you need to make it alive. When you need to hydrate it, you can pull that fragment out of the DOM and put it somewhere. So that's X4 and then x-transitions. Alpine also has a really robust transition system that is extremely, I don't know how to say this without sounding like whatever, but it's really good. It's really good. It took a long time. Caleb Porzio: And it was pretty much driven by Tailwind UI. I'm friends with, with Adam and he loved Alpine right away and he wanted to use it in Tailwind UI, but he's like, dude, you need a really good transition system. And so I came up with one and he's like, no, no, no, no. I need full control over the Bezier curves. And I needed the transition out to be half the duration of the transition in, and I need the transitions to cascade so that an outer one doesn't stop and hide something before an inner one finishes. And it's like stupid complex, but it's done now and stable and it's really good. Kate: That's awesome. That's great. Yeah, because I listened to the episode of Full Stack Radio with you. At the time, it was about a year ago, and you were talking about how there wasn't a loop option in Alpine. Caleb Porzio: No way. Kate: Yeah. Caleb Porzio: That's crazy. I don't even remember that time. Kate: No, that's awesome. Ben: Now, as we look to the future, curious what's the future of Alpine? What are you most excited about on your roadmap for the next couple months, couple of years? What's out there? Caleb Porzio: So I rewrote Alpine recently. It's not released. It'll be Alpine version three and it's a total rewrite from the bottom up. I guess the big architectural difference now is that every DOM manipulation in Alpine going forward after V3 will be a true side effect of state manipulation, sort of like reactive state. And maybe the best way to explain that from like a bird's eye view, if you have like 1,000 components on a page and if one tiny element of the 1,000 elements relies on one specific piece of data, when that piece of data changes, only that element changes and nothing more, which is a huge improvement. Alpine is, it's like JS Sprinkles, so it's not used really to drive out full SPA huge frontends. So you don't really run into performance issues as much as... Like, I guess I don't have to care as much about performance as some of the big frameworks, but it feels really nice to me to have that really lightweight style under the hood rather than walking the DOM and rerendering every time something changes. Caleb Porzio: So that's huge and I'm using Vue 3's reactivity core for that. So basically the reactivity core of Alpine initially was just my own hand rolled proxy based reactivity engine. And then that broke down quick because you have to support every single JavaScript type and unlimited levels of nesting and it's crazy. So I ended up using observable-membrane, which is Salesforce's reactivity core that Vue 3's reactivity core is inspired from, whatever. But now Vue 3 is out and so the reactivity engine is like a JavaScript module that you can import on your own. It's not tied to Vue in any way. And it's freaking awesome. It's like solves 1,000 problems that Alpine has had to work through over the year and some change like instantly. So that is the core of Alpine 3. And I get to focus on making the core as expressive and lean as possible. So yeah, maybe that's kind of a really deep tech answer. There's some other, not as technical answers, but that's the technical one of where is Alpine headed? That's where it's headed right now. Ben: How about in terms of any API changes or any new features that you just can get excited about? Obviously performance is something that affects everyone using Alpine, but just curious if there's any new, fun things you can do or stuff like that. Caleb Porzio: So there's a handful of little things that aren't probably worth going into detail on, but here's maybe the big one. In the first two versions of Alpine, x-data is how you declare a component and then everything inside of that has that data, but if you have like a nested component, it has an entirely new scope. So every component is an island unto itself even if it's nested. Cross component communication isn't as pleasant. So new Alpine, and if you listen to that Full Stack Radio episode, you remember me talking to Adam about this, where he's like, "I would assume that encapsulation would just be like JavaScript closure scope. Anything can access anything outside of itself and if it changes something it overwrites that scope for itself." Caleb Porzio: So that's a big change from day one that I wanted to do with the new version of Alpine, it's like scope, just cascades. If you want a global store, you could put x-data on the body tag and there you go, you have a global store. There's a billion better ways to do that, but you could. So that's one benefit and another cool under the hood thing related to that is every Alpine expression, when it goes to evaluate itself, it just crawls up the DOM stack and collects a bunch of data objects up the DOM tree. Literally using dot closest like in the browser, just crawls up the tree, builds up a stack and then that's its scope for its execution. All the scope is literally attached to the DOM elements themselves and there's no such thing as like a component class under the hood. Caleb Porzio: It's all totally like ephemeral. Yeah, so anyway, that's one big change that is coming that I don't know if many people will appreciate, but I appreciate it a lot. What else? There's a few other ones that I've been toying with and I'm really unsure about, but maybe I'll give you those, but dust hasn't settled on them. But I started building an x-intersect, which is basically a really declarative nice way to use the Intersection Observer API. Basically for me, the case is when I'm building like a marketing page and you're scrolling down to something and you want it to fly out, like you just want something to transition in or fly in or animate in some way based on the user scrolling in, which I think is an extremely common need, it's kind of complex. Intersection Observer is nice, but it's not incredibly intuitive and it takes some time. Caleb Porzio: So I thought, wouldn't it be great if you could just say x-intersect on any element and then its expression will run when it shows up in the viewport and that's it. And then I added a few niceties, like x-intersect. You can also say colon enter or colon leave to scope it for either entering the viewport or leaving. And you can say dot once if you only want it to happen once. So that's something that I'm not sure if I'll put in core, I will put it out there, but it might be a plugin. I don't know. So that's one that I think is just a nice utility. I guess I'm working on a little secret project that I haven't actually talked to anyone about at all on any platform, but I'll mention it here. I'm looking into web components and seeing what the story is with Alpine and web components. And I think there's a really cool story there and I'm extremely excited and I have a bunch of prototypes built. Probably not going to be core, but that's something that is definitely secretly on my radar for 2021. Kate: Or not so secretly if you're listening to this podcast. Caleb Porzio: Not so secret, but yeah, so that's a big one that I'm not going to hold up V3 at all for, and it might be a completely separate package. But it's something that I'm really personally very curious about and interested in. Ben: Very cool. And I guess even more broadly, completely outside of Alpine, what are you most excited about in the world of frontend for 2021. Caleb Porzio: So web components. Forget about the stuff I'm working on, like lit-html or LitElement and any of those polymers, any of those frameworks I think are really cool, but web components has come so far. And I think it's the answer to a lot of things. I just wish it was farther. I wish there was a story for styling web components well. The scoping of styling is just a huge hurdle in web components and there's no good answer. And I feel like if the web as a platform could answer that, then we could have first-class components, cross platform, cross framework, that we could plug in play and make... Like, why do we have the same things built for Vue and the same thing's built for React, like something like a datepicker? Like why are we splitting up all of the effort amongst these ecosystems? And I think it would be freaking fantastic if we could share them amongst all frameworks. And I see that as a huge pathway in that direction, but there're some serious hurdles like props, scope, slots, styling. There's things that any componentized framework is used to using and loves using and should love using that web components just totally lacks. That's something that I want to see development in, in the future. And I think we will because that's been the story so far. Ben: Yeah, and it sounds like your secret web components experiments maybe potentially are in that direction. Caleb Porzio: Yes. Kate: Okay. So Caleb, tell us a little bit about your other project Laravel Livewire. Caleb Porzio: Yeah. So Livewire is actually the reason Alpine exists because a while back, so Phoenix came out with LiveView which was this way of creating interactive frontends, but only writing backend code. And it was pretty wild and it just struck me when I saw it because it was kind of along all the same philosophies that we talked about before, sort of backend first philosophy that I had been kind of inching towards. So I wanted to create my own prototype in Laravel and that was like a week after I quit my job to go on a "sabbatical" and the sabbatical never happened and I never got a new job. It's been like two years now. Caleb Porzio: I've just been working on Livewire ever since. It's taken on definitely a life of its own. So if you know Phoenix LiveView, I guess I'm making this note that it's similar in nature and goals, but maybe not exactly, just like a Laravel version of Phoenix LiveView. But anyway, so yeah, that's kind of the origin story of LiveWire in Laravel, is bringing that sort of, can we make a way where you can do the interactive parts of a frontend that rely on the backend that's really painful right now. And there's like server components in React and there's things that are coming out that are answering this problem like the server function things in Next. Notice these things that are answering this problem of like, okay, is there a way that we don't have to have two completely separate systems that are talking to each other all the time and like, whatever? Anyway, testing them separately. Caleb Porzio: So LiveWire is an answer to that problem in Laravel ecosystem. And it uses a lot of the philosophies basically underpinning Hotwire, which just came out. It wasn't inspired by Hotwire because it didn't exist for two years, but it was inspired by a lot of those Basecamp philosophies and GitHub. If you like open your DevTools when you're browsing GitHub and look at the request sent back and forth, there's very little JSON. It's mostly HTML snippets using like pgx. There's just so much there to bringing templating back to the backend and passing HTML over the wire. And that's kind of the core fundamental thing with Livewire, but I needed a way to handle ephemeral little browser interactions and that's why I created Alpine. So there are two sides of the same coin, but yeah, I work on both projects and I'm super excited about both of them and yeah, that's Livewire. Kate: Yeah. Awesome. And then Caleb, tell us a little bit about Make Vs Code Awesome. Caleb Porzio: Yeah, I've sort of an early adopter of Vs Code. There's probably many earlier than me, but I've just been using it for a long time coming from Sublime and I liked it for the things like the integrated terminal is probably the biggest reason that I went to VS Code. And now it's gained a ton of steam and there's a bunch of little ways that I found it to be not sublime, I guess. And I mean that both literally and metaphorically. Yeah. Like just the experience. There's so many more things happening and so many more things are jumping out at you on the screen and it kind of gives you some of a bigger IDE, but it also comes with it a lot of the noise and fan noise and a zillion extensions you have to install. So I wanted a more zen experience in VS Code and I just wanted to streamline the workflow as best as I could. Caleb Porzio: And I just did that over years working with VS Code every day and enough people had asked like, share your settings file, how did you do that? How you do this. And I went, all right, well, how about I create a course? Well, it started as an email list and then of course, ballooned into this huge thing that took me forever. And I poured my life into for a while and now it's Make VS Code Awesome. So if you use VS Code, at least go to the landing page and hear me rant about some of the things. Kate: Yeah, it's really funny, our YouTube channel, we have a couple of videos up and the biggest question is everyone asking, how do you get that theme in your editor? Not even talking about the code. Caleb Porzio: My profile bio for the longest time, it was like theme, colon, front, colon because I know I'm going to post the deepest thought I've ever had and the first comment will inevitably be "theme/font?" Kate: Right. That's awesome. Cool. Well, Caleb, it's been a pleasure. Thanks for coming on. And yeah, we'll see you around. Caleb Porzio: Thanks for having me. It's a great time. Brian: Hey, it's Brian again. So it turns out that running a podcast is maybe harder than we thought. And so I kind of want to hear from you. I'm genuinely interested in your feedback. We have to think about new topics, new guests. We have to find them. And don't get me wrong, we can do it, but it's a lot easier if everyone else who's listening helps. So if you'd like to suggest the topic or volunteer to be on PodRocket, we'd like to hear from you. So you can do that by going to podrocket.log rocket.com/contact-us. The hyphen is next to the delete key, if you're curious. If all of that is too long, you can just email me directly, brian@logrocket.com. That'd be great. Also, if you're feeling magnanimous, be sure to like and subscribe to PodRocket. Thank you.