EPISODE 1824 [INTRODUCTION] [0:00:00] ANNOUNCER: Remix is a full-stack, open-source web framework that was developed by the creators of the popular React Router library. It focuses on features such as server-side rendering and efficient data loading, and it emphasizes developer experience. Ryan Florence is a co-creator of React Remix. In this episode, he speaks with Josh Goldberg about the Remix project. This episode is hosted by Josh Goldberg, an independent full-time open source developer. Josh works on projects in the TypeScript ecosystem, most notably TypeScript ESLint, the tooling that enables ESLint and Prettier to run on TypeScript code. Josh is also the author of the O'Reilly Learning TypeScript book, a Microsoft MVP for developer technologies, and a live code streamer on Twitch. Find Josh on Bluesky, Mastodon, Twitter, Twitch, YouTube, and .com as Joshua K. Goldberg. [INTERVIEW] [0:01:07] JG: With me today, back to the podcast, is Ryan Florence. Ryan, welcome to Software Engineering Daily. [0:01:12] RF: Thanks for having me. Excited to be here again. [0:01:14] JG: Yes, we've been looking back at your old interviews, and you've talked about a lot of really cool stuff on the show, and we're going to dive into a lot of cool stuff today. But before we get into the wonderful world of Remix, can you tell us a little bit about yourself and who you are? [0:01:27] RF: Sure. I'm Ryan Florence. I live in Utah, and I've been doing web stuff since the beginning of the web, really. My dad invested in an ISP when I was a teenager back in the mid-90s, then I started doing websites for customers of theirs. One of them was a plastic surgery before and after photos thing, and I was like a 16-year-old. That was not something I wanted to work on. Anyway, yes, I've been doing web stuff for a really long time. I remember when CSS was invented. I remember the JScript versus JavaScript thing with Internet Explorer, and Netscape, and, well, Mozilla before that. But anyway, and then more recently, what most people probably know me by is a React Router and after that, Remix. So I was a co-author of both of those, along with my career partner, Michael Jackson. He and I have been doing stuff together for over a decade now, so yes, love working with him. He's brilliant and just awesome person to work with. It's been fun working on all that stuff. That's what people might know me by, and I love playing guitar. Oh, you can't see it over there and just music generally. Same with Michael. That's why the Remix brand has so much music stuff with it, and snowboarding, and soccer, and raising kids. I got three of them. That's me. [0:02:49] JG: I just connected Remix as in river Remix. That's what the connection is? [0:02:53] RF: Yes. Yes, Remix. [0:02:55] JG: Amazing. Just curiosity, do you ever look back at all the advances in the web and feel some sense of positivity or optimism about how far it's gone since you started? [0:03:07] RF: Oh, man. That's sort of like looking at your teenagers, and sometimes you feel like, "Wow, we nailed it. We did such a good job raising these kids." There's other times you're like, "Where did I go wrong? What did we do to mess this child up so much?" The web definitely feels that way to me, where it's like sometimes it's just incredible. I mean, the fact like what we're doing right now in Riverside FM, we went to a website, right? We opened up a browser, the first browser that I ever used. The links was just in the terminal, and it just sent you text. It was hilarious. To where now I punch in Riverside FM slash whatever this idea is. Now, we're streaming, and uploading, and communicating in real-time with like, what, probably 20 milliseconds of lag between when I speak and when you hear it? That blows my mind. Yes, so it's incredible what we've done with the Internet and with browsers in particular that WebTech can do this. The financial models aren't there for a lot of the things. I think that's the thing that I lament the most is we got WebGL. You should be able to go to eldenring.com and start playing Elden Ring. We have technology in the browser that should make that possible, but we don't have that, I think, primarily because of financial models, where it's pretty much just ads. E-commerce is like the - what do they call it? That's the killer app of the web, right? E-commerce is the thing that I think the web is clearly the best at. You can just go and shop and buy stuff. But everything else, it's hard to just always do ads to make money. App lowered some stuff. [0:04:48] JG: You make a really coincidentally good segue. You mentioned that you co-authored Remix and React Router. Y'all were in some way acquired by Shopify. Could you tell what the actual thing that happened was? [0:05:02] RF: Yes, we were acquired by them. [0:05:04] JG: How does that work though for an open source project to now be owned or acquired by a company? [0:05:09] RF: I don't think it's different than others, except for we had no revenue. No, we actually did. We actually sold Remix at first. Our first model was selling licenses to use it. It was open source, but you had to pay to use it. So we actually did have some revenue. Yes, we had been building Remix. We raised some VC money. We're building the framework, and then always in the back of our head was like, "Well, then what's the business model?" At first, it was licenses, but we always knew that we're going to graduate past that and do something else. Do you build services on top of it? Do you do hosting next in Vercel? That's how most VCs thought of us. That's what they all wanted us to do was build a platform like Vercel on top of Remix. Anyway, so we had a bunch of ideas about what we were going to do. Then we saw that Shopify was building Hydrogen, which had a lot of overlap with what Remix was doing. Kent C. Dodds at the time was working with us, and he reached out to them and was like, "Hey, we have no particular thing we want to pitch you on or anything, but we're both building similar things on top of React. Let's talk." So we learned about Hydrogen. They learned about Remix. From there, it just eventually ended up with them saying, "Hey, how about instead of having to come up with a business model -" we raised some VC money, but that'll ran out. "Instead of worrying about your business model, how about you come and just build Remix at Shopify, and essentially Shopify funds the development of Remix?" And we just build it under their roof. It sounds really fun because, of course, it's fun to build products and stuff. But our heads were just in Remix for the most part, and that's what we wanted to work on. Or at least that's what I wanted to work on. Yes, so you sign some papers and make a deal, and then they send you a work laptop. [0:06:52] JG: And off you go. [0:06:54] RF: Yes, and off you go. [0:06:55] JG: How would you have described Remix let's say two years ago? Just know that the follow-up question is going to be how would you describe Remix in six months from now or a year from now? [0:07:04] RF: That made me just think about what are the differences now. But I think I would still describe it the very same way that I worded it on our website. I don't have it memorized. I'm going to go look at it. [0:07:14] JG: Focused on web standards. [0:07:14] RF: Yes. It says Remix is a full-stack web framework that lets you focus on the user interface and work back through web standards to deliver a fast, slick, and resilient user experience. I think that's how I described it four years ago. That's how I would have described it two years ago. I would describe it now as I would just say, instead of Remix, I would say React Router. [0:07:36] JG: Yes. Let's talk about that, actually. React Router, the router, or one of the big routers for React. [0:07:42] RF: Before we go there, I do want to talk about what changed after we got to Shopify with Remix. Remix was very much - I don't know if server-first is the word, but server-required. It always server-rendered. You always had a server. You always had to deploy either a Node, or a Cloudflare, or a Deno, or Bun server. We had the whole full-stack JavaScript thing going on. I always like to say center stack because some people when you say full stack think, "Where are your queues? Where's your database? Or where's all this stuff?" It's like, "Okay, we're center stack. We cross the gap, but then you get to do whatever you want on those sides." Anyway, it was very much started with a server. When we got to Shopify, there was a handful of things. They don't just build e-commerce with their framework Hydrogen on top of Remix, but they're using React Router everywhere. So React Router, when you log into your store, if you are a merchant, that's a React Router app. If you are in that admin interface, you can add what we just call apps, third-party apps where maybe someone can create a shipping tracker app that you can add to your Shopify store. Those are just like one-click installs for a merchant, and those apps are hosted on - they're built by whoever this app provider is. But then they're integrated into the admin interface so that a merchant has a really nice cohesive - it's sort of like an operating system for your store. Everything's right there. You don't have to go log into someone else's thing to work with your shipping stuff. You can just do it right there. Those third-party apps, we had some templates for people to use React Router. So this is kind of big push, like, "Hey, how can we adopt Remix in more places?" That actually pushed us to soften up the server requirement, and we brought a lot of the abstractions from Remix over into React Router directly so that you could do things like define your data for the page for your route, define the actions for a route. But instead of doing those things on the server, the way that we did in Remix initially, introduced these concepts of client loaders and client actions, and they would just run in the browser. Then we even got rid of the server requirement where it could just run as a full-blown SPA with no server or server rendering at all. That helped get a lot more Remix adoption too, where people are like, "I don't actually want to run a JavaScript server, but I do like the way that you organize code in Remix with loaders and actions and getting access to all those pending states when those things are pending, so you can build a nice user interface." That's the big difference that happened from before we got Shopify and then now is we really beefed up the flexibility of how to deploy a remix app. You don't have to have a server. [0:10:23] JG: Yes. I remember when the Static HTML features started going into - I think it was beta or however you call it. That was very exciting. There's been a lot of back and forth on the web over - traditionally, it was called MPAs, multi-page apps versus single-page apps, SPAs. Not the most helpful delineation these days. [0:10:42] RF: That's all fuzzy, but I think we all generally now agree on what we mean by SPA. [0:10:47] JG: Yes. Are there particular architectures that you think Remix is moving more towards or away from, or do you see like a next set of steps in Remix React Router's future for that? [0:10:57] RF: Let's go back to the, "What happened with React Router?" Then I think we can get to that question. Your questions, I'm always going to keep putting at the end of the stack, and then we'll pop them off. Yes. So all that work, we realized - the question you just asked me though is do I think that Remix has a specific architecture that it blends itself toward more than others. Is that kind of - [0:11:17] JG: Yes. I'm just curious your perspective on what are the right way or set of ways to work with Remix if there is such a set? [0:11:24] RF: Yes. Is that a cat tail I see walking back and forth? [0:11:28] JG: It is. He's a very needy cat. His name is Jim. [0:11:29] RF: Oh. Like, "What is that?" I was like, "Oh, that's a cat." Actually, I think I can speak to both things at the same time. The short answer is, no, I don't view Remix and React Routers having a preferred architecture. React Router is actually really old in web years. You think about CSS was created 22 years ago, I think? It was like CSS. I think kids today probably just kind of assume that it has existed forever, right? I remember when I realized that the Beatles weren't like a thousand years ago. It was like, "Oh, wait. There are Beatles who are still alive?" That just blew me away. Remember, I was like a teenager. I think that's the way CSS is for some kids where it's like, "Oh, it's not that old. It's only like 22 years old." React Router is 10, 11 years old, so it's half as old as CSS itself. This project has been around for a long time, and React itself has always been super flexible, too. We've always been able to server-render React from the beginning. Most people didn't, but it was always there. You could run it on mobile and React Native. It's always been a very flexible thing, and React Router has always tried to support the great flexibility of React. When Remix added a bunch of service stuff, right afterward, React itself did too, with React server components and server actions. Then they introduce a bunch of things like use action state, and use optimistic, and use transition. All of those concepts, all of the use cases for those things in React we had like a cognate over in Remix already. It's been kind of tricky for us to figure out like, "Do we deprecate our stuff? Do we just go straight to that stuff?" Because there's like 90% overlap if you have like a task. Which API are you going to use? With React getting more involved with the server and with transitions, being an old project, we want to support that in those new models of how to deploy a React app with the assumption of a server like React server components. But we also have to recognize that we've got a decade of highly successful apps still running React Router without servers like that. Right now, we're in Riverside FM. It uses React Router, but it doesn't use any of our server features, and it doesn't use any of React server features either. So we're not just going to like bail on that paradigm. It's a successful paradigm. Linear, which is an app that everyone talks about all the time, is being kind of like the pinnacle of web UX with local first and doing a data sync. They use React Router and not use in any of our async stuff like loaders and actions. They're just using the components that match URLs, and then the components and hooks that let you navigate around and read state from the URL. We're not going to go say, "Oh, we think you definitely need to have a server to run React Router." We would not be serving the user's needs that we've had for the last decade by doing that. While I think that there are some new architectures that are novel and interesting with server components, there's just no need to bail on what's currently working. So we got Linear on one end of the spectrum. ChatGPT.com is a Remix app. But most of their data loading is done with React Query instead of React routers, loaders, or Remix's loaders and actions. But what it does use is the root loader for user information and other kind of other things like that, and so that's really useful. Now, you navigate around. You don't have to worry about over-fetching all that stuff again. They get the bundle splitting that Remix provides on their routes, but they aren't using the data-loading pieces. Then you've got bolt.new. I don't know if you've messed around with that AI. Oh, my gosh. It's so cool. Go to bolt.new and try it out. It's one of those AI things where it's like you just described the app or what you're trying to do, and then it does everything. It makes files. It refactors them. It can write tests. It does tons of stuff. That's a full-blown Remix app using lots of our features. I kind of like where we're at of not saying this is the blessed architecture. Because at Shopify alone, we have very different use cases, and they're all using React Router or Remix. You can like tacos and you can like burgers. You don't have to say burgers are the only best fast food, right? We can be a single team building a single project, React Router, and it can support multiple paradigms, and architectures, and deployment strategies. I'm happy with that. [0:16:17] JG: I'm happy to hear you say that. There's been somewhat of, I think, a misconception at large in the React community the last year or three that React was going all in on server, that server components were the one and only way. That is an area of investment for sure. But there's nothing stopping you from, as you said, making a Riverside or ChatGPT-style single page or somewhat single-ish page app. You've also brought up a lot of really interesting words like root that have meanings in the Remix React Router world in context. For those who haven't used Remix or React Router themselves, could you give us a brief overview of what some of the really important concepts are if you're writing an app with them? [0:16:52] RF: Yes. I'm just going to throw this in here really quick. We moved everything from Remix over into React Router, which really was just our bundling and a couple server concepts. Now, you can really say Remix and React Router interchangeably. But moving forward, React Router v7 has everything that Remix had and more. We'll talk about this later in the show, I'm sure, what we're going to do with Remix after this. Now, I'm just going to talk about React Router because everything that was in Remix and wasn't in React Router already is now in React Router v7. Yes, I said root. Then there's the word route. If you are from certain parts of the world, speaking English, you say those words the same way. So you can have a root route or a root route. So let's see. Where should we start? First thing is URL, right? That's how websites start. Here's a URL. We call that anything that's going to match that URL and then render something. We call that a route. You can nest these routes below other ones, so they build on the path of their parents. They also build on the UI of their parents. There's this idea of an outlet where it will, I guess, yield the content of the child route inside of the parent route. It makes layouts really easy. That was kind of like our bread and butter for the last 10 years. The root route, it has no URL. It just always matches. You can put things like loaders on there that say, "Hey, here's all the data that I need for this route." If it's the root, then that's kind of like the core data of the app. Who's the user? What are their preferences? What A/B test are they in or whatever, right? But every one of those routes down the tree can have their own data as well, and it will go and fetch that data. Or simply just call your loaders in the browser to get the data, hand it to the component, and the component can render. It's kind of an MVC model. You got model view controller. We have no model. The Vue, our React components, and the controller is these two functions called loader and action. In the case of a SPA, it's client loader and client action. Those loaders decide what data to then give to the component. Instead of splitting up model view controller at a flat layer at the top, you get little nested MVCs for each route inside of there. Then if a form is submitted or you do it with code, it'll call the action on that route, which can run on the server or in the browser, whatever you want. After that action gets called, instead of you having to then go find the new data and set some state and React to then update the page, we just know automatically that if you did something that calls an action, then the framework will automatically go and say, "Well, I knew how to fetch the data originally. I'm just going to go and fetch the data again." Then the page will update automatically. It gives you that old school PHP feel of, "Here's a page. Here's a form. You take some data. Forward right back to the page that you're at, and then your code just runs again and gets all that data." The behavior is a single-page app, even though a bunch of your code's running on the server, where it's just using React to update just those parts of the DOM. Did I go off on too many tangents, or is that what you were looking for? [0:20:01] JG: That's very much what I was looking for. Thank you. [0:20:02] RF: Yes, you bet. [0:20:03] JG: Are there other topics or parts of React Router you'd like to go into before we move on? [0:20:07] RF: I don't think so. No. [0:20:09] JG: All right. We've talked a good bit about where things came from, the fact that you've been purchased by Shopify or acquired by Shopify. I would love to get your take before we talk more about the future of a React Router. Where does React Router end and Hydrogen begin? Or I guess, really, what is Hydrogen, and how does that fit into the React Router vision? [0:20:31] RF: Yes. If you're a merchant, you want to set up a store, if you have like no technical ability, which is most of them, you don't care about React, or React Router, or Hydrogen, or any of that stuff. You just pick a template from the Shopify interface and go from there. Then we have this thing called liquid as well. If you're technical, you can get in there and customize your store with liquid templates. But there's this other version of e-commerce. Some people call it headless, so headless e-commerce. I think we just call them custom storefronts where it's like, "I'm not going to use your templates. I'm not going to use your liquid stuff. I just want to use the API to my store." Shopify has a very capable API for everything about your store, get all your products, get all your collections. You still log into Shopify and manage your store through the Shopify admin interface, but you can then write code to talk to our APIs to build your store, the actual interface that people go and visit. Hydrogen is a way to build a custom storefront. So instead of just saying, "All right, here's our API. Knock yourself out," shopping carts are actually a little bit complicated, and all the variants of a product, and how can I render a 3D model of the product that I'm trying to sell you. Where will I get a component for that or just the image components? All that kind of stuff. There's a lot to think about and efficient sorting, and queries, and stuff like that. Hydrogen, I guess you can think of it as like a utility belt that works well with Remix. They got their own CLI to scaffold a custom storefront. You can just be like - I don't know the exact command, but like Hydrogen new, and then it scaffolds out a store for you. From there, you own all the code. You can go customize how it looks and everything else. Then there's a bunch of abstractions to render your cart. When you go to the cart page and it's got all the line items and they got abstractions for buttons to increase the quantity and see it optimistically update instead of waiting for the network request. Yes, it's like a utility belt of like, "Well, if you're going to build a custom storefront, here's a bunch of stuff, and you're probably going to want some of it." Then a CLI and things like that to make the full development process nice specifically for building a store. [0:22:57] JG: It makes sense then that Shopify be interested in being able to fit that together with the underlying meta framework for React, so to speak, that you have a vision of the architecture of your app that can be assumed or worked with nicely by the stuff on top. [0:23:12] RF: Yes. Yes. It was kind of fun when we went to Shopify. People are like, "Oh, great. Now, Remix is just going to turn into an e-commerce thing." It's like, "No, no, no. That's what Hydrogen is. Remix is still independent of that." Shopify has just been incredible. I've loved working here. They told us before we came, they're like, "Hey, we're not going to tell you what to do and stuff. We want you to just build the best React framework that you can, but we want you to listen to our teams, right? We want you to take their feedback and help that shape what you build. But by no means are we going to be held accountable for like, 'Oh, the Hydrogen team wants this. Why didn't you ship it?'" Now, we pretty much have tried to do everything that they've ever asked for that would make their lives easier. But they've let us operate very independently, and it's been great. They definitely kept their word because you never know, right? I never worked at Shopify. I'd never talked to any of them. They're like, "Yes, come and work for us, your company that you just built and you've put all your blood, sweat, and tears into." So you kind of worry like, "How much autonomy am I still going to have with this thing?" They've given us tons of autonomy. They're just awesome, awesome company. [0:24:20] JG: Yes. I think one of the signs that a framework is being given the autonomy it needs is that it's able to invest in areas that don't directly, obviously, contribute to whoever's controlling the money. Actually, I did want to bring up one area. If you go through the currently Remix docs, there are a lot of notes here and there about how something is not supported in the classic Remix compiler but is now supported in the Remix Vite build engine. What is the difference? Or can you tell us about this move to Vite that Remix has done? [0:24:47] RF: Yes. When Michael and I started Remix in the throes of 2020 lockdowns, Vite didn't exist. Webpack is a great project. It was a little bit slow though for bigger projects and stuff, and esbuild was in beta. Esbuild was fascinating because it was so dang fast that it was like we don't even need the concept of like a dev server. Save a file. Just build the whole app again, and it was basically fast enough for that. I remember stress-testing stuff before we had released anything. I made an app with like 2,500 routes. I worked on a Rails app. I worked at a company called Instructure. We built Canvas LMS that a lot of people might be familiar with. It was a Rails app. If you said rake routes, you had 2,500 routes in that app. I kind of picked that as like, "Well, if I can't build Canvas LMS all in Remix with this compiler, then it's not going to work." I did that, and it was too slow for my liking. Then after I profiled it, it was all my code that was too slow, but esbuild was plenty fast. [0:26:02] JG: Classic. [0:26:04] RF: Yes. Anyway, we made a bet on esbuild. This is fast. The thing that I liked the most about it is that with the classic Remix compiler, dev and production only had one difference, and that only difference was minification of your code. Other than that, it did all the exact same things. There's nothing that irritates me more in the JavaScript world than when it works in development but it's broken in production. Or when it works in production but it's broken in development. I've always really valued keeping that gap as narrow as possible of what's my dev build and what's my production build. That was the motivation behind pick an esbuild. We started to want to do HMR, hot module replacement, so that I can save a CSS file. You don't have to reload the whole page. We had live reload before. You could save the file, and then the browser would automatically reload through a web socket that we built. That's mostly fine. But then the way Remix works, you've got your loaders up top that are pulling stuff from your database or some third party or something. Super annoying for editing CSS and changing styles because every single time you tweak a style and save, you got to go fetch the data again. It just kind of slowed down that part of UI development. We started working on HMR, teamworked on that. Pedro and Mark put a lot of work in. Jacob is involved with everything. Everybody does. Once they got it working, they had gotten to the point where they're like, "Vite's pretty mature now, and we just did a whole bunch of stuff to try to support this." I don't want to put words in their mouth, but my memory of this is that they were like, "It works, but it's a little bit messy, and there's really no getting around to being that messy. We should probably just use Vite because it's got all this stuff built in." We switched over to - did some experience with Vite. It took us like a year. We kind of goofed around with this idea for a year before it was like, "Yes, let's go with Vite." That's been a big deal. It's been very useful for app developers. There's a lot of stuff that we don't have to do anymore as the Remix team. We don't have to build our own compiler anymore. We don't have to build our own HMR, CSS stuff, all the things that bundlers do. You can now just bring in a Vite plugin if you want to get that kind of bundling behavior. Half of our team, I would say the founding half of our team, have had it with bundlers, and we hate them. The other half of the team is like, "This is amazing." Bundlers are fantastic because they give you a whole graph of everything in your app from assets, to JavaScript, to icons, to CSS, and now we can optimize it all. But I just get super irritated because I can't touch a Vite without dev being different than production. Every time I touch it, I end up with that. Everyone always says, "Oh, no. You work those bugs out, and eventually it never matters." But I haven't gotten to that point yet personally. I always have a problem. But on the flip side, HMR is really, really nice with Vite. React Router dev tools used to be like this weird thing that to try to like add it in. It's built by another developer. Not on our team. He's awesome, Alam. That now is just a Vite plugin. There's lots of really cool things about us adopting Vite, but it's not without its trade-offs. I really hate the dev and production are not the same thing. It goes through completely different code paths. Sorry. I'm going to start ranting about it all. I should stop. [0:29:32] JG: Sure. [0:29:33] RF: It's great. Let me say this. If someone from the Vite team is listening to this, they're going to be like, "Oh, my gosh. Ryan is being a jerk and throwing us under the bus. But thanks." Adopting Vite has been - I still think it's the right choice that we made. They have been incredible to work with, smart, talented team. Yes, I still think it's a net positive. But personally, I still run into the inconsistencies. [0:29:57] JG: That's part of writing our framework is these trade-offs. I'm also excited to talk about - you've mentioned that it's freed you up to work on things. What are some of the things it's freed you up to work on? [0:30:05] RF: With React Router v7, it's been hard actually to push React Router forward. RSC threw a wrench in everything. It's hard to figure out. I already mentioned this a little bit. It's hard to figure out when your primary dependency, React, takes over a bunch of the use cases that you are handling. How do you incorporate that without looking like you're just changing the API arbitrarily, right? Why are you getting rid of loaders? Well, if you want to use RSC, you don't need a loader. But I liked loaders. Why are you always changing React Router? It's like, "Okay. Well, then we can just not support RSC." Then you get the like, "Why don't you support all of React? You're a React framework. Why don't you support RSC?" Literally, we had a hook called useTransition. That's what our hook was called, useTransition to know when something asynchronous was happening in remix like calling loaders or actions or whatever. React now has a thing called useTransition that generally is active when an action, a server action or a form action, is being called. We have our own form component, and an action points to your route, and now React has a form action prop that takes a function that when that function is getting called, it triggers the pending states of the useTransition hook. It's like there's just this huge mess of overlap now where like 90% of what made remix unique in the browser, in the client part of things, not the server stuff, but the client parts, React now has a version of that. We've kind of been doing two things at once. Number one is just figuring out what the heck RSC is, what server actions are, how all their new transitions and actions and stuff work, how to get it in to React Router, and to do it in a way that you can mix the concepts. Because you've got to be able to mix the concepts so that we don't blow away all the work that people put into their remix in React Router apps already. You've got to be able to easily move from the loader action paradigm of React Router over into the RSC and form action paradigm of React. These things have to be able to work together. Otherwise, you've got to rewrite your whole app. So balancing that, along with balancing just the typical SPA use case of Riverside and Linear and GitHub and everybody else who uses React Router, how do you balance all of these APIs and make them all work together? It feels like kind of a big thing that's slow and hard to move forward, but React Router v7 is what we generally worked on over the last year. I would say the first year at Shopify, we worked on making React or making Remix work without a server, so SPA mode, client server, client actions, client loaders, all that kind of stuff, and the migration over to Vie. Then second year has been RSC research and design and moving everything over into React Router so that we can have this multi-paradigm framework that lets you use as much of it or as little of it as you want. We're just about there. We're getting close on the RSC stuff. With React Router v7, we've got loaders and actions that run on server. We have client loaders and client actions that run in the browser or just keep on doing it the old way. Here's another thing that we've been able to work on a lot too is better type safety. [0:33:28] JG: It's very interesting to see. [0:33:29] RF: Yes. As TypeScript ESLint guy yourself, this is the topic you're probably interested in. It's difficult. There's two types of TypeScript, right? There's type safety, and then there's all caps type safety. Type safety is like you just naturally write your code. I take a string here. I take a number here. This thing should be a React Node. This thing should be that. It's going to return a number. That stuff's all fine and easy. But then all caps typescript is when it's like, "How come my links don't give me a list of every possible route that I could go to? How come my loader data in my component doesn't tell me exactly what the loader returned? Never mind it went over the network, and it got serialized. I should still see exactly what that data is. If I sent an integer of 42, and I said as constant the end of that, I want in my component to know that that is 42, right?" That's not normal type safety. That's like telling TypeScript about how the framework operates, right? Because the type system itself doesn't know. If the loader returns this, then an argument to this export in your module is going to get this value. You got to do tricks to know that kind of stuff. Pedro on our team has done a lot of the work there to get type safety. We've got really great type safety now. We have this routes TS file where you define your routes, a lot like Rail's routes.rb. As part of the dev workflow, you get these - I think they're virtual modules that give you all the type inference for those routes. We're actually looking at the route paths where you have patterns with the colon like colon user ID, and it can be optional, too. Our type gen there will parse out those dynamic segments of your route paths. Now, inside of your component and your loaders and actions, when you say params., you get a hint that says, "Hey, I know that you have a user ID on there because I went and read your routes TS file. That sounds really nice because now you're not going to go try to load data for a param that doesn't actually exist on your route. That also infers the loader data now, too. So you return values from your loader, your component gets a prop called loader data, and that thing's fully typed as if you called the function yourself, and it comes back. Jacob has worked a lot on our transfer format over the wire for streaming, a thing called Turbo Stream. It does serialization and deserialization of a bunch of different types, so it's better than JSON.stringify. You get numbers back out of there. You get dates back out of there. It's the basis that we're going to do for RSC, so you can get components out of there. That couples with the type safety because if you pass a date, React Router sends it over the wire, and it has to serialize it. It comes back to the browser as a string, but then React Router on the other side of that parses it and then gives you back a date, so all of your type safety is much simpler. You don't have to like assume, "Oh, these are all serialized." They're actually the same values. Even promises, you can even have nested promises, and they come all through. Yes. It's a promise on the back end, goes over the wire, and then comes back as a promise in the browser. It's kind of cool. [0:36:43] JG: I like the way that you put it that they're the two levels or types of TypeScript. I think it's kind of unfortunate that as people go more and more into frameworks such as yourself, like folks who are actually writing their frameworks, they may or may not be the people who also want to write intense, deep TypeScript with words like key of and constant maps types. But if you have users using it, it's going to be an inevitable thing that they want that level of type safety, the all caps one. [0:37:10] RF: As a humble JavaScript web developer who graduated with an economics degree and has never touched a computer science class, it took me a while to figure out that like just to iterate over a list of an array or unions or over a union, it's recursive. There's no like for each in TypeScript generics, right? It's like if you're writing TypeScript code, everything is a recursive function. So it's like, okay, I know that this is a map, and I need to do a map here, and then we got to do a reduce. I have all the words in JavaScript. But then in TypeScript, it's just a different way to think about code. So it has been kind of fun. Yes. One time, Michael and I were working on - I don't even want to say it out loud, but working on a new router. Anyway, we're getting type safety there. It was like six hours straight of writing these recursive functions to try to get the thing that we wanted, and it felt like doing homework. It's like, "Okay, here we go. What do we need? First, we need the loop code, and then we need this. Does this extend that? Okay, here's - does it extend an empty array? Okay, that means that the left side is one item, and the right side is zero items. So at this point, we do this, and then we recurse." It was just like recursion after recursion after recursion. I was like, "This is - I feel like I'm in a computer science class doing a worksheet on recursion." It's cool, though. [0:38:41] JG: I have a computer science degree, and I felt absolutely unprepared for the TypeScript type system when I started using it. I did not think it was something that I got out of university or really wanted in my life at the time. [0:38:53] RF: Did you have the vocabulary, though? When things started to click, you're like, "Oh, this is like that." [0:38:57] JG: You know, I think I did at one point in computer science class. I'm so sorry, Professor Varela, who I remember being a great programming language as professor and teacher. But, no, it's one of the unfortunate things, I think, that it's just so different from everything else. By the way, I could talk about TypeScript for years, as I'm sure you know. But I do want to give you a chance to talk about more React Router stuff. I have one final question on the subject of it. Let's say that we have this conversation again in two to three years. What would you predict to be the thing that you are most excited about having been accomplished in those two to three years? [0:39:28] RF: Oh, man. Remix v3. I want to call it Remix v45 for the RPMs on a record player. But I don't know that I'm going to get my wish. We moved everything over to React Router, which 90% of Remix was already in React Router. So it's like we moved the last 10% over. We moved everything over to there. That gave us room to just do something really cool with Remix. We love the Remix brand. We get a lot of flags still on Twitter. We even got a little bit internally of people like, "What on earth are you doing? Why are you killing Remix?" Yes, yes. It's super fun. We're like, "We're not. We're not. We're not killing Remix." I said from the stage, Remix is going to take a nap. Generally, people don't die when they take a nap. They'll come back. They come back refreshed. They come back better than they were before. But we've been dedicated to smooth upgrade paths. So the best way with the model that Remix was on of everything being done at the route module level, that was best moved over to React Router and just continue with that paradigm. That's one timeline. We want to make the best version of that that there is. The analogy that I always use is it's like Chrono Trigger. Did you ever play Chrono Trigger? [0:40:44] JG: Let's say that I did. [0:40:45] RF: Do you know what it is? [0:40:46] JG: It's a video game. [0:40:47] RF: It is a video game. Good job. [0:40:49] JG: Yes. Thank you. [0:40:51] RF: It was a Super Nintendo game built by SquareSoft, or maybe it was Square Enix at that point. I think it might have been Square Enix. In my opinion, it was pretty much the best Super Nintendo game ever. It was my favorite one. Actually, every couple of years, I'll play it again on an emulator, just because I loved it so much. What's interesting about Chrono Trigger is that it came out after Nintendo 64 was released. So you got Nintendo 64, a whole new model. You got 64 bits. You can do 3D stuff. It was a completely different world over there. Obviously, the future of video games was over there on the Nintendo 64, not on perfecting and optimizing Super Nintendo games. But Chrono Trigger was released after Nintendo 64 on this old model that it was just the best version of that ever, and it is still good today. I still love playing that game. Games today could still learn stuff from Chrono Trigger. For me, personally, I'm not going to speak for the whole team here. Everybody on the team works on React Router and has an influence on it. But for me, that direction that we were going with Remix and then React Router is the Super Nintendo. There's nothing wrong with it. React Router v7 and when we have a v8, to me, that's Chrono Trigger. It's like this is the best thing that we can do with this model before server components, before web UIs were all over the place, before React could do things that it can do now, where we basically had this one tool which was the route module and we hung every API off of route modules. React has inspired what I think is a new generation of even more encapsulation across the stack for a server component, server actions, and client components inside of there. You can build a little box, right? We've seen people making these kinds of demos with AI, especially, where you're in a chat, and it's like the chat wants to show you a little map, or it wants to show you a little product, or it wants to show you a little to-do list. That's not a route anymore, right? That's just a component that has data and actions and stuff inside of it. You still are going to need a server on the back end to manage those actions and to get the data into that component. Remix, for me, is the Nintendo 64 now. There's this new world. Our biggest bet is actually not on React. Our biggest bet is on the web APIs; fetch, request, response, Web Crypto. There's so many APIs that we're starting to see run on more and more JavaScript servers, including Node. In a couple of years, to answer your question, I can't wait to see what both our team builds and what our community and the ecosystem develops around what we're building. The stuff that we're building right now for the next version of Remix is super compostable. It's going to be consumable as like a framework, but the way that it's built isn't. You could use little parts of it. Even today, already, if you go to the React Router docs to look at a file upload, how to do file uploads in React Router, you're going to bring in one of our Remix packages in the future version of Remix for multi-part parsing. Astro sites will be able to use this stuff. Solid Start sites will be able to use this stuff and just plain old web servers that need to support whatever you need. We'll be able to use everything in Remix, and then we're going to package it up really nicely as like a framework with some docs that are cohesive, so you don't have to go to like 12 different readmes to figure out how to put things together. See, that's what I'm excited about. It's a big bet on the web platform, anticipating more stuff like React server components, encapsulated widgets that can be easily embedded anywhere into existing apps or even generated by AI on the fly. We want to build a back-end JavaScript infrastructure or architecture to support all that stuff in the future. [0:44:44] JG: That's similar to the bet you've been making a lot of the time with Remix, right? Bet on the platform, bet on the web APIs, see where things go. That would be a fantastic way to close out this interview. If you'll permit me, can I ask you one completely unrelated to Remix and React Router question to actually close out, though? [0:45:00] RF: Yes. [0:45:01] JG: For the listeners, we did confirm this as a question ahead of time. How come there are so many JavaScript and React people in Utah? I'm legitimately interested in hearing your answer on this. [0:45:10] RF: I don't know. I don't know why. We're just the loudest for some reason. Yes, there are a lot of us, me and Kent and John from Ahead and Tanner from TanStack. I'm probably even out with some people. React Rally, Jamison and Matt. Zabriskie ran React Rally for a while. Actually, they're still doing that. I don't know if they're doing one this year. But, yes, there's a lot of us. I love Utah, absolutely love Utah. Economy's awesome. The weather sometimes can be terrible, but that also gives us all the ski resorts. I'm within an hour of like, I don't even know what it is, 12 ski resorts. I only go to two or three of them. Just tons of stuff in the mountains, it's beautiful here. I love it. Super family-oriented, too. Everything is designed for families. When I lived in Washington, we'd show up to a restaurant, and they'd give us a look like, "Oh, crap, kids." But in Utah, it's all fast-casual, and it's just 100% designed for people with kids. We really love it here. The outdoor stuff, all the family stuff, it's fantastic. [0:46:10] JG: That's really lovely. Well, cool. Ryan, thank you so much for coming on. I thought this was a phenomenally interesting set of topic; Remix, React Router, the merge, the React Router, and then the Remix, and where you're all going with Shopify. Is there anything else you want to tell the listeners before we sign off? [0:46:26] RF: No. Buckle up. I don't think any of us really even know what the heck is going to happen with the web. This has got to be the most exciting time. The only precedent is the web itself with what's going on right now. So, yes, I'm pretty excited to see where it goes. [0:46:39] JG: Strongly agree. For Software Engineering Daily, this has been Josh Goldberg. Thanks for watching, everyone. [END]