AJ_O’NEAL: Yo, yo, yo, coming at you live from the fish tank.
CHARLES MAX_WOOD: Dan Shapir.
DAN_SHAPPIR: Hello from an Israel unbelievably still at war.
CHARLES MAX_WOOD: I'm Charles Maxwood from Top End Devs. And this week we're talking to Sam Selikoff. Sam, do you want to introduce yourself, let people know who you are and why we all love you so much?
Hey folks, this is Charles Maxwood. I've been talking to a bunch of people that want to update their resume and find a better job and I figure, well, why not just share my resume? So if you go to topendevs.com slash resume, enter your name and email address, then you'll get a copy of the resume that I use, that I've used through freelancing through most of my career as I've kind of refined it and tweaked it to get me the jobs that I want. Like I said, topendevs.com slash resume will get you that. And you can just kind of use the formatting. It comes in Word and Pages, Formats, and you can just fill it in from there.
DAN_SHAPPIR: Started in Perl and lived to tell about it.
SAM_SELIKOFF: There you go. I have blessed a referent in order to get an object in Perl.
CHARLES MAX_WOOD: I jumped on just to see, and we had you on what? Back in 2019 to talk about Ember Octane.
CHARLES MAX_WOOD: A good deal.
DAN_SHAPPIR: Yeah, we're all old, old guys.
SAM_SELIKOFF: I've got the gray hairs in my beard to prove it.
CHARLES MAX_WOOD: So yeah, when I grow mine out, my wife's always like,
DAN_SHAPPIR: I think those, those of you have hair basically just shut up.
CHARLES MAX_WOOD: Oh yeah. I shaved mine off because it's embarrassing, embarrassingly sparse.
SAM_SELIKOFF: I think it would have been like 2013.
DAN_SHAPPIR: How about you, Ajay?
AJ_O’NEAL: Um. I'm going to go probably closer to 2008, 2009.
DAN_SHAPPIR: And you, Chuck.
DAN_SHAPPIR: No, but did that count? That counts.
CHARLES MAX_WOOD: So it was probably 96, 97, but like getting into actual programming with actual, you know, where I was running against maybe a prototype JS or jQuery. That was probably 06. 05, 06.
DAN_SHAPPIR: So I wrote a large scale front, you know, single page application as it were back in 97, 98.
SAM_SELIKOFF: That's bad ass.
CHARLES MAX_WOOD: Yeah.
DAN_SHAPPIR: Offline first, by the way.
SAM_SELIKOFF: Wow. There you go.
DAN_SHAPPIR: Should have been impossible. Kind of was.
SAM_SELIKOFF: No fat arrow functions back then, eh?
DAN_SHAPPIR: Nah. No closures. No try and catch.
SAM_SELIKOFF: No closures?
DAN_SHAPPIR: No try and catch.
DAN_SHAPPIR: If you wanted to catch an error, that, you know, you had window on error.
SAM_SELIKOFF: There you go. Nice, nice.
CHARLES MAX_WOOD: I do everything I can to avoid writing try and catch, but. Yeah, crazy. That's crazy. Yeah. All right. Well, should we dive into our topic here? It sounds like there's a bit of a backstory here to Sam. You reached out to us. There's some been some back and forth on Twitter. Do you kind of want to set the scene for us and then we can kind of fill in the gaps?
SAM_SELIKOFF: Absolutely. Yeah. So you guys had a podcast. It looks like it was November 14th. It was called RPC resurgence from client-server applications to next. Next. Just frameworks. And I think it was you three talking about it actually. And you guys mentioned the slide from my talk that got turned kind of into a meme, but you were talking about server components and server actions and the new React features that kind of have been trickling out over the last year or so. And it was a really good conversation. And there was just some stuff in there that I thought would be fun to dive into a little bit more. And yeah, just unpack. So that was kind of the backstory. And I guess that if we wanted to kick it off, Dan was talking about, had a really good kind of survey of like the history of RPC. Maybe it was when you were writing that SPA in 97.
SAM_SELIKOFF: But you know, and then you also, I had a tweet about my slide and about server actions. And you had kind of replied saying like we used to do this and we chose not to. So it's there and there was a reason we chose not to. So maybe that is one way we could kick off the conversation. Basically, our server actions, just RPC, are they the same thing? And if so, then why should we not or why should we not do them or do them? And if not, how are they different? So that's kind of.
DAN_SHAPPIR: Syntax, exactly. For over-the-wire communication you're performing an operation that looks like a function call, you're sending parameters like you would into a regular function and you're getting a return value like you would from a function, but it's actually being sent over the wire, and it's type safe and whatnot. That's exactly what RPC is and that's what we're bringing back. But at the same time, there are some really notable differences because back in the day, if you looked at systems that did this thing back in the 90s, and even more modern systems like gRPC, it's also about being able to communicate between different programming languages and different architectures. Whereas RPC that we're seeing in the context of React lives and exists because everything is like this React app and it's just trying to abstract the way the concept of some stuff running on the client and some stuff running on the server. But it's not as a means of communicating between separate systems and even separate programming languages, it's more of the concept of doing everything within that same React app, using TypeScript all the way up and down. So there are some like key differences here as well. So, I found that really interesting to see both the similarities and distinctions. But I think I might be pulling us forward maybe too quickly. Maybe it's worthwhile to talk again a little bit about what there was in your slide and why you think that maybe people got so hot and bothered about it.
SAM_SELIKOFF: Yeah, so the slide was showing a server action where you clicked create a bookmark and write in your components JSX. It basically had an on click and then the event handler had the use server directive which meant that that code ran on the server and it used the SQL with a template tag literal to insert a new bookmark into the database. And folks, there was a couple of things that kind of sparked it off. One was it looking like an SQL injection vector, which it wasn't because template tags and the SQL function sanitized that. But setting that aside, it was more about the separation of concerns or the lack of separation of concerns from the perspective of those folks. And that's kind of what got the conversation going. So it was kind of like showing, normally you have a button and like you were saying, the the form or the button can make a post request to an API endpoint over the network. And there's a separation there. It's like the front end calls the backend logic and then the backend can be written in any programming language. And it can be using Ruby on Rails or LayerVal or Node server. And there's a nice separation here. And we are used to thinking about front-end and back-end development separately because they have different constraints, they're in different environments, they have different responsibilities, that's a good thing. And so putting all these things together, maybe is not the best idea. So that's kind of the argument and the criticism with the demo.
CHARLES MAX_WOOD: So, yeah. I was just going to jump in and say a lot of people that I've talked to when they talk about separation of concerns in some of these same ways, they try and bring up the single responsibility principle from solid and effectively say, yeah, so we don't want to mix all this stuff together. But I've talked to Bob Martin actually quite a bit. And when he talks about the single responsibility principle, it's you want to put the code together that's likely to change together.
CHARLES MAX_WOOD: I think it's interesting because I think you just illustrated what is it, Conway's Law, where the structure of the code reflects the structure of the team.
CHARLES MAX_WOOD: I'm gonna agree with you on this. I think people don't talk about agile development anymore, but this was one of the ideas that came out of some of the different agile methodologies was that, you know, you get together every so often and have a retrospective where you talk about what's working for you and what's not. And at that point, yeah, you can say, look, we're going to keep using JSX because it solves these problems for us. And we're going to adjust our team structure or our team responsibilities or educate people who work with us or whatever to handle the other piece. Right. And so then, yeah, maybe you teach your designers, look, this is how components go together. And so if you need to adjust styles, you're going to have to look in one of these places. Right. But this is how we've structured the the components that have an area of control. And so it should be relatively easy for you to figure out which component you're tweaking and then you can go and edit JSX.
DAN_SHAPPIR: By the way, I wanted to say that for me, the component model that you talked about works best in React when it's coupled with the unidirectional data flow. When you're when the data flows properly, then components really work. When it doesn't, it can become a hot mess.
SAM_SELIKOFF: Yeah, I think that's definitely aligned with the overall React philosophy. I mean, especially when it came on the scene, it talked a lot, they talked a lot about one-way data flow because the prevailing frameworks at the time used two-way bindings to try to get a lot of things done. So you just drop an input in, you bind it to a model, you know, Ember was like this, Angular was like this.
DAN_SHAPPIR: By the way, do you remember that back when React came out, it actually had two-way data binding just to be on par with the other frameworks? It kind of had that mechanism built in, and then it kind of, you know, fell by the wayside over the years.
SAM_SELIKOFF: I don't remember that actually. I, what was the syntax for that?
DAN_SHAPPIR: I'm trying to remember. I'll find it. I'll try to Google it while we talk about the other stuff, but you could actually, you could actually bind the field to, to a state.
CHARLES MAX_WOOD: That was an Angular's big selling point and they were kind of the big dog before react, so I can see why they did that.
SAM_SELIKOFF: Yep.And you know, that was it, it was, it was nice. Um, that the framework was able to keep your UI in sync with your state. But as it got more complex and app got more complex and there was two way bindings happening in lots of places that were triggering effects or other running other functions as a result of a change, it was hard to follow. So one way data, one way data flow, I think is, is a core principle of, of react. It's one of those like unwritten rules that you really need to understand and follow if you're going to be successful. And interestingly,One way to think about server components and server actions is that it's bringing that one way data flow to the whole app across the network. That's actually how a lot of the core team has talked about it.
DAN_SHAPPIR: And so going back to the slide that you showed, so we talked about like the two reasons that people were kind of I wouldn't say upset. Well, maybe some of that triggered. That's the best word. So one, like you said, was SQL injection. And we already spoke about why that wasn't really a concern, because it looks like an SQL string. But in actuality, it's actually a function call. So it can actually sanitize that string before it actually uses it. And that overcomes that issue, because it's a templated string literal. But I think the bigger issue was the mixing of concerns. And I think people say, okay, like you said, I'm encapsulating the relevant logic in the same component like this. But how do I now overcome the fact that I've got my SQL code spread all over the application? And if I ever need to change anything in the structure of my data layer that I basically need to go throughout my entire UI layer and fix it all up.
CHARLES MAX_WOOD: I think Redwood JS uses Prisma that way.
SAM_SELIKOFF: Yep. Basically, however you're writing your API endpoints today that your SPA is already hitting, whatever logic's in there is just, it's gonna be the same exact logic that you can now put inside of the component with the server action. So again, it's not about- It's not about making an argument about where your boundaries should or shouldn't be. It's about enabling the co-location of code that changes together in a way that we couldn't before.
DAN_SHAPPIR: The way that I like to think about it is basically saying that at the leaf node, let's say, of the component tree, you've got some client-side interactive component, and it captures some event and then it invokes a function that was probably passed to it as a prop. So it effectively now bubbles up that interaction. Now, in the past, at some point you needed to explicitly send that across the wire into somewhere which wasn't react anymore. Now, it bubbles all the way up to some component that actually does access the data. And somewhere along the lines of that bubbling, it crosses the network divide. You don't necessarily need to think about it as explicitly as you did before. It feels like it's functions all the way up. It's just that at one point or another, that function is an RPC function that effectively sent the data over the wire. But it feels like it looks and feels like a regular function.
SAM_SELIKOFF: Yeah. I think...Part of it is the ergonomics, which is what you guys talked a lot about in the last episode, because you can import a function and React can take care of serializing the arguments across the wire and deserializing them and giving you type information about that and errors, as opposed to what we have to do today, right? Which is just write fetch, put in a string to a URL and then pass along the data in the request body. That's a very error-prone process in a lot of ways. If you were to give me a React SPA and ask me to show you all the ways that all of the user flows that that SPA can make network requests, it would be hard. I'd have to search for a fetch or whatever abstraction around fetch exists. I'd have to look at the URLs that are hit and the data that is collected because Data has to be serialized across the wire and everyone's kind of doing it their own way. Whereas a nice benefit from server actions is that, especially because if you're writing TypeScript, that they're traceable just like any other module is. So if we were looking at your SPA and you were using Radix dropdown, from Radix, a UI library, and I asked you to find all the places you're using that we could just do that very easily because we can just look at the module import graph. And so now you can do that as well for, it's kind of like what you're saying, the RPC calls have become first class modules in effect, and they take part in the module graph. So that's a nice DX win. And it just takes a lot of the work off of our hands in terms of how we are gonna go about serializing things. There's kind of a standard now with form data and action in React and it just takes a lot of the work off. But I don't think that that's the most important part of this. I do not think it's about DX. And it's not about eliminating some of that boilerplate. It actually is about bringing those back-end pieces of functionality to inside of the component boundary.
Hey, have you heard about our book club? I keep hearing from people who have heard about the book club. I'd love to see you there this month. We are talking about Docker deep dive. That's the book we're reading. It's by Nigel Poulsen. And we're gonna be talking about all things Docker, just how it works, how to set it up on your machine, how to go about taking advantage of all the things it offers and using it as a dev tool to make sure that what you're running in production mirrors what you're running on your machine. And it's just one of those tools a lot of people use. We're really looking forward to diving into it. That's February and March. In April and May, we're going to be doing the Pragmatic Programmer. And we're going to be talking about all of the kinds of things that you should be doing in order to further your career according to that book. Now, of course, I have my own methodology for these kinds of things, but we're going to be able to dovetail a lot of them because a lot of the ideas really mesh really nicely. So if you're looking for ways to advance your career, you're looking to learn some skills that are going to get you ahead in your career, then definitely come join the book club. You can sign up at topendevs.com slash book club.
DAN_SHAPPIR: So, and I took it a step further and saying, yes, it's part of the component boundary and it's also part of that unidirectional data flow. It's the data flowing from React Server components down into client components as props and it's events bubbling up from client components to server side operations where the data is actually persisted as function calls.
SAM_SELIKOFF: That's one way you could use it, is if you did have a running node server, then you could have that kind of BFF model where your React components can interact with other server-side services at runtime because you're running it. You can also use them at build time. And we can talk about that, but I think runtime is the more interesting idea. And maybe one way to think about this is think about integrating something like Stripe checkout into your app. So let's just take Stripe, right? It lets you charge your customers money for your products. Let's say I have a PHP app. How do I integrate Stripe with my PHP app that renders a React front end. Let's say I have a Create React app. Well, they're gonna give me like a Stripe Checkout React component that renders the front end. And then I need to import and use their SDKs in my PHP app so that when my React front end, their component, their checkout component can talk to my PHP server, which can then interact with Stripe's APIs, right? Because we put that kind of logic web hooks and all the logic that needs to go between our trusted server and Stripes as a service, right, with all the secret keys there, that needs to run on our servers. So point being, if you were going to add Stripe checkout to your site, there's a client-side component and a server-side component. There's a client-side aspect and a server-side aspect to getting a full integration, a full stack integration with a service like Stripe. And the cool thing about. Server components and server actions is that you can imagine a world where that Stripe checkout component, uh, can include the server-side logic. And now you can just render it. It's going to do the same thing and talk to your trusted server, but the logic for integrating it, the surface area of that is much, much smaller. Maybe you just give it an environment key and it's on your trusted servers. So that's safe. But now the back-and-forth communication, the error handling, it's not left up to you to do that, to make fetch calls or to wire up a new endpoint to do that. They can bundle it inside. And then, yes, if you have the capability to run Node at request time, you could do certain levels of this. But even if you only could do it at build time, libraries could ship a lot more of the logic by including that server-side piece. So that's kind of one way I think about this is that most libraries, integrating with services is a great use case for this. And today to integrate with a service, we have to have a front-end piece and a back-end piece. The front-end piece is really easy to use because React now has all the primitives on the client to let us do things like just render a Stripe checkout. And that Stripe checkout component, that React component, is gonna do all sorts of things in our browser, right? It can render dropdowns that the user can use to choose their credit card. It can use any browser API it wants to set up the UI, but React has all the primitives needed for Stripe to be able to bundle those things inside of the component boundary, right? Because of use effect and use state, they can access the entire array of browser APIs and encapsulate that within the component. But we don't have a similar tool for the server. There's no way to encapsulate arbitrary server-side code inside of a component. But now with server actions and server components, there is. So companies, services, and even teams can start to bundle that in the same easy-to-use component interface. And the way to think about this is like it's a missing primitive that enables more powerful components in the same way use effect and use state were missing primitives that have enabled richer client components
DAN_SHAPPIR: bundle it and also compose it. One of the things I really liked in your talk, which I highly recommend people watch if they haven't for some reason is how you highlighted the fact that with server components, before you even got into server actions, you highlighted the fact that with server components, you can actually, because they're components,
SAM_SELIKOFF: I'm interleaved client.
DAN_SHAPPIR: Yeah, exactly. Yeah. Compose them together.
SAM_SELIKOFF: Yes. That's exactly what I was looking for. Yeah. And that's another really important point.
AJ_O’NEAL: I just don't have enough faith in humanity. I just don't think people are that smart. I just don't, you know, I don't, I don't think people are that smart.
DAN_SHAPPIR: But they don't need, but they don't need out and know they don't necessarily, but they don't necessarily need to be because if you. If you build the component interface correct, if Stripe did the work and build their component appropriately, and they should have the resources to do that, then effectively you're just dropping a Stripe component into your code. You don't need to know anything about what's it doing on the backend, what's it doing on the frontend because it's self-contained.
SAM_SELIKOFF: That's the goal. That's the dream. We are in an early stage. Obviously this is new technology. So right now, um, it's,
AJ_O’NEAL: we don't have a new technology. It's PHP. Like it's literally PHP. It's the exact same thing. We're gonna, we're gonna have, we're gonna render this and we're gonna render that and we're gonna have some of the, we're gonna have some of the server code in there and we're gonna have some of the client code in there.
DAN_SHAPPIR: Like, yeah, but with PHP you are, yeah, but with PHP you were wearing, but that's like the whole thing of object oriented, like, with PHP, you were wearing your underwear on the outside in the sense that all the interface that connected to the front end part, which was self-contained, to the backend, through your own code, was all out there in the open. All the end points, all the code that did the translation and stuff like that was not encapsulated. It was fully exposed.
SAM_SELIKOFF: Yeah, this is what you can't do with PHP. You can't render something that fetches data, a list of countries. Let's say you're doing a dropdown, you need to show all the countries, and the list of countries comes from your database. You render something that is a country list, and then inside of that, you render a dropdown component from a UI library, like radix, and you pass the countries from the country's component into the dropdown. And now you have a UI that is driven by dynamic data, but Radix is doing a dropdown that renders a portal and has virtual scrolling and keyboard shortcuts. So the way those things compose together is the novel aspect of this. And the way I think about what it will enable in the future is the same way I think about how React enabled libraries, UI libraries like Radix to exist today, because when React first came out. If you needed to render a dialogue, you might have to render the dialogue right here, but then in the root of your app, you might have to do something like, oh, we need a separate div, right? We need a separate div outside of our tree, because when we render the dialogue, it can't be inside of the content, it has to kind of portal out so that it lays on top of it. So there was two steps to rendering a dialogue. You could render it, but then when it was open, somehow you had to tell the root that it was open and then you had to hook into this sibling div that was outside of our application so that the dialogue showed on top. Then React came out with portals. Portals solved that problem. And so today, if you install a dialogue component from a library like Radix or React-
AJ_O’NEAL: No relation to the HTML portal spec.
SAM_SELIKOFF: Well, where does that come from?
SAM_SELIKOFF: Well, oh, is that a new spec that's coming or?
AJ_O’NEAL: Yes, yes. So it's unfortunate that they called it portals because there actually is a thing called portals that basically solve the single sign on and out cookies.
DAN_SHAPPIR: Is it still a thing though? Is it still a thing? I think the whole portal thing was kind of deprecated somewhere along the way. I'm not sure that they're coming up with it.
AJ_O’NEAL: But with passkeys it probably won't matter because I think the primary use case of portals would have been single sign-on and I think passkeys are going to be fine.
DAN_SHAPPIR: But I think we digressed.
AJ_O’NEAL: Yes, I'm just saying that it's not no relation to the portal spec.
SAM_SELIKOFF: Ah, okay, you're saying it's not related. Got you.
AJ_O’NEAL: What I'm saying is there's already a thing in HTML called a portal. We're not talking about portals.
SAM_SELIKOFF: Okay, got you. So there's a feature in React called portals, and basically every UI framework has something like this now that does let you render a div elsewhere in the tree. If you need to render it outside the tree of where you currently are, right? If you were toggling something and you show and hide a paragraph and it moves the page, that's like what you want, that's fine. But for things like dropdowns and dialogues, you want those to be able to render outside the current tree so that that UI element is on top conceptually in the Z index and it doesn't interfere with that, it sits on top of the existing content, right? And so there used to be a step to do that. So if I was an author of React modal library, I would say to use my modal library first, render capital M modal and put your content in there, but then also come here and render modal root alongside your body tag so that when the modal renders, it behaves like a well-behaved modal. It renders on top and none of the other contents of your page obscures it. But then React added portals as a feature to the library. It was a missing primitive which let you move that logic inside the component boundary. And so today, if you install something like RADX or React ARIA or Headless UI, you get to render a modal wherever you want. And behind the scenes within that component boundary, it's gonna set up a portal, it's gonna set up context, it's gonna set up effects that add keyboard listeners. All of the features of those UI components are contained in the component boundary. And using those components is the easiest part of working with React today, because you get to just render them. They're declarative. They take props and you can conditionally render them in JSX. It's like the most base. It's just like rendering HTML elements, right? Cause that's what it's based off of. But, but they contain all this functionality, all the browser APIs that they need inside of that component interface that makes them easy to use. So exactly like Dan was saying, you can imagine a world where a CMS like gives you a text field component. And text field, you can say, what's a prop? The prop, the model name is user, and the ID is 123, it's coming from the URL, and that's it. You just drop that into your app, and now it's gonna be able to read the data from Contentful on the server side, it'll populate it. As you type and make changes, you could hit save, and hitting save is gonna run a server action that's bundled inside of the component by Contentful and makes a write back to your CMS. And you didn't have to do that one two-step integration where to use Contentful, you know, text field first, import the React component, add it to your front end. And second, create a new API endpoint and integrate with our SDK on your server because all of it can be bundled in the component boundary. And it respects the data flow from your React tree. It can trigger re-renders it can pass a draft version of the content to other React components. That's the composition story that we never had in PHP. And that's the goal of what these new primitives enable.
DAN_SHAPPIR: So I've got two concerns. I'll start with the first one. The first one is the, and I mentioned these concerns, by the way, in that episode, when we spoke about RPC, my first concern is the proliferation of endpoints or, or API's. Like in the old days, because creating APIs was so explicit, we were very intentional about creating those API endpoints. And we tried to minimize their number simply because they were not that easy to create. And if we were doing things right, we used, let's say, RESTful APIs or maybe GraphQL, but let's stick with RESTful APIs, and we modeled them according to the structure of our data, and we use them that way. These days, an API is as easy as creating a function. It's likely that we're going to have a ton of internal APIs within our application, and they're going to be wholly distinct from you know, the external APIs that we create. So maybe nobody's actually checking that the external APIs still properly work because we're not using them anymore. And that's, you know, that kind of scares me, this cavalier approach to endpoint creation.
DAN_SHAPPIR: I agree with everything you said. I do think that I'm not sure frameworks can take us all the way. I think that best practices will need to evolve beyond what frameworks can and should enforce. Like maybe pulling the, like we said, I talked about the fact that, you know, the events bubble up and now with the server actions, they cross the wire somewhere along the way. Maybe you want to pull that point higher up within the component tree, like to the highest node that still has the appropriate context so that you kind of minimize the number of these kind of crossing points that you have.
SAM_SELIKOFF: But I guess basically what remix does remix hoists the actions and loaders to the route level. So if you want to know how your react app is interacting with the network, you only have to look at the route file. You don't have to worry about leaf components deep down.
DAN_SHAPPIR: Yeah, I totally get it. I actually think that React server components are intentionally not that. And the Stripe example that you gave before is a perfect example, because you can have the Stripe component dropped in within the page and the router doesn't need to know anything about it.
SAM_SELIKOFF: Yep, that's true. So it is true that if you are in a world of server components and server actions, part of the whole point is that any component can interact with the network. That's part of the benefit is that they're encapsulated inside of a component. And so yes, you could drop a Stripe checkout deep in the tree. And now it's making a network request that you don't that you didn't maybe intentionally, like you didn't opt into intentionally, I guess. But I still think there's a way for frameworks to kind of solve this problem. I see the possibility to create that Stripe component as something that React is trying to solve. And now we have the primitives for that to exist. And then the question of how best do we use these new powerful full stack components in a way that doesn't expose our apps to new security risks or keeps our apps maintainable. That's going to be something that we figure out and that we get advice from with frameworks and different opinions.
DAN_SHAPPIR: All I'm saying really is that it does make a lot of sense to tie the communication to the router in many cases, because at the end of the day, in a lot of cases, it is the the the navigation that's all about changing your state. But as we as you know that stripe example shows that's not always the case. It's not always the case, but it's a very powerful model, but it shouldn't be the exclusive model.
SAM_SELIKOFF: Yeah, and it's also not the exclusive one because another primitive that has recently come to react to suspense and suspense is all about coordinating things like data requests. So you can drop in your stripe checkout component and let's say it has to load data first before actually charging someone, like just to render, it requires data. It requires the current user, it requires your catalog of products and the prices. So you just drop that in and you say, well, isn't that bad because my route already loads this other data. Now I'm dropping in a Stripe component deep down in my tree and it's gonna do its own data fetching. How does that all work? This is where suspense comes in. Suspense lets the whole tree of components tell the parent, hey, I'm not ready yet. And so I have this network request or this one. You can hoist them, but basically suspense lets you keep those at a choke point, but still have the logic inside the component boundary so that you do get to do things like if a framework was to decide we only want to load data on URL change, they can do that without breaking the encapsulation of the fact that the Stripe checkout component knows what it needs from Stripe. I just know that it needs to rent to load data, but I don't know how it gets that. They can do that for me.
DAN_SHAPPIR: Yeah. And you don't want to be blocked on it is the most important aspect, I think, at the end of the day.
SAM_SELIKOFF: Well, sometimes you might, sometimes you might want to block on getting every data loading component to fetch its data before it renders. Sometimes it might be below the fold and you want to let it render lazily with the loading spinner. And again, suspense is the answer. That's the primitive that lets you have control over that. But but you still get the benefit of having the component have its own logic inside of the component boundary.
DAN_SHAPPIR: So one point that I did want to mention is like another as a final point on my end that's kind of related to RPC, which we've also brought up in that discussion. It wasn't a problem when RPC existed back in those days in the nineties. And it's also a problem with quote unquote RPC here within Server Actions, as far as I can tell and that's versioning, that you're tying the version of your clients to your server. Now, you might think, hey, that's not a problem. I mean, it's everything part of that single Next.js app, which I deploy as a whole. But you're not thinking about the situation where somebody keeps a client up and running while you're, let's say, updating the server version. So you can get even if it's like all a part of that single app, you can get into version mismatches between the client and server fairly easily with long-living client-side web apps.
SAM_SELIKOFF: Yes, and that's a problem that's existed, you know, since we started doing long-lived client development, right? If you have a route split Create React app, and you only load the first page, the person leaves it open for a day or two, and then they navigate, maybe they get a different version of the next chunk, or that chunk references a different version of something because there's been a deploy since then and they haven't refreshed. So I think that this comes up a lot with long-lived clients, but I think either React or Next has some built-in stuff. I think React has some built-in stuff to kind of fingerprint the version of the server action that a particular Client component may have gotten reference to. I'd have to look more into that, but.
DAN_SHAPPIR: Yeah, but then what do you do? It's definitely something they've written about. But then what do you do?
CHARLES MAX_WOOD: Is that like API versioning on your Rails app or PHP app?
SAM_SELIKOFF: Exactly, it's like that. You tell it.
CHARLES MAX_WOOD: You're using V1 in your path instead of V2 in your path.
DAN_SHAPPIR: Yeah, but like when you're doing RESTful APIs, you're cognizant of that. You're very explicit about it. Yeah, you know, and you can make sure to maintain backward compatibility at least one version back. It's pretty straightforward when you're doing everything with RPC and it's intentionally made to look like a function call. You know, you've added a parameter in the next version and it's suddenly incompatible.
SAM_SELIKOFF: So yeah, I do know that there's I'd have to look I don't know if the top my head I know that they have some solution to this and I think they've thought about it. But I don't know off the top of my head what it is, but I think it's, yeah, I'd have to look more into it. But that's definitely something that's-
AJ_O’NEAL: The good news here though, is that between the cookie banner and the subscribe banner and the did you want more content banner, the people are probably never gonna get to your site, so they'll probably never notice.
SAM_SELIKOFF: There you go.
CHARLES MAX_WOOD: Oh, all right. Well, if we're going here,
AJ_O’NEAL: it's just one more thing. It's just one more thing in the list of things that are going to go wrong on your site. Yeah.
CHARLES MAX_WOOD: All right. I'm going to push this to picks. Sam, if people want to follow you or check out build UI, what are all the links, URLs, et cetera?
SAM_SELIKOFF: Yeah. buildUI.com is our site where our courses we've got a Tailwind course, we've got a React A remix course, we really love building with remix. And Frame or Motion, which is a cool animation library. And this week we're putting out one on Radix, which is a UI component library. So, if you're into that, you can check that out. We have a newsletter, builddry.com slash newsletter. It's a nice way to keep up with what we're doing. And then I'm on Twitter. So, Sam Salikoff on Twitter.
CHARLES MAX_WOOD: Awesome. All right, well, let's go ahead and do our picks then. We'll put all those links in the show notes. And if you drop them in the little chat over here, we'll make sure they also wind up in the comments.
Hey, this is Charles Maxwood. I just wanted to talk really briefly about the Top End Devs membership and let you know what we've got coming up this month. So in February, we have a whole bunch of workshops that we're providing to members. You can go sign up at topendevs.com slash sign up. If you do, you're going to get access to our book club. We're reading Docker Deep Dive, and we're gonna be going into Docker and how to use it and things like that. We also have workshops on the following topics, and I'm just gonna dive in and talk about what they are real quick. First, it's how to negotiate a raise. I've talked to a lot of people that they're not necessarily keen on leaving their job, but at the same time, they also want to make more money. And so we're gonna talk about the different ways that you can approach talking to your boss or HR or whoever about getting that raise that you want and having it support the lifestyle you want. That one's gonna be on February 7th, February 9th, we're going to have a career freedom mastermind. Basically you show up, you talk about what's holding you back, what you dream about doing in your career, all of that kind of stuff, and then we're going to actually brainstorm together, you and whoever else is there and I, all of us are going to brainstorm on how you can get ahead. Um, the next week on the 14th, we're going to talk about how to grow from junior developer to senior developer, the kinds of things you need to be doing, how to do them, that kind of a thing. On the 16th, we're going to do a Visual Studio or VS Code tips and tricks. Um, on the 21st, we're going to talk about how to build a software course. And on the 23rd, we're going to talk about how to go freelance. And then finally on February 28th, we're going to talk about how to set up a YouTube channel. So those are the meetups that we're going to have along with the book club. And I hope to see you there. That's going to be at topendevs.com slash sign up.
CHARLES MAX_WOOD: AJ, what are your picks?
AJ_O’NEAL: So I had some last week that I didn't, first, okay, so first and foremost, I'm gonna pick this no backend. There was a movement called no backend that started, I don't know, 100 years ago, something like that, 2017 maybe. And I don't think that it has any chance of succeeding, but but it's kind of the idea of. If, if you just created standards for common actions, then you could have components for the backend that I mean, essentially kind of what we're saying, but it would be API, it would just be a well-standardized API. So that on your front end, you didn't have to be aware of the backend. So same kind of effect. You'd be able to install. A component for front end and back end. Um, for, for lots of different things and, and the person who put this site together, it has examples of like user accounts, generic data storage, emails, uh, permission sharing, file conversion, payments, et cetera. Well, the only other one on there was make coffee or tea, but that's kind of a joke because of the, the HTTP four 19. I am not a teapot. Um, but anyway, so that, that idea I really like the reason that I say it'll never take hold is in comparison to this, like RST type thing is that our entire foundation of the internet is built on money that doesn't exist. It's low-interest rate loans from the federal reserve that get pumped into investor money that get pumped into businesses that don't ever need to have a thought about being profitable that, you know, the only thing that they need to do is to grow. And as long as we have that, the proprietary nature of creating a payments API that only works with one provider is going to always trump over having a payments API that any provider could use. Because you're not trying to get profitability and then compete in a, in a free market. You're trying to take advantage of government regulation and, and investor, you know, hot potato to just create businesses that have growth and, and you want to trap in, you know, this one little niche thing, like what Stripe has done. You know, it's, it's funny. People, I mean, Stripe in particular, like they have way better documentation and way prettier pictures on their website. Other than that. How much they're worth. Huh? Oh, other than that, they kind of look like the other, you know, 15 different options that you can choose from. You know, it's like, you put in a credit card, you pass the rate, and then like, it's not, anyway. So, but I like this idea. This would be my dream, is that we use protocols rather than companies. Uh, and that it's a free and open market where the company that can provide the best is the one that wins rather than the one that is able to, uh, use investor money to create advertising hype, to, you know, create a proprietary API for something that should be relatively simple and open like messaging or, or file storage or whatever, but old man yelling at clouds, clouds aside, uh, there were a couple of things that I had to pick. One was home assistant, which I just mentioned last time because we were really running low on time, but home assistant is. You know, it's also bittersweet that it works at all is what's really cool about it is definitely not end user-friendly whatsoever. But if you are, you know, an IT guy or a programmer, you can probably get it set up and get it working. And it doesn't really matter whether you buy the box where it's pre-installed or not. It's it's basically like Apple HomeKit or Google Assistant or Alexa Home. It's that type of software. And in fact, it integrates with those things as well. So it can piggyback on those. If you happen to buy a device that doesn't have a way to have a local API or ZigBee or Z-Wave or any of the standards that have existed for home assistance and smart home stuff before the Google Assistant type of things kicked off. But anyway, I was able to get it working. I got it. It wasn't. It was, it took me a few hours to get my thermostat set up on a schedule, which is not, I mean, I guess it would take that long if I just bought a thermostat at Lowe's and then press the buttons on it, going through the, the schedule menu thing, but, um, anyway, it, it's, it, it works like you can have cameras. I've got a camera connected to it. That's using on VIF, which is the open video standard for security cameras. I've got a thermostat via Z wave. I'm going to get, um, a power device, uh, via Zigbee. And I think that that's probably going to be as easy to detect as Z-Way, but it's all event-based and the problem is that it's like, there's no modules for, you know, here's your thermostat module. Everything is if this, then that style. So your thermostat has an event like temperature change that it fires off and something can listen for that. And you can have a schedule system like a calendar, for example, and say, okay, like 9 a.m. is an event and what should the event do? Well, the event should trigger the thermostat to be set to 72 degrees. Or, you know, that sort of thing. So wiring it up is very tedious, but at the end of the day, it works at all, which is better than the alternative of not having any way to do any sort of smart automation in your home without having Google and Amazon listening to every conversation that you have and knowing when your lights are on and what your power bill is likely to be and all that stuff that, you know, can just kind of feel creepy. So I'll pick Home Assistant. There's a couple of different sites. One is Ameridroid. Another is cloud free. And those are sites that particularly sell things that are known to be compatible with Home Assistant and probably some of the other ones like Hubitat and whatnot. And then a lot of the stuff you can get on Amazon, but it's very difficult to do any sort of search on Amazon and actually know whether or not the thing is actually going to be compatible. Whereas if you use a Maradroid or cloud free, I mean, it's, you know, they're selling all of these DIY smart devices. You know that they're already pre-flashed with the right firmware or they're already, you know, they're already kind of set up so that you can start using them in your home with the different sensors and relays and whatnot. One of the things I'm going to do is get my garage door opener so that I can open it and I don't have to worry about some data leak happening and then anybody that gets the Amazon database being able to open my garage door or something like that. So yeah, kind of a love-hate relationship at this point. Love that it is allowing me to do things I couldn't otherwise do. Hate that it is extremely geared towards people that want to edit YAML files and do if this, then that. Just have a module for the thermostat. Or the garage door or whatever.
DAN_SHAPPIR: So do you have a Docker container for your thermostat?
AJ_O’NEAL: So it does that automatically. That's how it works. So you install Home Assistant, Home Assistant boots up the Docker container. So there probably is a Docker container for the Z-Wave module. I don't know exactly how it does it. I just put it in a virtual machine and then pass through the USB device to the virtual machine let it do its thing and it's working. And I have it segmented. So I have a separate network in my home that's an IoT network where any of the home devices like our laptops and phones can access the IoT network, but the IoT network can't go back and access anything else. So it's like even if I buy some weird device that has hacked firmware on it, I'm relatively safe. Now, obviously that's not something the average person's gonna do. And even as a programmer, you're not going to have any idea how to do that. Hey, better you than me. It's all I've got to say. But the thing is, one day, one day it'd be nice if we did have a box that could just do the stuff that's just plug and play. And some people have got to deal with this iteration of technology in order for us to get to that iteration of technology. Um, and then one other thing that I will pick today is Chaos walking. I did. I mentioned that I watched the movie. I don't know if I mentioned I watched the books are good. It is. Okay. Yeah. The books are good.
CHARLES MAX_WOOD: And the movie was you despair on the quality of the movie.
AJ_O’NEAL: It was just, it's a completely different story that happens to have a few of the same characters. So if you, for anybody that watched Jurassic park two and read Jurassic park two. It's like it's the same kind of thing, like completely different story. A couple of the same characters have the same names and a couple of the same catchphrases, but other than the first 30 seconds of the movie, which is exactly the same as the book, a boy walking through the woods, talking to himself. From that point forward, it's just a completely different story that, that has a few similar motifs in it. You know, like Jurassic Park 2 was a completely different story, but it was also a story about dinosaurs. So that's what I have to say about it. So yes, if you did not like the movie of Chaos Walking, I highly encourage you, but you liked the premise. Like the trailer was interesting, the movie was terrible. Take a look at the books because the books have a coherent story and it's really good and compelling. And it is nothing like the movie other than there is a May apprentice and there is a Viola and there is a Todd Hewitt and they have noise. So those will be my picks for the day.
CHARLES MAX_WOOD: All right. Dan, what are your picks?
DAN_SHAPPIR: Okay. So my first pick is going to be a series that I'm currently watching on Netflix, which is amazing. And it's called Blue-Eye Samurai. And if you've not watched it, you need to watch it. Now, it's an adult show. So there's some nudity and some sex and lots and lots of violence. But the artwork is amazing. The storytelling is excellent. I'm really enjoying it. So I highly recommend it. And it reminded me of another excellent show about samurais, which is surprisingly, which is really different but in some way surprisingly similar, which is that old show, Samurai Jack, from originally 20-something years ago and then with a few more episodes 12 years after that, which is also highly recommended if you can find it. But like I said, it's a totally different character of show. It's mostly intended for it's effectively, you know, a show for kids, but it's one of those shows for kids that adults enjoy more. But, but Blue-Eyes Samurai is definitely a show for adults, not for kids. So cool. Yeah, I highly recommend it. So those would be my picks for today.
CHARLES MAX_WOOD: All right. My picks are going to be a little bit heavy. So Sam, why don't you go ahead and go first?
SAM_SELIKOFF: I was going to say lessons in chemistry. A bunch of people were recommending it to me. It's an Apple TV plus show and it's really great. It's like a timepiece in the fifties, I guess. And that's about, yeah, chemistry and cooking. And it's just really well-made. So I've been enjoying that.
CHARLES MAX_WOOD: Cool.
DAN_SHAPPIR: We started watching it and then we let our Apple TV subscription, you know, and we didn't renew because I just, you know, I can't abide by the fact that, you know, you pay for a subscription, but then you also need to pay for the movies that you want to watch. So, you know, it's kind of annoying.
CHARLES MAX_WOOD: Well, the other thing is, is I think our, we quit paying our cable bill way back when, when it was like a hundred bucks. But I think we're already halfway to there with all of our streaming services. And so yeah, unless there's something really compelling to keep you there, you know, just pick the ones that have most of the stuff you want. Anyway. Um, so I'm going to get a little bit heavy. I'm going to get a little bit personal as well. Um, and, and I feel like I just want to talk about this for a minute, mostly so that. Um, if there's somebody in your life that you can help out, that you can do it. Um, and if my talking about self-harm or suicide will bother you. Then turn off the episode at this point. Um, so right before Christmas, my brother, he's 32 attempted to end his life. And, um, he, he bought himself a pistol and he wound up, um. He put the gun to his temple, but when he pulled the trigger, he, his hand moved forward and he shot his eyes instead of his brain. And so, you know, we still have him here is essentially what I'm saying. We kind of got lucky in that sense, but he's blind now. Um, and so a lot of the things that I've been talking about releasing, I haven't released because I've been dealing with family stuff for the last month. Um, that all said, what I really want to put forward is I've talked to, so I'm involved in several other things, right? And so I've had to explain to some people in other areas, hey, look, this is what's going on. And so this is why I've been in the place that I have been and why I haven't done everything that I wanted to do for you. And you know, everybody's been very understanding. But the thing that really surprised me was that a lot of people basically said my son or my brother or my parent or my family member, my friend attempted suicide. And and so it's, I'm finding that it's something that touches a lot more people than I thought. And, you know, you kind of hear the statistics, but it never really hit home to me as much that, you know, a lot of the people that I talked to have had experience with a friend or family member who has tried to end their life. And so a couple of things that I just want to put forward is, first of all, you know, my brother and I, I mean, we didn't have a bad relationship. We just didn't really ever talk all that often. And he was kind of a loner. And so, you know, that kind of happened. But for one, if you haven't talked to somebody in a while, if you have a relationship with somebody where you feel like or wish that it could be better, I mean, even if there's history there, right, because sometimes that's the way it is, just take a minute and reach out and let them know. And then the other thing is, is that what I'm finding, I actually went and talked to a therapist last week, you know, after I kind of got I set it up when I was really suffering and then, you know, I had kind of gone through most of my anger and frustration and things like that, which is why I haven't talked about it to this point, because it's just been really hard for me to think through and deal with. But I'm feeling a lot better now about things and, you know, just working toward how I can help him out. But a lot of people have that hole in their life, right? And I'm not going to tell you how you feel it. Um, I also haven't been that low in my life where I felt like I, you know, wanted to hurt myself. I also have a number of friends who have addiction issues and they, they tend to fill that same kind of hole with, with some kind of addiction, whether it's drugs or pornography or something else. Um, but just realize that a lot of people out there really are suffering and they're going through a lot of things and you need to figure out if you're feeling that hole how to fill it. And for me, I fill it with my family and my faith and things like that. And if you can't figure out how to fill it, then go talk to somebody, go talk to a professional. The other thing is, is that if you have a friend or family member that goes through something like this, just realize that it affects you too. And that if you need help, you should also go talk to a professional or go find a church leader or somebody that you can confide in and find that help because I can tell you, I have a couple of really close friends. We get together every Wednesday night and play board games. And we played board games basically the week after and just talked and it helped so much. Right. And they're not professionals and they weren't telling me, oh, you should really do whatever. Right. But yeah, if you're experiencing this kind of anger or frustration because somebody did something you know, whether it was personally directed at you, or you're just angry that, you know, they did something like what my brother did, go find somebody to talk to and go find that help.
DAN_SHAPPIR: Humans are social creatures. We need that human interaction. But I totally agree with what you said, that, you know, find somebody to talk to, but if you really need professional help, then, you know, go for it. Don't, you know, don't assume that just talking to a friend is a sufficient substitute.
CHARLES MAX_WOOD: Right, exactly. So, I mean, I don't know if I'm giving any specific or concrete way of knowing where you're at with some of this stuff. And a lot of times it's really hard to figure out and, you know, one day it's great and the next day it's not. But just be aware and, you know, look out for other people, the people you care about in your life and look out for yourself. I think that's all I really have to say about this, but It's just kind of been, it's something that I've really wanted to just tell people to just think about. All right, well, we'll go ahead and wrap it up there. Sorry to get all deep and...
SAM_SELIKOFF: No, thanks for sharing, man. I'm sorry you're going through that. That's rough. Yeah, I appreciate you sharing, man. That's... you're thinking about your family for sure.
CHARLES MAX_WOOD: Yeah, thanks. All right, well, we'll wrap it up here. Till next time, folks. Max out.