Code and the Coding Coders who Code it
We talk about Ruby, Rails, JavaScript, and everything in between. From tiny tips to bigger challenges we take on 3 questions a show; What are you working on? What's blocking you? What's something cool you want to share?
Code and the Coding Coders who Code it
Episode 62 - Cameron Dutro
Use Left/Right to seek, Home/End to jump to start or end. Hold shift to jump forward or backward.
What if you could keep Rails pages fast, accessible, and SEO‑friendly, yet still get modern interactivity without shipping a mountain of JavaScript? We sit down with Cameron Dutro to unpack Live Component, a server‑first approach that breathes life into ViewComponent by treating state as data, rendering on the server, and morphing the DOM with Hotwire. No fragile ID wiring. No React by default. Just clear state, small payloads, and focused updates.
We trace the path that led here: experiments rendering Ruby in the browser with Ruby.wasm, Opal, and even a TypeScript Ruby interpreter, and why those payloads and debugging pain pushed the work back to the server. Cameron explains the Live Component mental model—initializer‑defined state, slots, and a sidecar Stimulus controller—plus how targeted re‑renders make forms and micro‑interactions feel instant. We talk transports (HTTP vs WebSockets), serialization best practices for Active Record data, and where React still shines for high‑intensity builders and editors.
Beyond the code, we dig into the bigger web story: how DX‑first choices often punish users on slower devices and networks, and why a balanced, server‑driven approach can close that gap. You’ll hear real‑world tradeoffs, debugging techniques that feel like home to Rails devs, and a clever fix born from a Snake game that surfaced timing issues and led to a preempt option for queued renders. If your team wants dynamic islands without adopting a full SPA, this conversation offers a practical roadmap.
Explore Live Component at livecomponent.org and the GitHub org at github.com/livecomponent. If this resonated, follow, share with a Rails friend, and leave a review so more builders can find it.
Judoscale
Autoscaling that actually works. Take control of your cloud hosting.
Honeybadger is an application health monitoring tool built by developers for developers.
Judoscale
Autoscaling that actually works. Take control of your cloud hosting.
Disclaimer: This post contains affiliate links. If you make a purchase, I may receive a commission at no extra cost to you.
Hello everyone and welcome to another episode of Code and the Coding Coders Who Code It. I'm your host, Drew Bragg, and I'm joined today by Cameron Dutro. Cameron, for anyone who's not familiar with you, would you please do a quick introduction for the listeners?
SPEAKER_00:Big fan of the show, so thanks for having me on. Yeah, I'm Cameron Dutro. I work on the Core Dashboard team at Cisco Meraki and have been working with Ruby on Rails and Ruby more generally for the last 15, 16 years. Started out at Twitter working on the Translation Center, which is a Ruby app or a Rails app, and then just have kind of stuck with it since then and excited to chat with you today.
SPEAKER_01:Anyone who is new to the show, the way this is going to work is I'm going to ask Cameron three questions. There will be more, but three basic questions. What are you working on? What kind of blockers do you have? What's something cool, new, or interesting you want to share with the audience? Doesn't have to be coding related, but it is code and the code encoders, etc. So it absolutely can be code related. So, Cameron, what are you working on?
SPEAKER_00:I'm kind of on the show. I think because I reached out to Drew about a project I've been working on called Live Component. And I was telling Drew kind of pre-show here that Live Component is like an outgrowth of a bunch of front-end concepts and ideations that I've been working on over the past couple of years. And I think actually Drew had just brought up too in the pre-call that we had a conversation. I think it was Sin City Ruby in 2023 or 24, which is unfortunately the only one I was able to go to. Jason Charns had given a presentation during that conference about his company, Podia, and his work on trying to get, I think it was like a website editor project.
SPEAKER_01:He was our site editor. We have it in React. We built it when Hotwire wasn't really a thing. So he was kind of like, I wonder what it would be like to try and build it now with Hotwire as it is.
SPEAKER_00:Totally. Yes. And I apologize. I forgot that you also work at Podia. Podia is always like talking about what they're working on and doing. And like I because I listened to Andrew Mason on the other on the remote review podcast. And he talks about his work a lot. Just lots of cool stuff going on over there. Anyway, so Jason, yeah, so you're right. So the site builder that he was working on, yeah, like you were saying, he I guess first built it in, I guess tried to build it with just regular rails, and that didn't work out so well. And so you guys switched to React. And then his presentation was about like, what if we had tried to build this with hotwire instead? And he sort of like live coded the hotwire version of that on stage, which was like so great. I mean, I was nervous for him, but also like so impressed that he managed to, because he really did it. I mean, it was at the end of the day, he had a working prototype of that in Hotwire. And I had not used Hotwire that much before watching him do this or stimulus for that matter. And so watching him do it was a real like crash course education and like how that stuff works. And there were some things that I noticed, right? Like one of the things I noticed was that he was having to like wire up IDs everywhere. So like you have an ID on the page, and then you have to target that ID in the controller when you render the response, the hot wire response. Like a turboframe, I suppose, has an ID and that matches with an ID that's already on the page, and then it morphs the contents of that into the page. And the morphing part of it was cool, but like the ID wiring, I was like, boy, that really feels like it could be ripe for mistakes, right? Like I could target an ID that doesn't exist, or I could target the wrong ID, or right. And there's nothing really linking those two things together. That was one thing I noticed. Another thing that I noticed was just how often he had to flip back and forth between different files. So like there was a JavaScript file and there was his templates and the controller, and the this, and then there's so many times he had to like flip to another file, and sometimes it would be the wrong file, and he'd be like, oh crap, this is the wrong file. I have to go search for the other one, a bunch of tabs open. I think we've all had this experience with working on apps in general, and the navigation aspect of it can be kind of of a time sync, right? Like I've got a billion files open. I'm trying to find the, I know exactly where I want to go, but I can't find it in my editor. So just the overhead, sort of like switching between files, maintaining these IDs in your head, which one do I target next, right, from this controller action. And something he also said that lit off sort of a spark in my brain was that Podia has a bunch of view components, but they couldn't really use them because you can't re-render them on the front end. You can only render them on the back end, kind of one time. They generate HTML and they ship that to the browser. And that really made me think like, huh, what if you could render a view component in the browser? Would that have made this easier? So I actually asked him that question at the end of his talk. And he said it would have made it much easier, or it would have made it more possible, I think, to reuse their existing systems and components if they had been able to do that. And at the time I was working on this web like framework, I guess you call it, like a replacement for React, that I called Nido. And the concept behind Nido was that it was Ruby running in your browser, and you could load a view component, for example. I think I actually used Flex at the time because Flex was easier to run in Ruby and in JavaScript, because it's just a simpler project. Like View Component depends on action view. That's a big dependency to stick in your browser. And so I was looking at Flex for the first iteration of this. I had also at the time, been because I didn't want to transpile the code, so I'd also been working on like a Ruby implementation, like a Yar of implementation in TypeScript, which is like one of the reasons I was able to answer some of your questions on the game show, because I had been working on an actual Ruby interpreter. And so like I knew the ins and outs a lot better than I would have otherwise.
SPEAKER_01:The cheat code for the game show is like if you work on a Ruby interpreter, you get pretty close to some of the weird Ruby in the game show.
SPEAKER_00:You do absolutely do. Yes. To be honest, though, some of those questions still like totally stumped me. Like there was no substance.
SPEAKER_01:But I wrote the thing. That's the only and it's funny because if I haven't given it in a while and I'm like prepping to give it, like I quiz myself and I get questions wrong.
SPEAKER_00:Totally. Yeah, some super esoteric little corners of everybody I've ever talked to just loves your game show, by the way. Thank you. It's super fun.
SPEAKER_01:It's hard to put down because of that. Like I keep saying I'm gonna do a talk that isn't that. I'm gonna do a proper talk or at least just a different topic with some other weird presentation aspect to it. So many people are like, we'd love to have the game show. And I'm like, well, if you'd love to have it, I'd love to give it. Like I'm not gonna submit it to any places. I'm not gonna be like, would you like my game show? But there's enough places that they're it's fun. And like I said, if you haven't seen it in a year, I could not change a thing and you'd probably still get a couple wrong. It's just such goofy Ruby syntax. So if I did at RubyConf in Chicago with Matt's in the front row, yeah. And when he got a question wrong, I was like, I just like I can retire now. I got I stumped the creator of Ruby with my silly little game show. This is gold.
SPEAKER_00:I can retire. Happy man. I can say that even though I had worked on the interpreter and got some wrong at Sin City, I came back and had seen the whole thing. I think you probably added some new questions and whatnot, but like even seeing it again, like there were some that I'm like, oh yeah, I saw this one last time, but I do not remember the answer to the question.
SPEAKER_01:Yeah, in addition to the Matt's stumping Matt's with one, that was great. Having him like interact with people, like everyone was calling on him to help. But the best was I forget who ended up coming up, but they were like, Yeah, I'm on the Ruby core team. And I'm like, Well, that's great. And it was for the flip-flop operator. Oh, yeah. Like he was helping whoever looked at the question and he named it. And he's like, That's the flip-flop operator. And then he paused and he's like, Now I just need to remember how it works. How it works, yeah. And I was like, that is perfect because like it was one of those. The first time I saw it, I was like, I don't even know what to Google here. Like, how do you really? I don't know what this is called. I don't know. And this was pre-AI, so I couldn't just copy and paste the syntax and be like, what the hell's going on here? Yeah, yeah. So it was just so great. Someone even on the Ruby core team gets up and he's like, I know exactly what that is, I just don't remember how it worked. And I was like, Thank you for proving my point. Of like, when you're writing readable Ruby, people have to know what's going on. Great.
SPEAKER_00:Like sitting here now, too. Like, I don't think I could tell you what the flip-flop operator looks like or even does now. Even having seen the presentation twice and like having written Ruby for a long time, I just feel like we don't use it that much, I guess.
SPEAKER_01:Now, because I've talked about it enough, people have shown me real use cases and like the reason why it was undeprecated after it was deprecated of like, hey, we use it in this parson library, we use it in this way, or like these older projects rely on it. We're not rewriting them. So I get it now, but yeah, it's one of those. The first time I ever ran into it, I was like, really? Not even a code comment saying, hey, you might not be familiar with the flip-flop operator or like something. It's like for me, Ruby was always the most readable language. And then I ran into something that was just like not readable. Yeah. It's like holy crap.
SPEAKER_00:Yeah, for sure. But there's been a number of talks, I think, at previous Rails comps where people will bring up sort of like weird corners of Ruby. And sometimes I think the flip-flop makes it in there. James Edward Gray, back in like 2012, the first RailsCon if I ever went to, he gave a really fun talk where he went through like a hundred weird things in Ruby in like rapid fire back in the day. Yeah, he was doing talks like that and they were super fun. And I think that yeah, he also had the flip-flop in there at one point and like just blew past it. And this is one of a hundred things. And everybody was like, okay, like I don't even know what I would use this for, but yeah.
SPEAKER_01:So good. Sorry, I totally derailed your line of thought. Well, we were talking about. No, no, no. You were writing a bit of a Ruby interpreter in TypeScript.
SPEAKER_00:Well, actually, you know, it's funny you say that. TypeScript is actually such a great choice for a library like that because there are so many times where I'm like, I don't actually know what I'm doing. Like the big one that really made me appreciate the power of like a typed language in for something like this is that you so you know that the difference between like a regular method and like an async await method in JavaScript. So like it returns a promise, and you can't just like use the value to await it, right? And so like that whole async await model, if you use it in one place, it like a it like infects everything else, right? So like if a function calls another function that returns a promise, then that function has to also be Marcosync to be able to await it, right? And so it ends up, and that's what happened to me. I was trying to use some node API, or maybe it was even a browser API, in some like Ruby method in this interpreter, and the only way to call it was via async await or via promises. And I was like, oh no. And so I literally had to go through the entire thing and change basically every method call to async await so that I could support that. Yeah, it was really painful. But because it was in TypeScript, I was able to just like turn on a bunch of like compiler warnings that told me when I wasn't awaiting things or when something wasn't, and like I could also I actually don't think I used any tools to actually fix all the function calls and things, but every time that I put an async in front of a method call or a method definition, it would tell me, wait, you forgot to change the return value to a promise of this type, right? And then just also just being able to like right-click and say rename this symbol, and it renames it across the entire code base. And at the time that I was doing this, I mean, I was pretty far along in the project. And so like being able to do that was so nice and helpful. And like, yes, adding the types and maintaining them and all that and keeping them in your head, it's overhead for sure, but it really pays for itself in some cases.
SPEAKER_01:I mean, now that we've got Claude AI writing all of our code for us, you're not the first person to bring up like those kinds of hey, it's really nice with typed languages because you can do this quick refactor, it'll yell at you. And it used to be like, yes, I hear you, and there's trade-offs for everything between static and dynamic typing, but like with Claude, I'm like, yeah, Claude can do that in my dynamic language now, too. And I mean I'm fairly confident in its ability to do it accurately. The benefits of both different types are almost like melting a little bit. It can just handle it. It's yeah, wild.
SPEAKER_00:Yeah, that's so true. It's they're getting so good that yeah, like maybe this is like kind of a boon, really, for dynamically typed languages where you don't actually have to be have the type information around it all the time, which yeah, super interesting. Good point.
SPEAKER_01:Yeah, we just had Scott Werner at Philly RB and he was talking AI because he runs the artificial Ruby meetup up in New York, and he had some really interesting ideas and thoughts on where programming is going to go because of AI and like the way we're using AI right now is like it's not the end game. We're like barely scratching the surface of how AI is going to shape how we write programs going forward.
SPEAKER_00:Yeah, yeah, both exciting and scary, I would say.
SPEAKER_01:Yeah, interesting stuff, stuff that we didn't have to think about before. Like I love meetups because you get this side conversation, someone does a talk, and then everybody kind of creates their own little bubbles where they're talking about X, Y, or Z. And the one group I was talking in, someone had ranked the token efficiency of programming languages, and Ruby was in the top three of most efficient. So, by most efficient for tokens, uses the least, AK costs the least. Couple that with it's not hard research, but from all of the tinkering I've done with AI, AI does a really good job with Rails conventions. Like if your Rails app follows the Rails way pretty closely, like it does a really good job finding stuff, knows where to put things, understands the boilerplate. And I'm like, you combined that Ruby on Rails is already a predictive framework, and Ruby's a great language to read. Couple that with AI works really well with Rails and it's token efficient for Ruby. I wonder if that's going to help more startups be like, well, let's use AI to build our vibe-coded thing, but let's use Ruby on Rails since it's cheap and AI's good with it. Like that's an interesting force multiplier for Ruby on Rails, I think.
SPEAKER_00:Yeah, for sure. I do think, too, there's like a lot of really interesting investments, I feel like, that are being made in AI tooling, like lots of Ruby MCP servers, lots of like jobs that of course communicate with like the open AI API, things like that. Those came out really quickly. Like the Ruby community seems to like really be responding to this moment in AI right now. And I that's really heartening to see because I think, like again, I'm somewhat of an AI skeptic in some ways, but also like something of not of one, right? So like I tried to feel it out just like everybody else. And I mean, I think AI will change the way we write programs. There's no question about that. And so, like, if we can be more ready for that than less ready, then that seems like a good thing, right?
SPEAKER_01:Yeah, it's not even remotely surprising that the Ruby community as a whole is like on top of, hey, what can we do with this? Not even like, yeah, I don't think anybody in the Ruby community, aside from a handful of people that are like very bullish on AI, like, no one's pushing AI. It's more of like, hey, what can we do with it? Like, where is this going to go? And like, that's what I love about what Scott's doing with AI. He's doing so much exploration, and some of the stuff he comes up with feels so why? Like, very whimsical, very like, why would you build this? Like, what's the point of this? It's like, I just wanted to see if I could. Like, I just wanted to, yeah, we were riffing on an idea and we've shoved it into AI and let three different agents come up with a plan and we like and the way that he's going about it seems so much more fun than I don't know how we're going about it in our day-to-day, where it's like, well, I don't write code anymore. I tell the LLM what I want it to build. Yeah, that's yeah, boring and corporate and bullshit. He's over there having fun with it and having a blast. Wacky, no one's gonna use this, but I wanted to see. And that's why, like, when he gave his talk, and I don't want to spoil it because I know he's planning on giving it in a few more places. It was just a very like, I think he's on to something. I think he's on to like we're using this tool to do something way different than we can be doing it because of this tool. We just haven't quite figured that slice out yet. Like, software engineering is not going away, it's just changing. We are going to use this tool to build bigger and better things, but we are still building.
SPEAKER_00:So, yeah, and I love that framing. And that's a much less defeatist framing, I think, than like all the jobs are going away and nobody will be writing any code anymore, and it's all gonna be agents everywhere. And like, I think one of my big sort of problems, I guess, with how a lot of the AI companies themselves are framing AI is that they're they're claiming it can do all these things that they really can't do. That's number one. But there's also, I think, just kind of this condescension, I suppose, for labor. And there's some companies in pr in particular that actually want to replace all jobs, not just programming jobs. I don't mean necessarily the leaders of these AI companies, but more just there's there's one company in particular that wants to like use AI to literally make it so that nobody has a job, so that nobody has to work, so that everybody has, and they're trying to fit universal basic income into something, into that world and like plan for when none of us have jobs, we're all just able to do whatever we want all the time. And condescension is the wrong word, but just like this contempt for labor, right? Yeah. And that's something that really kind of rows me the wrong way. And I wish that there wasn't that aspect to it, because I think if there weren't, like we could all just focus on how cool the technology is, but instead we have to focus on how cool the technology is and also how am I gonna feed my family based on these things you're telling me? And that I was told back in the day, like, this is a good career. You should go into this career, you should learn how to code. And I was like, okay, and I did, right? And now it's like just kidding. You know, this is a bad career now. You shouldn't learn to code, nobody should. We're all gonna use agent. And so it's like, wait, what? It just feels like a rug pull.
SPEAKER_01:And really, I don't think it's true that there won't be a human component. I mean, maybe AI has changed rapidly. It's sort of weird to think like Claude Code came out in what May 2025. Like, we haven't even hit a year with it yet, and it's already changed our jobs drastically. Yeah, yeah. So I don't want to sit here and say, oh, it'll never happen or anything, but like the idea that our jobs will not exist is not an imminent threat. Our jobs definitely will change. I really loved writing code, like I found it very meditative. Like, you'd solve the problem and then you'd write some code, and that was great. And I loved the writing code part, it felt very zen. It was a great escape for me. I loved it, and that part of my job is gone, and I had to do a little bit of grieving because of that. But the really, really fun part of my job is figuring out problems, and that still exists because I think that LLMs are still really bad at it. And to be fair, even the code that Claude writes for me, when I have it write code for me, it's not ready to go. It's like 80% of the way there. It needs refactoring, it needs someone to tell it things and to call it on its bullshit. I call it out all the time. It can't one-shot things right. Maybe it's a fault of mine, maybe I'm not prompting well enough. But talking to my peers at podia, like we're all kind of on that boat of like sometimes you do get a PR that was one-shot AI and you can tell, and it's not good. It needs a little bit of human touch before it goes out. Still, maybe that'll change.
SPEAKER_00:No, true.
SPEAKER_01:There's still someone gotta be there guiding it, giving it guardrails.
SPEAKER_00:Yeah, so you're right. I think our jobs are secure for the time being, anyway. I also like your framing there, just like you know, that the writing of the code itself is what a lot of us think of as the fun part, but but really, what are we really doing? We're really just solving problems, and like the problem solving part of it is kind of where I think a lot of we can drive a lot of meaning. It's not so much like the actual output of the code, it's like I learned this problem well enough that I could write a code solution to it, and that is where the value is. It's not so much in the code itself, right? Yeah, but no, of course, a conversation is going to include AI because that's just such a huge topic. So back to live component and where you were at with Yeah. So the I think I left the story off that I'm working on this TypeScript interpreter, and you know, that was super fun. And I'm still contributing to that from time to time. There's just obviously so much to do on it, right? Like the Ruby standard library is enormous, and so like trying to support all of that is hard. I will say what I've been doing on that project, I've been using AI on that project to debug problems for me. So I don't have it write a lot of code. What I have it do instead is like find where this problem is because a lot of the time I'll run a piece of Ruby code through the interpreter and it will crash with some like very vague JavaScript or Ruby error. So I will point, I use augment in my editor and I just say, Can you figure out? Don't write code yet, but like figure out why this is breaking. And it will what would take me hours to debug, it can do in like 10 minutes, which is just super helpful. And then I can go and I can either write the code or I can ask it to like draft something for me. And I usually I usually write the code myself because that's again the fun part and it's a side project and all that, but it could just save me so much debugging time. And because I've got two young kids, I don't have a lot of free time. And so, like, if I can just type into my augment code extension, if I can just say like figure out what's going wrong here and then report back to me, and then I can hit enter and then go play with my kids or serve them lunch or whatever, and then come back. It's just such a great like time saver for me and a great like like productivity unlock. And again, this is all side project stuff that I'm not like actually shipping to people. So it doesn't I'm not, I don't feel super responsible for writing every line of code or debugging every single problem. Anyway, so that was that's a fun project that's called Garnet. You can go to camera tron slash garnet dashjs on GitHub. It uses the Prism parser in Wasm. It does a bunch of other cool things I think are cool. Like it uses the Enigmo regular expression library, which is a C project that's also compiled to WASM. It uses that as its regex engine. Because I did not want to write my own regex engine. That sounds like a huge. I wonder why. Yeah. So anyway, so that project was sort of in flight and sitting there at SinCity Ruby and listening to Jason talk about rendering view components in the browser, and I was like, man, this is really where we should be doing. I should try experimenting with how I could potentially take a view component and render it in the browser with Garnet or whatever. And so I tried that and it worked okay. But like there's no way that like I'm gonna tell people to use Garnet because it's such an incomplete implementation. And so I also dove into like trying Ruby.wasm because you can run Ruby in the browser now with that project and got to a place where like I was rendering stuff in the browser with that as well. But then I kind of hit a wall because you look at the download size of Ruby.wasm and it's just enormous. Like it's we're talking like 50 megabytes. And that's not even your application code. That's just the interpreter. And after a while, it just felt like I was just fighting the browser. Like the browser is not really meant to run these. I mean, yes, it can do them. And it's amazing that we can get this far with this cool new technology. And I mean, WASM is really, really cool stuff. I mean, don't get me wrong, it's all very cool. But I was like, it feels like I'm kind of going in the opposite direction here that I should be going. And so like I took a step back and started to think about an alternate approach that wasn't rendering view components in the browser necessarily, but maybe was rendering them server-side and then shipping them back to the browser, sort of using the same hotwire paradigms that they're already in Rails. And a lot of this was also like informed by the fact that I used to work for GitHub. I used to work for the primer team. Primer is a design system. And I worked on the View Component framework itself and was for a while a co-maintainer of that. And then also worked on primer view components, which is like a collection of view components that implement the primer design system. And after a while, though, GitHub started to sort of shutter that project because they were moving mostly to React. And there was also a primer React library that I contributed to as well. But like sort of in that conversation about like should we switch to React or not, I was very much on the side of we should not, by the way, because rewriting an application is because GitHub just seemed like a very foolish thing to do. And we can kind of see, I think now some of the cracks in the armor that that's caused.
SPEAKER_02:Yeah.
SPEAKER_00:So for sure. And there were a lot of people at the company at the time too who like really were against that idea, but whatever, it happened anyway. And so like part of that process was me internally like trying to fight against it a little bit and like resisting that change a little bit. And so I sort of had this brain flash one day. And I thought, what if we because like a view component is really just made up of its props or it's arguments you pass into the initializer and slots that you define. It can really be reconstituted from those two things. And I thought, what if we like defined that a JSON structure of some kind in JavaScript that provided those pieces? It provided the props and the slots, and then just sent those to a special controller action that knew how to render whatever component you wanted based on that information and then returned to you the HTML. And so I mocked like a really quick proof of concept. I also was thinking like, what if it worked over WebSockets so that you were not dealing with a lot of the same like HTTP overhead that you would normally be dealing with in like a server-side rendered application? And so mocked that up. I had it working in this lookbook thing, which is like a Rails app that lets you preview view components and you could click on a button and it would dynamically add an item to this action list component that we had. And I showed this off to a few people, and the reaction that I got was like really good. I was like, this is people seem to think this is an that's pretty cool that we could even do this. And I didn't think it was that like revolutionary. It's like we're just you know rendering stuff on the server like we always have. But yeah, I got a lot of wow, that's cool reactions to it. And so I thought, okay, well, there might be something here. But I kind of put that on a shelf for a long time because I was still working on this like neato idea and didn't know where that was going to go. And finally came to the conclusion that like this is just like shipping more and more stuff to the browser is just generally, I think, a bad idea. I think that, and this is sort of where the conversation gets maybe more philosophical. I think we have to start thinking about the browser differently than we are now. And this is not just true of Rails developers. This is true, I think, of our whole industry. The browser is not somewhere where you want to catapult a bunch of code and just hope for the best, right? The browser is an environment that is at its fundamental core good at like displaying documents. Like it's not an application environment, at least it didn't used to be. And it is now because that's what we wanted to build. All of us web developers wanted to start building more applications. Totally understandable. And that's where like React came from because Facebook had this ads product back in the day, and they were like, we are having a hard time updating this page and like not breaking everything with a single line code change because you targeted the wrong ID, you know, this whole very procedural concept. Like, I'm gonna with jQuery find an element, I'm gonna hide or show it, I'm gonna maybe add a class to it, remove a class from it, right? Like that kind of programming was like brittle and hard for them to maintain for such a dynamic product, like their ads product they're trying to build. So that's where React came from. That's actually where a bunch of other frameworks too came from, like internally at Facebook. They tried to build a couple of other frameworks at the same time, they're kind of competing with React, and React eventually won. But the fact that the web and the browser was not dynamic enough is like where React came from. But we have now come to a place where like the browser does a lot of these things for us. We have web components, we have the CSS transitions API. We have so many tools now that have sort of been a long time coming, granted, but are now like in the browser that we can start to remove these hacks. And I really think of React as kind of a hack. It was designed to fill this void. And I think it's debatable whether it's removable in its entirety now, but I think we should at least start having that conversation. Because what I think React and a bunch of other front frameworks have done is sort of given us permission to like focus on DX over everything else and to focus on entirely browser-driven UIs that I think are doing the web a real disservice, right? Like Alex Russell, who is was one of the Chrome leads for a long time and I think works on Edge now, he has a blog called infrequently.org where he writes about how much of an impact too much JavaScript has on the web. And he has a sort of publishes like a state of the web or a state of JavaScript, I think, every so often. And his 2023 one, he talked about how like how much JavaScript and CSS like we can afford to ship with our applications so that our pages load within a certain amount of time for the P75 of like devices and networks. And that amount right now, well, back in 2023, I think it's a little higher now, was 300 to 350 KB of JavaScript. Now, if you've ever seen even a regular blog page, a lot of people write their blogs in React or View or something, and they're shipping many, many more megabytes than that of JavaScript and browser. And the problem that this causes is not one that us developers see very much because we use really high-end, generally, really high-end devices. We're on really high-end networks. We don't often experience, I think, some of the same problems that somebody in a developing country would run into. And for some applications, it's not a big deal because you know that most of the customers that use it are going to be on a high-end network, high-end device. But for a company like GitHub, which is used around the world, or a company even like, you know, Salesforce is a good example, or Zoom is a good example of it. Like they have a their splash page is like 11 megs of JavaScript or something. Like it's that kind of thing that just feels so gratuitous and that is, I think, damaging the web and making it hard for countries and people in those countries on low-end devices, low-end networks, to access some of these same tools that we use. And so it's really an equality issue. Even for people in the United States, or even people in developed countries where networks and devices are more high-end, we still see this all the time. I mean, who among us has not loaded a web page and had it just blank, show up blank? It's just a white page, nothing's rendering. You open the JavaScript console, there's like a hundred messages in the JavaScript console all red, like this error happened, and like how did nobody notice this, right? Or you click on a button and nothing happens, right? So many different, I think, times that that's happened to me. And I live in the United States, I'm a white guy, like I've got a great computer, nice MacBook M2, right? I have all this high-end stuff and on a high-end network for them compared to other networks, of course. And even I have experienced these problems. And I think that this is in large part due to the fact that we, again, are like shipping super huge bundles of JavaScript to browsers and we're focusing on DX rather than UX. Like a lot of the conversation that I hear about React is not that it is bad or good necessarily, but that it's really good for developers. Oh, this is great. I can write everything in one file and I can bring components in and I can update the state. And there's all these complex state management tools like Redux that I can use to query for my back end for data. And all that's developer focused. It's not user focused. And that conversation, I think, is just really missing the user, their experience. I don't want to rally against React. I think React is super cool and it has served a great purpose over the years. And I write React all on the daily at Cisco because that's what we use for our entire front end. So it's not like I'm really anti-React. I'm just really wanting the industry to take a step back and realize that like shipping megabyte after megabyte of JavaScript to the browser is just not serving users well and is, I think, causing a huge inequality gap in the web.
SPEAKER_01:Hard to argue with that. I mean, React is a tool and it's a great tool for doing certain things, but it's a tool and people are trying to use it for everything. It's like I have a screwdriver, which is great for driving screws, but if you flip it, you could, if you wanted, hammer in a nail with the handle of the screwdriver. And I think too many people are doing that instead of reaching for the right tool, the hammer, to hammer in the nail. That's always been how I've felt about React. It was like someone would be like, Well, we could do it in React. And it's like, but why? Like at Podia, we have a very small amount of React. We have our site builder and email builders because you need that high level of user interaction. User needs to click a button or slide a slider, and they need to see immediately something change on the page. React is really good at that.
SPEAKER_00:Yes. And I would never say don't use React. I would never say don't use Vue. Whatever. I would never say only use web because there's just there's always gonna be a class of problems for which React and View and Angular are really well suited for. But I do think that like most web pages, and I'm gonna go like that level of granular, not so much websites, but like individual pages and maybe even individual sections of a page can very easily be rendered statically. And the other and there's only certain parts of those pages that need to be fully dynamic, fully reactified, whatever. Yeah.
SPEAKER_01:Nothing is more frustrating than sitting there waiting for a blog to load because it's importing React so that I can read your static article. At some level, I get it. It's like if that's the technology you know, you go with what you know. I do get that. But like I think that's more of a byproduct of what you're explaining. There's like the core web that we should be using and reaching for a tool like React when it's needed, not oh, you want to be a web developer? Learn React. Don't even bother with the rest of it.
SPEAKER_00:Yeah. And I mean, I also think that like because React is so popular and because it is kind of the de facto standard, like everybody uses it now for everything, that hurts the web also from a developer perspective because now there's fewer people advocating for adding features that React would normally table for you to the browser and to web APIs and whatnot. It just sort of weakens the web, unfortunately. And I don't want to say that React shouldn't exist, that we shouldn't use it. It's more just that I want there to be a balance, right? Yeah. And that's a great segue into what live component is. So there's many different types of website you could build. Purely static, of course, is one. You could build an application with Rails where like there's multiple routes and you're maybe submitting forms, and that's a certain level of dynamism. But then I think from there, the next step is kind of it's either static or dynamic. But I what I'm trying to sort of advocate for with Live Component is that we don't have to go from one to the other and rewrite everything and there's nothing in between. I think that we there are options in between. One of those options could be just having React, but having it be just individual portions of the page. One option could be using web components, which I think doesn't cover all use cases by any stretch, but is good enough for a lot of use cases. I even think something like jQuery is good for a lot of use cases. Like 90% of the things that I was doing in my work on primer was like hiding and showing things. If that element is on the page and I target it with a selector and then say hide or show, like you don't need React for that. Just like jQuery.
SPEAKER_01:You shouldn't need React for that.
SPEAKER_00:You shouldn't. But yeah, yeah. Anyway, that's so what I'm trying to do with this is just to show that there's like maybe narrow that gap a little bit or provide another tool that can fit within that gap. You don't need to be fully dynamic. We also don't want to be fully static. And so beating around the bush enough just to say that I can finally talk about live component. Live component is a way to render your view components like client side. And that's a little confusing because it's not actually rendering the client side, it's rendering them server side, uses the same technique that I described working on at GitHub back in the day, where the component is defined by its state. And the state object is just a JavaScript, like a JSON object, which has the parameters that the component was initialized with, and it has the slot information and the slot parameters that you initialize the slots with. And all that information is like wrapped up into a single state object, and we can send that to the server, render the component, and then get the response back and morph the changes into the DOM. So you can imagine like a to-do list application, and you can imagine there might be your list items, and let's say you want to edit one of them. It says broccoli. So you click on the edit button. And in a traditional Rails application, what that might do is re-render the page and navigate you to the edit action of the to-do items controller, and you would then be faced with like a whole page reload, and you would get an edit field and a save button. And you would click the save button that would post back to the same controller and then redirect you to like the list page, and you could see the edited item from there. In the React land, of course, there would be no refreshing. You would be using the maybe the fetch API in the browser to post to the controller, and then that would update the item. And then React would just take away the input field and render the text back up for you to see the item. So those are the two paradigms. And I think in Hotwire, it's a similar idea. The difference would be just that like when I submit the form, it's also doing a fetch, but then it's rendering like the results being rendered by the controller, and then it morphs the changes at the DOM and your input field goes away and you get the text back. Live component works really similar to how hotware works because it's built on hotwire and it's built on stimulus. So let's say you have a view component, it's like a to-do item component, and you define a sidecar, JavaScript, or TypeScript file. And in that file, you define a class, it inherits from live controller. And then just using the regular stimulus, like targeting like data action and data target, well, like when this button gets clicked, I want to call this function on my controller. So you might say to do item edit or whatever, you click the edit button, and that calls your function. And then inside the function, instead of firing off a fetch or something, you would just say this dot render, and that would then yield to you what looks like a component instance. And you can say component.props.editing equals false or true, and that's all you have to do. And what that does is it takes the state that the component was rendered with initially on the page, changes that single prop editing to true or false or whatever, sends that to the server, gets the response, and morphs it into the page. So you're literally re-rendering and then re-injecting the rendered content into the DOM. And you didn't have to wire up any IDs or anything. You just had to define a sidecar JavaScript file and add a couple lines of code. So that's the goal of it. It's supposed to like be this like replacement for what you might use React for.
SPEAKER_01:You go through this to-do list idea, which is your standard to-do list, but just at the first glance, just on your basic docs page, it looks like view components. It's view components. Right. But you just have this one extra sidecar controller that's feels magical, but we know it's not. It's conceptual compression. Like it's just what Jason had to do, like to find all these IDs, link all these IDs up. Like it kind of, and I don't know, I haven't had the opportunity to use it yet, but it feels kind of like the biggest win is like that boilerplate's gone. Like we can already do everything you're describing, even with hot wire. You just have an endpoint, like it goes there, yada yada. But it really needs to render out the whole thing. You need to pass it a bunch of information and then let either turbo frames or turbo streams do what you need it to do. This feels kind of like a streamlined version of that, where like, hey, you clicked the edit button. We're just gonna re-render this component. We don't need to re-render the whole page, we don't need a special controller. I mean, we do have a special quote unquote stimulus controller, but like that's it. It's sort of the same idea of like stimulus. Stimulus didn't solve anything new. You could do all of that with jQuery, like you could totally target things, and like it just kind of wrapped it in a way that was really easy on the brain. Like, I just know like how actions and how targets and how things get linked up. I understand that, and now I've got an organized file instead of jQuery soup. It feels sort of like that for this. Yeah. When you have like you said you kind of you're kind of meeting in the middle of like the two extremes of like static and dynamic. Like, are you thinking, what is the intended audience for this? Is it for someone who has like a mostly static page and needs those like dynamic islands? Is it someone who's like, man, I really don't want to use React, but I need the interactivity? What stack are you mostly thinking live component works really well in? Like I can already conceptualize it a little bit, but I want to hear from you.
SPEAKER_00:Yeah, I think the target audience is kind of somebody who already has a lot of view components, but is now kind of getting to the point, just like we did at GitHub, where like they want to add some interactivity to those components. So, like a good example of GitHub was this thing called the select panel, which is part of primary view components. And when you type into the search box, it's supposed to go to the back end and get some search results and display them. And then when you select those items, it remembers those selections. And doing that in a web component was really annoying. You know, it was just not powerful enough to do that kind of thing. And a big reason for that is because there was no concept of like the DOM was the source of truth as opposed to the state being the source of truth, right? Like the back ends data models and whatnot being the source of truth, which is honestly the gap between React and not React is like React has it renders the page when your state changes because it uses that state as the source of truth as opposed to the DOM. The DOM should be the source of truth for some things, but not for a lot of things, right? And so I think the audience is people who have view components and that have struggled with trying to get dynamic content or dynamic behavior to work with those. Maybe they've tried to use web components. Like GitHub, we used web components as like the little add-ons, I guess you'd say. Like you'd have it was sidecar, but not necessarily in a direct sense. It was just we had like JavaScript web component and we had the view component, and they would target each other based on like the custom element name. But that's how we added dynamic behavior. And a lot of the time that actually works super well. But there were other times where it was just like, this is clearly not the right tool for the job. And so I think live components targeted toward that. And I think if you're already using it, you might as well use it for the things that you also maybe don't need full dynamism for too. So, because you don't have to use the re-render capabilities. It defines a stimulus controller and it wires up that stimulus controller belt to the component that you rendered automatically. So there's utility there too. It's not like you have to re-render the thing dynamically and swap in the HTML. You could also just define that component and say, I want to connect this component to whenever I render this view component on in the back end, I want to automatically wire those things together. And when a button gets clicked, I can, and it's a little bit more automated that way than stimulus would be. Like it registers a component for you with stimulus and again wires the things together. And so like I could also just use it that way. And actually, one other like kind of nice feature I think of Live Component is that it does have a React integration too. So if I have a React component or I need to use React, but I want to like send that React component props from the back end, like inertia would do, you can also define like a React component in Ruby land, and then it will render your React component and update its props from the back end.
SPEAKER_01:Yeah, we actually have our kind of a homegrown solution for like for doing stuff like that in Podia, where we have a view component that essentially renders a React component and gives us a avenue for sending it props so it'll re-render for our site builder and email builder, which has worked really well. But you know, that's our own internal. We would never inflict that upon the world. It works for what we needed to do. You know, I think Hotwire got pretty popular because it does require a mental model shift a little bit, but not so drastically. If you were doing traditional React server rendering, then Hotwire doesn't change a ton. You have to make some tweaks to your mental model, but like not nearly as much as going like, well, we were doing server rendering, but now we're an API backend with a React front end. Like that's a huge mental model shift. How much of a mental model shift do you expect it to be for someone like a traditional Rails developer to come in and use the live component?
SPEAKER_00:Yeah, that's a good question. That's a really good question. I've thought a lot about that actually. There's a slight mental model shift, but not necessarily in the parts you might expect. I think that if you are a view component author, you're used to writing view components. You're sort of already used to the sidecar idea because you've got the component itself, the RB file, and then you have like the template file next to it, could be ERB or whatever you want in there. So that part of it should be pretty, I think, familiar to people. It uses stimulus under the hood. So like when you define your JavaScript class and you inherit from Live Controller, that's really just a stimulus controller with some extra baggage in there to handle, I should say baggage, some extra functionality in there. Sure. To handle the dynamic re-rendering and all that. Oh, and then also one thing that I haven't talked about yet, that I'll just briefly mention now, is that it actually uses the same like underlying hotwire mechanism to update the DOM. Like if you're doing a get request, like I show on the homepage of live component.org with the to-do item, when you click the edit button, it'll send the request to the server, but it uses a get for that. But if you want to post a form, actually in the to-do item component, when you click the save button, that's posting a form to a Rails controller. The way that the response works in that case is that like live component provides like an override to the form width helper. And so you have your form width and it's inside your template in your view component, and you can say form width and give it the URL or the model. Or whatever, and then you can say re-render colon self. So you can say when I submit this form, I want you to do whatever the controller does, but then respond with the re-rendered version of this component that I'm in right now. So re-render self. You can also say re-render parent. You can say re-render a particular ID. And what that does is it means that in the controller, you can then say live.re render, like in your template, and that will automatically re-render the component that the form targets. So the form targets a particular component. Like when you're in your controller and you're in your action responding to that request, you can say live.re render and it'll implicitly understand, like, okay, you want to re render this component that has that like wraps the form, and it will re-render that component. You can provide new props and things to it. And that's all done with hotwire with turboframes. It actually renders a turbo frame and then live component will extract the content out of that turboframe and put it where it needs to go. Hopefully that's clear. I it's hard to sort of just speak out the code.
SPEAKER_01:Yeah, but the docs are good. The docs are very good. I felt like I had a good mental model of what was happening with live component. It made sense to me while I was looking through it.
SPEAKER_00:I did want to touch on your question about like what's different, what mental model shifts need to happen. I described all the ways that it's not different, but there's all there is a way that it is different. And that is like when you provide props to a component, like the way the live component works is it tracks the initializer arguments. It uses that to know what you've passed into your component, and then it will look for instance variables with those same names and then will track those things, which means that state is entirely defined by the initializer. You can't provide state in any other way. And I think that that does, and that's on purpose. That's to keep things really obvious. Like this is where my state comes and this is where my state gets set. That it just means that derived state is a little bit more difficult to sort of understand or intuit. It's not quite the same thing as like I'm just newing up a Ruby object, passing some state in. Like that state has to then come back again to be used a second time. And keeping that in mind can be a little bit of a mental shift. Hopefully that's described well enough in the docs, but I do anticipate people kind of being a little bit surprised by that. So hopefully it's not too big a difference that people will not want to experiment with it.
SPEAKER_01:I think that's one of those spots where the experimentation becomes very important. The actual, like, I've read the docs now. Do I want to do this? It's like, well, you need to experiment with it. You need to understand now my initializer needs to be the source of truth. We all do some things after initialization. We call a method or something that will set up some state based on parameters for us. And you might not be able to do that exact thing with live component. You might need to take a slightly different approach.
SPEAKER_00:Yes. I think especially around active record objects, that gets a little confusing because I don't, you don't necessarily want to be doing lots of I.O. like when you're trying to re-render a component. And so there's those mechanisms for serializing your active record objects or like pulling individual columns off of your records and storing those in the state object so that if I go back and need to access those in my re-render, I don't have to hit the database for that. And that's in the docs as well. So the claim on the homepage is that components can re-render in 50 milliseconds or less. And when I was first working on this, I know, yeah. When I was first working on this, that was what I was seeing, and not just in dev. I also deployed it to Heroku and I was seeing really good performance there. And for whatever reason, I tried, and I of course had added features and things to it, and this may be where the slowdown comes from, but I don't know. I wasn't able to figure this out. And I even tried the header instance in Oregon, it's closest to me, and tried one in Virginia to see like what the difference would be. Because I live in California, so like Oregon's really close, but like Virginia is pretty far away. And there is definitely a marked difference between the latency between those two servers. And so what I see now is like a hundred milliseconds or less for a server that's close and like 120 for one that's kind of far away. I mean, I would love it to be less than that. I mean, in development, you see when the server is cold, it's like 50 and then it gets down to like 18 in some cases. Like really, really fast, yeah. Yeah, but like obviously that's not production, it's not live actual workloads. Well, and this is why I really like I'm trying to like not say like this is a React replacement necessarily. I mean, I I think it for some use cases it can be. For some it cannot, though, because React is going to render much faster than that. That's why it's it's sort of a player in the gap between static and dynamic. It's not fully dynamic and it's not fully static, right? There's like a but I think you get a lot from that. You get to reuse your existing components, you get to use the Rails paradigms that you already know, like stimulus and hotwire. And the only thing you're really doing is paying a slight network tax, like we're already paying for so many other things. So I think the trade-off is worth it. And again, it's for some use cases, like not for everything. For live component, you can choose to either use an HTTP transport between the front end and the back end, or you can use WebSockets. I found that the Russia was not any performance difference between those two things. Really? And part of that is because I'm just not that good at setting up action cable servers. I think if you were to use any cable or something that's more efficient, it maybe would be it would be better. I do think HTTP is just simpler. And so that was kind of what I used for the most part, but it does work with both.
SPEAKER_01:Is that a global setting where you're like, I use HTTP or I use WebSockets, or can you do that on a per component level? Like this component trends, you know, uses WebSockets because one reason, and these don't need the WebSocket whatever. So HTTP over here is it global or per component?
SPEAKER_00:It is global right now. It could be per page. If you load a new page, okay, then all the JavaScript gets reevaluated and you could swap in the transport at will. It's still a global setting, but you could in a component on a page, you could swap in a different transport and then swap back to the other one if you wanted to. It's not like there's nothing preventing you from just switching objects, I suppose. But that's a good point. Maybe we should do it at the component level.
SPEAKER_01:So performance-wise, it's it's pretty quick. There's small network latency, as with anything. But is there anything, hey, at a certain level, because all of these live components are hooked up potentially via WebSockets or HTTP? Like you have to be consideration. Like, even like you're essentially serializing state through the initializer. Is there a limit if you've got 20 keywords in your initializer now because you're serial and we're trying to serialize a state like now our network calls are getting very large, and sure, this is potentially not a good use of this, or you need to break that up more, or I have a ton of slots. Like, is there any anything to consider like that? Oh, absolutely.
SPEAKER_00:Yeah. I mean, and I have not hit those personally because the stuff that I've done with this so far has not been of huge size. I did the to-do list app. You can actually see that at to do dash list.licomponent.org. There's also crosswise.rocks, which is like a little set of mini-games, one of which is a crossword that uses live component. And you can pop open the network tab and see what it's doing and see how fast or not fast it is. But I do think, I mean, anytime you're sending data over the network like this is doing, you're you're gonna run into diminishing returns the more and more data you're shoving over the wire. It tries to be as efficient as it can, of course. Like it does compress requests and responses using, I think it uses broadly compression, which is really good for text, which is what this would be mostly doing. Sure. Yeah, yeah. So that shrinks the payloads by 65% or something. So like there's a good amount of a win you get from that. There is a big difference. Like Postgres, for example, will not store payloads larger than 64K, I think, in for WebSockets. Uh, if you're using the Postgres iNotify system, which a lot of people do. If you're using that, there's a limit to how much you can a message size limit. It might be 16k. It's it's actually pretty small. And I actually ran into that myself when I was trying to test crosswise because crosswise, it's a mini crossword puzzle, and there are 16 squares, I think. And it keeps the state for each of those squares. So there's like a bunch of nested JSON structures in there. And that turned out to be too big for Postgres. That's why I added the compression feature. So trading off space for compute cycles there. Fortunately, the browser has that built in though. So it's you're just running native code to do that. So yeah, the there are definitely performance and I think implications of too many slots. I think you see that even with regular view components. We actually had somebody when I was still working for GitHub who was wanting to render, I think it was a table, and that table had like hundreds of rows in it. And the way the view component would have you do that is to define like a row class, like a row component, and then on the table you would say with row or whatever and provide the columns. And he was like, this is taking like whole seconds to render, it's just way too slow. And our answer to that was sorry, like we don't really have a good answer to that. Because it just doing anything else is kind of against like the architecture of the component system itself. So you're there are going to be limitations like that that I would imagine people would get to if they have too many slots. It really depends on how big like the number of keyword parameters you're passing into a component is probably not the limiting factor there. The limiting factor is like how those get serialized. So if you're serializing a string, that's just there's a one-to-one mapping between a Ruby string and a JavaScript string. Those two things exist in both languages, but active record models might be a different story. I think by default, live component serializes all the attributes. No, that can't be right. I don't remember the default. It serializes a couple things for you. If you serialize too many attributes and you have a bunch of different active record models, potentially a list of them that you're passing in, and it has to serialize all of those. And yeah, that could be really heavy. There is, I think, going to be just discrepancies between people's mental models now and what they might need to adopt to use live component. And another one of those things would be just like how much are you serializing over the wire? And like live component tries to like provide a bunch of mechanisms to limit that serialization, like how much you have to serialize and how much you have to deserialize. But you know, if you're not paying close attention to that, you could definitely run into some issues.
SPEAKER_01:Which actually kind of makes me think like, what's the debugging experience like? Because now there's an extra transport layer essentially. I mean, when you're debugging with live component, is there an extra consideration because of the hidden transport layer? Or is there anything that that the live controller that you inherit from for your sidecar controller that is more complicated, or that it you have to take into consideration when you're trying to debug? This wasn't exactly what I expected.
SPEAKER_00:Man, that's like one of the major reasons why I stopped working on Nito, which was that fully in the browser transpiling thing. I didn't even mention this. I used Opal at one point, also got it working on Opal, Ruby.wasm, the Garnet thing. Like all of those suffered from the same problem, which is they were just way too complicated. And debugging them was really hard unless you knew what was going on.
SPEAKER_02:Yeah.
SPEAKER_00:And like I'll be honest, I barely knew what was going on. Especially with the thing. Yeah, no, right. Like Ruby.wasm in particular was really hard with that because like it's this black box Wasm environment. And I would like, I don't know, I'd run a line of code, it would spit back this error that made no sense. Like, what do you mean? I'm not, I wasn't even awaiting anything. Why are you telling me that you can't await something? Anyway, so like the non-debuggability of it was really a factor. And one of the things that I love about Live Component is that there isn't that same sort of complexity at play. I mean, there obviously is more than you would normally be getting with like a regular Rails app that's just using hotwire and stimulus. But because it uses hotwire and stimulus behind the scenes, like if you're familiar with debugging those things, then you're gonna be right at home using Live Component. It's using the same mechanisms under the hood. You can also like pop open your developer tools, the network tab, you can see what it's actually sending and receiving from the back end. So hopefully that is gonna be familiar to most Rails devs. Where things might get a little more complicated is just in that re-render loop. If the database is getting hit for some reason and you didn't mean for it to get hit, or if something's getting serialized and then not deserialized correctly, like those things can be challenging because all those serializers live like in the live component gem. They're not, I mean, you can write your own, of course, too, but you might not be able to see what's going on behind the scenes there. So there could be some challenges there. I personally have not run into those because you can usually like just set a breakpoint like in your components initializer and you can see what you're getting back and then determine. Hopefully, from there, it's enough information to determine like what went wrong. One thing that I have wanted to add and have not added yet is like an error page. Because right now, if you click on a button and it goes to the server to re-render a component, but like an error happens in that, like on the back of like some Rails error gets thrown or something, or you're referencing a local variable that doesn't exist or whatever, then that error it comes back to you, but you can't see it on the page. You can only see it if you've got your developer tools open. And if you click on like that one network tab, it'll show you like a Puma rendered error, which is literally just a text. It's just like a the error message in a stack trace, like that's it, right? You don't get any special Chrome or anything. And so what I was thinking was it'd be super nice to have like what React does in this case, which is or some flavors of React, like Storybook will do this, where it will like pop open like an overlay over the top of your page and say, here's the error, and here's the stack trace, and like here's where you should go to to debug it, right? So hopefully you can add that at some point. Yeah, I'm hoping that generally speaking, the debug experience is pretty straightforward for most Rails devs.
SPEAKER_01:Going through the docs, it's like all these questions I wanted to ask and things. I tried to keep it so like, all right, we'll talk about debugging. We're talking, but like the one potentially deep question that isn't super high level that you will only understand if you've read the docs. So I'm sorry, listeners who I might be confusing with this, but so you have two life cycle hooks before update and after update. And as a Rails developer, any kind of life cycle hook in anything kind of is like, all right, what are the foot guns? How can I shoot myself in the foot with these? Like, what is your expected use of those? And what are ways that you already can envision someone abusing those hooks?
SPEAKER_00:I think in live component, right? I mean, there is an initializer because stimulus controllers have initializers, or at least they have a connect function, I think it is. But it's not the same initializer that you would have in Ruby. Like it's not passing in props, right? And this is also different than the way React would work. Like React, you would have you define a function that's your component, and you'd receive your props in that in the functions argument list. And in Ruby, that's the same way that you would do things. You get the argument list. But in on the JavaScript side, you don't get that argument list. And the reason for that is because the state object contains those arguments, and that state object is serialized as like a giant JSON object, like attached to a data property on the web component that live component renders on the back end. And so when that component gets instantiated, we have to go fetch that object and parse it. And then we have to propagate that state. Oh, something I should have mentioned, by the way, we were mentioning like performance issues is you know, a live component contains its own state, but it also contains the state for all of its children. And when it renders, it passes that state down to each child. And the state, of course, it like shaves off bits of the state like as it goes down, because some of that state pertains to the parent, some pertains to the child, and it just keeps propying that state down. That happens every time it renders from the server, it kind of has to. Anyway, so that's just to say that that state object has to get parsed and propagate the state has get propagated down. And the when that state gets propagated, there is like that's when the lifecycle hooks get called. So it gets called during that propagation step. And so those two hooks are sort of designed to be like the initializer in a sense. Okay. If you need to do something when state updates, that you would put that code inside either before or after update. So yeah, they're designed as like sort of before and after initialize. So the things that I use them for in my own code is to set up derived state that I can only really get from the browser. Like if I need to call a third-party API or whatever, or I need to call a, I'm gonna forget the exact the specifics of where I use this because it's been long enough. I know that Crosswise, you can look at the code for that, by the way, it's on GitHub. Crosswise does this a couple of times where it needs to hold on to certain state. And so it does that in, I think a before, before update callback. Yeah, hopefully that answers your question. I think that like two, being that this is a new project that people haven't used that much, including myself. I mean, I've built several things with it to like flesh out how it should look, but you know, it still hasn't seen that many real-world use cases. And so I wonder like, are there probably will be opportunities to add either additional hooks or modify the ones that exist? But to be clear, that you asked like what are some of the foot guns? If you are doing a lot of work in those methods, like something that's maybe compute intensive in your browser, that will slow down the entire rendering process. So you do need to be careful to not do too much in those, I think.
SPEAKER_01:Okay, that makes sense. Yeah. Yeah, I have so many other ridiculous questions and like rabbit holes we could go down, but like gotta keep moving. Because I do have another question to ask, and it's about blockers, which I feel like could be a good one here. Although, I mean, I could almost guess that one of the blockers is like, hey, this hasn't had a ton of adoption yet. So you don't have a ton of users outside of the person who wrote the thing. So you need that kind of traction. But like, what is another type of blocker, whether it be something that's blocking you on now, or I was blocked by X and this is how I solved it, or blockers around not the use of, but the building of Live Component.
SPEAKER_00:A big blocker that I had recently, I was working on the Snake game that's was actually for my daughter. She was like trying to find a good snake game for her iPad, and like they were all like full of ads and like way too complicated. We just like wanted the original like Nokia version. Yeah, sure. And she actually she has this little like camera that she got from her grandparents, and the camera has like Snake on it, but like we don't want her staring at that all the time, and like it would be nice if it was a bigger screen. And so I was building the snake game on crosswise.rock. So you can go there, like I think right now and say slash snakes or whatever, and you can play the game. But the problem that I ran into when I deployed that to production was that like you would click the button to like make the snake go, like turn a particular direction. And because of that hundred millisecond latency, if you did that too early or too late, it would not do what you wanted it to do. And the first time that she played, she's only six. So the first time she played that game, she got super frustrated and like tried to like I don't think she threw her iPad, but she was like, Dad, this is not working. And I was like, Oh my gosh, she's right. This is terrible. And so I had to go in and figure out how to make it more consistent.
SPEAKER_02:Yeah.
SPEAKER_00:This is actually a really interesting, I think, use case. Because if I had done this with React, I would never have had these problems because the page re-refreshes would re-render much more quickly. But because there's a hundred millisecond latency and there's a timer involved, because the snake has to move on a timer as well as the result of your clicking the directional arrows, there was a race condition essentially in like if I click the button, but like we're already in the middle of a render cycle. Like if I'm the timer has already fired, but the page hasn't updated yet. And so I think I still have time to click a direction arrow. And I click that direction arrow, the way that live component works, there's like a task queue built into it. So anytime that you take an action that requires a re-render, it enqueues that task. And these are all async tasks. And so I don't want them to run at the same time because one could overwrite the other depending on how the server receives them, right? And so they're all queued behind each other. And we guarantee that we process the one that was fired first before the one that was fired second. And so what you were getting was like the timer one would enqueue, and then the click one would in queue, and the timer one would go first, and then the button one would go next. And what that would result in was like the snake advancing potentially into the wall when you already clicked the no go to the right button. Yeah. Right. So you would lose. And it was confusing because you thought, oh, I've got enough time. I've still got what half a second to click the button, but then you actually didn't because the anyway. So that was where the confusion came from. And so that was a blocker for a while because I was trying to give this to her as like a Christmas present. Sure. I think that's the first version was like on Christmas Day. I like pull her iPad out and go to the site, like, okay, try this. And she's like, it sucks. I'm like trying to figure it out.
SPEAKER_01:And real world user feedback. It sucks. Thank you.
SPEAKER_00:That's funny. The blocker was that sort of in a nutshell. And so the solution that I came up with was because I didn't know what to do initially. I was like, this is kind of a crazy problem. Like, and I don't think this is a problem that most people are gonna have because most people are hopefully not gonna write games with live components. The reason that I wrote games with it because I wanted to like really push like the boundaries of how real time it could be, right? And so the fix I ended up doing was it was adding a flag to the render process where you could say like preempt true. And if preempt is true, then any tasks that are currently in the queue get cleared out when the next one comes in. So what that meant was we when you click the button, that would clear out the timer in queued one and just process the button one, and that pretty much solved the problem.
SPEAKER_01:As you were describing it, I'm like, I don't know if game building was the use case I was envisioning for live components. But that is like I liked how you were like the reason why you were doing it was to see how much you could push the real time because 100 sub 100 milliseconds is pretty damn fast. Yeah, but it is cool. Like you have that experience. This isn't what you would use it for in production, but because you're doing it, you've kind of uncovered this. If you really need this action to supersede everything else, now you have a mechanism for doing that. And I think that's right, probably what you'll end up getting a lot of feature-wise when other people start to use it and use it in ways that you weren't even necessarily anticipating someone using live. Like there might be, hey, I want a feature for this, and it's like, yeah, that's not what we built this for. It's not really how you should be using it. But there's also tons of use cases where it's like, huh, that's a use case I hadn't anticipated. What's a good way to fit into the spirit of live component of feature that allows you to do this?
SPEAKER_00:For sure. I mean, I do anticipate that there will be like some other like timing related problems with the library, depending on what you're trying to do with it, just because that's not really my area of expertise. Like, I'm not Concurrent distributed systems programmer for the most part. Sure. But hopefully most of the of the con edge cases are covered. That's awesome.
SPEAKER_01:So the last question is always my favorite. And I feel like live component as a whole could have been the answer to this question. But you've already used it, so you can't answer with live component. What is something cool, new, or interesting that you've recently built or discovered or read or anything? Like what's something that you're I just want to share?
SPEAKER_00:Okay. You've talked about hockey, I think, on this podcast a few times. Yeah, a couple of times. I just have to shout out the Seattle Seahawks right now.
SPEAKER_01:And that's not a hockey team for anyone who doesn't follow sports for the record.
SPEAKER_00:No, sorry. It's just a sports, it's a sports team. It's along the same lines as the hockey in terms of the sports angle. But yeah, no, I'm a big Seahawks fan, have been for a long time, and just impressed with their current run in the playoffs. So go Seahawks. Hopefully they can beat the Rams this weekend and against the Super Bowl. We'll see. And sorry about the Eagles.
SPEAKER_01:I mean, I don't see, I'm not a big football guy. So like my brother and sister-in-law are huge Eagles fans. So like we have a meme chat where everybody dumps memes every other day, whatever. And for at least three days, it was all crying Eagles something, like someone in pasting Eagles players into some meme or whatever. But yeah, there was a bunch of people in the area very upset. I am a Flyers fan, so I'm just used to disappointment at this point. Okay. Um I haven't had the experience of like, oh, we were good for a few years there. Um I'm like every time we win a couple of games in a row, I'm like, hey, this is awesome. But yeah, it's might be our year.
SPEAKER_00:For the longest time, the Seahawks were not competitive, right? Like it was just lots of ups and downs, mostly downs, especially because the West Coast tends to kind of get overlooked a little bit for a lot of things, and sports teams being one of them. But the true mark of a fan is that you stick with them through all the good and bad times. And so big respect for the Flyers fan fandom there. Cause it's like it's just going to make it all the sweeter when they do put stand a cut, right? Yeah, it'll be great.
SPEAKER_01:It'll happen. I do think we've made some big front office changes, and I think it needs a few years to really settle in. We have a lot of prospects that are coming up. Our really good players are really young. So as they get more and more experience, I think there's a good future, but I'm also being cautiously optimistic because it's true. I've said that before and been very wrong.
SPEAKER_00:No, I know. It's so hard, it's impossible to predict. Yeah.
SPEAKER_01:Yeah, sports is crazy. I think the first year that the Eagles won the Super Bowl, like it was against the Patriots. We had our backup quarterback in. Yeah. No one expected them to win. And then it was like the flukiest, weirdest. I don't know what happened, but someone who wasn't the quarterback threw the ball and then the quarterback caught it, and it was crazy. Yeah. Yeah. And everyone lost their minds. And there was rioting in Philadelphia because our sports team won. Yeah. And for some reason, that's what we do. I do enjoy the Super Bowl. And I think it's universal of sports, like playoff sports and especially the championship. Like there is nothing better than that game. The worst is when you have if it's a series or if it's like the Super Bowl is a one game when it's like someone got in there by a complete fluke and they're not even competitive and it's complete blowout. Like, that's so disappointing.
SPEAKER_02:Yeah.
SPEAKER_01:I love seeing the best of the best, or like the representative of the best face off against the other representative of the best for this is peak football, basketball, baseball, hockey, whatever it is. So good. It's another level of intensity and energy.
SPEAKER_00:It's so true. And I in football, like you do get that sometimes. Sometimes you don't, though, because like it's always the AFC versus the NFC in the Super Bowl, the two different conferences. Yeah. And sometimes there are just better teams on like it's Lopsided. Sometimes the better teams are in the NFC, sometimes they're in the AFC. And so we at the Super Bowl, you don't really get the two best teams. You just get like the best team from one, and then like the best team from the other, which may not be the overall best. Sure. And I think that's kind of what happened Seahawks versus Broncos in 2013. Not that the Broncos were a bad team, they just were in the AFC, and so they were playing different caliber teams than the Seahawks were. And that's why it was such a blowout. This year, there are so many good teams on both sides that God knows what's going to happen. I mean, nobody can predict. All the pundits are like, well, I think it could be this team this week, and then the next week they're like, nope, I was wrong. It's gonna be this team. You know, nobody knows. So it's gonna be a good idea.
SPEAKER_01:And it's wild that one injury can change the entire landscape. Because totally that one injury, if it's a star player, oh no, what do we do now? But also those injuries can the person who replaces that person has the next man up mentality, which is you've I've seen it in so many different sporting events. It's like that next man up mentality can be huge, and otherwise a mediocre player can suddenly turn into a superstar just because they're like professional athletes have a different mentality in general too. It's it's wild. Yeah, it's really fun to watch.
SPEAKER_00:Yeah, super fun to watch, yeah, for sure.
SPEAKER_01:So yeah, good call out. Is there anything else while we're still chatting that you want to talk about, whether be live components or what you're doing at Cisco or what you've done at GitHub or well, really interesting block or I missed anything. The floor is yours if you want it.
SPEAKER_00:Let's see. I guess I'll just Cisco Meraki is great if you want to work there. I'm sure we have open roles, go check it out. And it's probably one of the only companies that's like hiring consistently these days. There's not always openings, but there there often are. So if you're looking for a Rails Ruby job, check out Cisco Meraki. Yeah.
unknown:Awesome.
SPEAKER_01:Yeah, and shout out to Alan and Fito. I love them. They're always spreading the good word about Cisco Meraki at all the conferences.
SPEAKER_00:So totally. They're awesome. I talk to them frequently. The other thing I might want to say is that the I'm also one of the co-organizers of the SF Ruby meetup. If you are in the area, we actually it's to as we record this, the next meetup is today.
SPEAKER_01:Is it always the second to last Thursday? Or is there a little variable? How often it's pretty variable.
SPEAKER_00:You can go to like our Luma, so Lou.ma lu.ma slash SF dash Ruby, and that's our our main page that talks about all the upcoming meetups and stuff. We're having one actually at Cisco Marocki in March. Cool.
SPEAKER_01:Check it out. Very cool. SF Ruby looks awesome. If I find myself in the San Francisco area, I am going to hopefully time it so that I can make one of those meetups because it they look awesome.
SPEAKER_00:Yeah, thank you.
SPEAKER_01:So great. Yeah. Shout out to SF Ruby and awesome. So thank Cameron, thanks for coming on and talking about all the cool stuff going on with Live Component. Seems like a really interesting project. I'm excited to use it, if not at work, on side projects and just tinker with it because that's always fun when you've discover something new and you get to play with it. So yeah, for sure.
SPEAKER_00:So well, thanks so much for having me on. Super fun. And took a long time out of your day. I really appreciate it.
SPEAKER_01:No worries. It's hey, it's if we're talking about something cool and interesting, I don't mind at all. Where can people find you on the internet if they want to learn more about live component or just follow you and your work?
SPEAKER_00:You can go to livecomponent.org. There's no hyphens or spaces, it's just live component.org. That's the doc site. You can go to github.com slash live component. Again, no spaces or dashes or underscores. And then I am available on GitHub at github.com slash camera tron, c A M E R T R O N. I'm also on Mastodon at Camratron at Ruby.social. I think that's it. Awesome.
SPEAKER_01:I'll put all the links in the bottom so it's real easy for people to track you down. And thanks again for coming on. Listeners, I will see you in the next one. Bye.
Podcasts we love
Check out these other fine podcasts recommended by us, not an algorithm.
Remote Ruby
Chris Oliver, Andrew Mason, David Hill
The Ruby on Rails Podcast
Elise Shaffer
Ruby for All
Andrew Mason & Julie J
IndieRails
Jess Brown & Jeremy Smith
The Bike Shed
thoughtbot
Code with Jason
Jason Swett