SolidStart with Ryan Carniato - JSJ 581

Ryan Carniato is the CEO of Signals and the Principal Engineer OSS at Netlify. He is the author of the SolidJS UI library. He returns to the show to talk about SolidStart. He begins by explaining the difference between signals and observables. Along with that, he discusses how he came to develop the framework.

Special Guests: Ryan Carniato

Show Notes

Ryan Carniato is the CEO of Signals and the Principal Engineer OSS at Netlify. He is the author of the SolidJS UI library. He returns to the show to talk about SolidStart. He begins by explaining the difference between signals and observables. Along with that, he discusses how he came to develop the framework, its features, and his future plans. 

On YouTube

Sponsors


Links


Socials

Transcript


Charles Max_Wood:
Hey everybody and welcome back to another episode of JavaScript Jabber. This week on our panel we have Dan Shapir.
 
Dan_Shappir:
Hi from Tel Aviv, where the weather is great and the politicians are terrible.
 
Charles Max_Wood:
Steve Edwards.
 
Dan_Shappir:
I'm gonna keep saying that because it keeps on being true.
 
Steve_Edwards:
Uh,
 
Charles Max_Wood:
I don't
 
Steve_Edwards:
hello
 
Charles Max_Wood:
think that's
 
Steve_Edwards:
from,
 
Charles Max_Wood:
different anywhere else.
 
Steve_Edwards:
yeah, I was going to say hello from Portland where our politicians are awful.
 
Charles Max_Wood:
I'm Charles Maxwood from Top End Devs. Quick reminder, we're putting together the game dev stuff starting next week. We have a special guest this week. It is Ryan Carniato. Ryan, it's been, you've been on a few times lately. You wanna just remind people real quick who you are if they've missed the other episodes?
 
Ryan_Carniato:
Yeah, for sure. Yeah, as you said, my name is Ryan. I am the creator of Solid.js. I work with a lot of open source libraries and frameworks and I work on open source at Netlify.
 
Dan_Shappir:
I think you have a few additional titles,
 
Charles Max_Wood:
Awesome.
 
Dan_Shappir:
like you're the CEO of Signals, and you're also like the leading expert on all things framework, which is I guess why we are having you here today. Turn extended.
 
Ryan_Carniato:
Yeah, it's funny how we end up there. But yeah, CEO Signals was not a title I came up with, but it's my official Twitter title. Because on Twitter, you have to be a CEO of something, right? So.
 
Charles Max_Wood:
I was going to
 
Ryan_Carniato:
But
 
Charles Max_Wood:
say, is that
 
Ryan_Carniato:
yeah.
 
Charles Max_Wood:
like the great Bambino or the Sultan of Swat or something like that?
 
Ryan_Carniato:
Yeah, I don't know. It was from, I think it was a Brandon Roberts stream. There's been a lot of talk because Angular
 
Charles Max_Wood:
Okay.
 
Ryan_Carniato:
community has been picking up signals and they're like,
 
Charles Max_Wood:
Uh huh.
 
Ryan_Carniato:
they want to position it like that. It's fun. I had a podcast recently where I was with Ben Lesh and they called him the CEO of Observables. So there you go.
 
Dan_Shappir:
Well, there is truth to that,
 
Charles Max_Wood:
That's
 
Dan_Shappir:
for
 
Charles Max_Wood:
not
 
Dan_Shappir:
sure.
 
Charles Max_Wood:
uncalled for.
 
Ryan_Carniato:
Yeah.
 
Charles Max_Wood:
Yeah.
 
Ryan_Carniato:
Yeah.
 
Dan_Shappir:
Were you able to come to a definite conclusion like what's the difference between signals and observables?
 
Ryan_Carniato:
We were actually, I mean, I think both of us understand the difference in their range. I think the fun part about it is we like to kind of position ours as the more, each of us position ours as the more primitive thing, right?
 
Dan_Shappir:
Hahaha
 
Ryan_Carniato:
Like you can use one to build
 
Charles Max_Wood:
Ha ha ha.
 
Ryan_Carniato:
the other. So that was like the dance that was going on. He's like, oh yeah, you could just like make signals by using, you know, an observable with no, with the notification blah, blah, blah. And that's like, oh yeah, but signals are like a language level thing that you could build an observable. Yeah. It was kind of like.
 
Dan_Shappir:
So you know
 
Ryan_Carniato:
bit of
 
Dan_Shappir:
what,
 
Ryan_Carniato:
circling
 
Dan_Shappir:
as
 
Ryan_Carniato:
but
 
Dan_Shappir:
long
 
Ryan_Carniato:
generally
 
Dan_Shappir:
as we're...
 
Ryan_Carniato:
speaking the you
 
Dan_Shappir:
Yeah, go for it, sorry.
 
Ryan_Carniato:
I was just gonna generally speaking the use cases and like where they are strongest are different. So they can work together quite well. It's just there's always this like thinking of like, can we unify it into a single thing? And the answer is like, not quite or like not like each has their purpose.
 
Dan_Shappir:
Look, it's not supposed to be the topic of this episode, but we got there. So it seemed to me, and this is by no mean official or anything, it's just something that I kind of came up with, and maybe I'm wrong, that the key difference between signals and observables is that you subscribe to observables, but you don't actively subscribe to signals. Or do you think that's not the salient difference?
 
Ryan_Carniato:
Yeah, I mean, the auto tracking dependency thing does make it different the way you wire things up. But it's like, it's hard to tell like, which one's like the symptom of the design versus which one is like the reason for it. But the key part about signals is they've been designed mostly for synchronous systems designed so that like everything stays in sync. And it fit into problems like almost like templating or like, I mean, they originally came from electric circuits to be fair, but with that kind of limitation, you can, or restriction, you can basically define almost all relationships as like an assignment almost, like not an assignment, like a declaration, like A equals B times C or whatever. So like when you have that sort of, you know, set up, you don't need, like you, having the subscriptions being automatic. simplifies the process and that's the focus. Whereas if you've ever used Rx, you know that like you're piping things into other pipes into like other things that like, you know, make that asynchronous stream go through. So like, it's almost like the use case that they're built towards kind of geared towards what they emphasize for with signals, the reason the synchronous is important is because they're topologically sorted, so that you ensure that change propagates glitch free runs RX is designed just to give you incredible flexibility and power around how you, you know, transform data through async. So like, I feel like it's just kind of like an extension of their primary purpose, uh, the subscription versus not subscription thing.
 
Dan_Shappir:
So you're saying one is designed for data synchronization and the other is designed for data flow?
 
Ryan_Carniato:
Yeah, yeah, yeah, exactly. Like transformations and stuff over time. Signals don't really have a time axes. I mean, yeah, I mean, it's possible to do stuff around time and I know I'm being a little vague here, but like generally speaking, everything's just like, when something in the system changes, make sure that it's all in sync, that everything's consistent. Where with RX or observables, like it's all about like watching the, yeah, you said it better. You know, it's just watching the data flow through your app. Like, Oh, try this fetch. Doesn't work retry, you know, split it, move it here. Yeah.
 
Dan_Shappir:
A stream of things, as it were.
 
Ryan_Carniato:
Yes. Yeah.
 
Dan_Shappir:
Yeah, values over time, whereas one is, yeah, like you said, synchronizing the values synchronously. Now, I actually think it does kind of tie into our topic today, which is going to be solid and solid start or solid start and solid, because in a lot of ways, you
 
Charles Max_Wood:
Mm-hmm.
 
Dan_Shappir:
defined solid to me once as, and not just to me, I'm guessing, as state management. or event system that happens to be a framework or something along these lines.
 
Ryan_Carniato:
Yeah, yeah, you know, like state management first, like renderer after, right? It's just like, it's just a side effect that we happen to be rendering the DOM.
 
Dan_Shappir:
And that's Solid itself. So Solid itself
 
Ryan_Carniato:
Yes.
 
Dan_Shappir:
is, well, it is a framework because it does update the DOM and it kind of looks like React as well, what with JSX and stuff like that, and use of the word use and other things like that. But...
 
Ryan_Carniato:
It's
 
Dan_Shappir:
But...
 
Ryan_Carniato:
a framework as much as React has been a framework historically. So wherever you want to like sit that, right.
 
Dan_Shappir:
Yeah, there is truth to that.
 
Ryan_Carniato:
I-I-
 
Dan_Shappir:
Have they finally come around to accepting the fact that React is a framework?
 
Ryan_Carniato:
I don't think so because they have an opinion on what they want to call framework versus meta framework, which we probably should talk about. But they react for them. I don't know if they've officially said it. I think they're still calling it the library. It could be arguably a spec with the new stuff that's coming down the line with server components and use client and all that kind of stuff. But they've kind of reserved the term framework to refer to things like Next.js and... remix.
 
Dan_Shappir:
I think it's more than a spec after all it does carry along quite a bit of implementation. So it's not just telling the people at
 
Ryan_Carniato:
Yeah.
 
Dan_Shappir:
Versel what to do you know.
 
Ryan_Carniato:
Yeah, it's an interesting balance on that because like, there is that part and there are specific like tools or primitives that they give to let you build. But they also like the stuff like use client and there's a bunch of stuff that they're telling you to do that they also don't do themselves like they use client on the bundler stuff is up to the bundler to implement. So there's they've they've kind of drawn a line where they're trying to like build as many as like just the necessary. building blocks and pieces and then be like, okay, everyone else, you should follow these kind of guidelines and in terms of how to do it, which is why they've kind of moved to the place that you need a framework to use react or you should use a framework to use react in the future. That's kind of, um, the positioning and it is an interesting topic, river, like tying back to what we're talking about today, because this idea of what is a framework has been very much on my mind since I started working with all start.
 
Steve_Edwards:
Dan, couldn't you really say that anything coming out of Facebook would be a meta framework?
 
Dan_Shappir:
Yeah, except that they officially say that the one thing that they're not doing is a meta framework, which does bring us up to the topic of our discussion for today, which is the fact that maybe meta is not producing a meta framework, but you are. And it's called Solid Start, which is a great name for a thing.
 
Ryan_Carniato:
Yeah, I mean, and it reflects my thinking about these things because like, um, it's tricky. I've always been one of those like, well, I'm not going to like, argue strongly like, Oh, it's all, it's just a library. You know, the same way people were like, React is a library. I just say it's like, whatever you want to categorize, React at, we'll, we'll take the same title, like this whole library versus framework thing. Um, it was very important for me to always provide the building blocks that let people build other things. And that includes like, I didn't really, you kind of know that like when you go higher up the stack, when you get into the framework or meta framework land, you have more opinions. And we've been throwing around the term meta framework. I don't know if people are too familiar with it. But it's this kind of funny term because I don't think I think React was always a library. So people could call next say a framework. And then they might call something like Blitz a meta framework. Blitz was built on top of next. And it used, they added like RPC calls and a bunch of like, uh, quality of life improvements to like next. But what's kind of happened over time because other libraries or frameworks called themselves frameworks, like view or whatever, like the term meta framework started just kind of meaning, um, any framework built on top of another framework. which meant that kind of, I mean, I don't want to say who's first, but it started becoming like view reacts felt are the framework. And then the meta frameworks are knocks next felt kit, you know, solid start, whatever, you know, etc. And but I mean, the problem is like, does it ever end because there's the other things like, you know, blitz or create T3 app, which then you're like, are these meta meta frameworks? I don't I don't this is why the distinction is is. difficult to make, as difficult as it was to make when we were talking about library versus framework. But for me, I just knew that I wanted to start from primitives. And mostly I wanted to kind of hit two birds with one stone. I wanted to create like a starter template that let people do SSR. That was the thing. So like one of the reasons people have metaframed works is because it's kind of hard to wire server-side rendering yourself. And I wanted to... make it easy. But on the other hand, I didn't. There's a lot of meta frameworks out there that have lots of features that are really opinionated and very powerful in that sense. But they're like, you do it our way, right? And I was trying to keep that like what made the quote meta framework as minimal as possible. So, you know, that's, that's where the solid start came from. Because I was like, I was really thinking starter template, rather than like, opinionated framework, like something on the opposite end of the scale might be like Nuxt is amazing in that, like they take care of all these things for you. And there's a lot of extra pieces to really lend to that experience. Things like auto imports and like they definitely have this really good DX story where it all ties into Nuxt and kind of completes the picture. Even stuff like, you know, next and next image and like all of those, those pieces kind of tie together into the single story. I wasn't as interested in bundling stuff up. I just want to make sure that the pieces were there so that. people could and initially I was like, like people like as soon as we got server side rendering and solid back in like 2019, people are like, okay, where's the next JS equivalent? I'm like, go build it. I don't want to, you know, like you go do it. And over time, I realized that like, it was a difficult task for people to approach. But that being said, I didn't want to get away from giving people that flexibility to be able to like, oh, here's the baseline. take and add and use it however you would.
 
Dan_Shappir:
So
 
Ryan_Carniato:
which I'm not sure if that's very framework-like.
 
Dan_Shappir:
Well, I don't see why it isn't. But yeah, it does seem that in many cases, frameworks are about codifying certain opinions. But I'm not sure that by definition, it's because they're absolutely certain, the creators of such meta frameworks, that they have the best opinions. Rather, it's because they want to jumpstart development, provide good DX, and being opinionated just kind of is the easiest way to achieve that. Once you start giving a lot of options, then there are a lot of questions you need to answer because you can you before you get into the primary task of actually building whatever it is that you want to build.
 
Ryan_Carniato:
Yeah, no, definitely. And when you have opinions, you can streamline it and you can cater to that. And you remove a bunch of questions or stuff that gets them off. You can get that. Really important thing for Framer is that if someone can download the project, I feel, and then one click deploy, even if it's just the Hello World version, and see the whole end-to-end story. Maybe run the project locally, run the tests, then deploy it. you know, within the first five minutes or whatever, then like, like that's incredible power to put some in someone's hand. But again, starter
 
Dan_Shappir:
So
 
Ryan_Carniato:
templates could do that as well.
 
Dan_Shappir:
you're saying it's not a surprise that a lot of these meta-frameworks companies also have a hosting business to go along with it.
 
Charles Max_Wood:
hahahaha
 
Ryan_Carniato:
Yeah, I mean, well, the thing is the the like library itself, you they're all open source and even the frameworks generally are open source. It's hard to try and run this stuff on open source people almost expect to get it for free. And it's a numbers game you want like as many people using as possible people aren't going to like it's not specialized enough for people to pay for it. So like where are you going to make money? Well, hosting is the natural like extension of that. The tricky part is I think that was like good for a time and a bunch of, you know, few companies got in at that point. Um, but I think, you know, there's only going to be so many hosting providers and you know, that can fit in, you know, in addition to, you know, the huge things like, you know, AWS, you know, right. Um, and in fact, a lot like with the cloud flare, um, being kind of an exception, most of the other hosting solutions are kind of built on top of another platform, whether it's Dino built on Google cloud, I believe. or Netlify and Versel both working primarily off AWS, but they also have their own Dino or Cloudflare edge functions respectively. So it's not surprising that those go together, though I don't know if I'm going to go create the next framework and try and get VC funding if hosting will take me very far these days.
 
Dan_Shappir:
Getting back though to that concept, I recall, I mentioned it before we started recording this episode, I recall that a while back, I guess while you were still thinking about whether or not you want to do the next JS thing, that you kind of said that while a single person can create a framework, it's obviously a very big task, but it's still something that a single person can do, In case in point, you've done it. And you might say that Rich Harris has also done it and a few other people. That creating a meta framework, again, you said, I don't actually have an experience in that, is something that's more suitable for an organization, that it's difficult for one person to do because of all the integration work that needs to go along with it. Or am I misquoting you?
 
Ryan_Carniato:
Yeah, no, you're correct. And when I, I need to like put like a little bit of explanation there, because like, when I say one person could create it, I mean, because you could, you can go, and this is kind of true about the meta framework as well, but I mean, you can go and build a JavaScript framework over a weekend if you know what you're doing, you could probably like put some pieces together and then, you know, you know, spend the next several weeks tinkering it as a single person for it to. get anywhere or succeed, it takes a ton of people. And the open source community is very, it's amazing that people come together to work on these kinds of projects to actually see them get there. It's more than the effort of one person, but it could start with one person kind of doing that. But the thing is what I felt is like, once the framework gets to a certain point of maturity, and you have a good community around it, the surf like... The core surface area and the ambition of it is small enough that, you know, a small set of maintainers, you know, could probably pull it off, you know, out in the open. Um, you know, you, you, you could do it mostly off people's volunteer if they want to spend the time kind of thing. Meta framework takes on just so much more that, and this is something that I realized, like even if it's just a combination of existing libraries put together. the combination of that comes with expectation, right? Because it's like more than the sum
 
Charles Max_Wood:
Mm-hmm.
 
Ryan_Carniato:
of its parts. And that means like, you know, now as a framework, if something, you know, happens weird during deployment, you're like, well, see what's wrong with your config, see what's wrong with, you know, how you're using your build system or your bundler or what's up with the deployment. You just kind of send people to kind of do it. You help them if there's bugs in the framework, you know, but generally speaking there. But with the meta framework, it's like, oh, no, no, this is your responsibility now. So it's like, there's a whole range of stuff that comes around infrastructure, deployment, bundling that are kind of additional to what you'd have in the, uh, the framework itself. Plus it's, it's, you know, any specific features, um, you know, like library stuff, like, as I said, my perspective is like the core of the framework is like this tight machine that, you know, as it grows, yeah, it probably needs more attention in terms of like people maintaining it, but it's actually maybe doesn't change that much. But when you start talking about the application of those things with like libraries, you know, I don't know, like, I mean, similar to like component libraries, you know, or when people start making those kinds of things, there takes like more scenarios that are just further from that core that require more work. And I think the biggest thing on the meta the expectation of support like that, like this is a product. And, um, as I said, some of this could just be like perception because of the competition, like where the line is, like if everybody was just by themselves or with a small group of maintainers building a meta framework, maybe it'd be different, but when some options are being funded, like, you know, next or remix or whatnot, um, you Gatsby, um, like it's what they can offer is. you know, considerably more. And it seemed very obvious to me, you know, maybe not at the beginning. I knew that it was ambitious, but like the more I worked on it and looked at the time you spent, you know, fixing bugs and the kind of work you have to do to maintain these things, it was just like this. This is a lot, um, because like, there's just so many, like now I'm worried about mono repos and different configurations. Like you've taken on all the pieces to make an app go out the door. Whereas just the. framework, which maybe is ill named, you know, like the core framework or library. That is a bit outside of your scope. And it's a considerable difference in scope, I'd say.
 
Dan_Shappir:
I understand. So given the fact that despite that initial hesitation, trepidation, call it whatever you will, you still decided to do, that you needed to do solid start as a meta framework, as your own sort of Next.js on top of solid, like Next.js is on top of React. And you've done it. To my knowledge, solid start is now in beta, right?
 
Ryan_Carniato:
Yeah, yeah, I mean, I did push back for about a year, more than a year, really. I said it was like 2019, 2020. Um, but I knew that people were going to build these things and that we needed it. It was an important part of the story, but I was hoping someone else would. And it actually, I worked with a few people who made one, a couple of like start starters to it. Like, uh, there's a project called liquid for a while, which was supposed to be like, you know, play off solid where they were working on a, um, a metaphor. That was a meta framework on solid. There was the guys from Builder before they picked up Mishko and Quick, Steve was looking, he created something called Snap, which was a solid meta framework. So like there was people playing around with it and I was like, okay, so I focused on stuff like the router and like core pieces that I knew would be useful. And I was like, okay, I got nested parallelized data fetching routing and all this stuff. I've got like got the pieces and I'm like, still, you know, we didn't have the framework best practices, people didn't understand things like suspense and transitions. Like, there's just, you know, out of order streaming, there's so many things that I had knowledge on, that, you know, you know, I saw some projects kind of playing around and they, they didn't understand solid specific reactivity. And like, I just knew that I probably needed to kind of show the way so to speak. And I even that wouldn't have been enough, but then beat to was released February 2021 and it added this SSR support and it was a game changer. Cause it was almost like all the pieces that I had were missing, just suddenly were there. And the big thing, the reason VEEP made it so easy was like they can find the plugin system for the client and the server in dev mode into single plugins. So it kind of slice vertically instead of horizontally so to speak. And this changed the way we could like look at plugins instead of like having to manage like four different web pack configs or whatever. Like suddenly it was like one config with a bunch of these sliced plugins and it would, you, you could just author stuff to work on both sides and you just need a simple kind of server start script, so to speak. And
 
Dan_Shappir:
So, just for
 
Ryan_Carniato:
yeah.
 
Dan_Shappir:
people who may not be familiar with the capabilities of Vite, per my understanding, well, Vite is a project that came out of Vue effectively, right? Out of the Vue world. And it's
 
Ryan_Carniato:
Yeah.
 
Dan_Shappir:
essentially a bundler, but a bundler that aside from working really fast and like you said having support for plugins, can automatically generate the bundles both for the client side and for the server side. for debug mode, for production mode, with support for hot reloading. And it has the server built in, which you kind of need if you want to do hot module reload. So you effectively got everything you kind of need in order to build a meta framework on top of it, or something along
 
Ryan_Carniato:
Yet.
 
Dan_Shappir:
these lines.
 
Ryan_Carniato:
Yeah,
 
Steve_Edwards:
Well,
 
Ryan_Carniato:
it was.
 
Steve_Edwards:
to clarify, it's not the bundler. It uses rollup under the hood
 
Dan_Shappir:
Ah, okay.
 
Steve_Edwards:
for the bundling. The big thing about Beat itself was the module reloading using ES modules, which is what made it so much faster, because you're basically using the built-in capabilities of the browser. And that's what makes it so smoke and fast. But for the actual bundling itself, it uses rollup.
 
Ryan_Carniato:
Yeah, it's this crazy Frankenstein, like actually, like the interface is kind of nice for the developer coming in. But when you understand the hood, because yeah, it does roll up. But then when it's doing the optimized builds for dev time and also use the ES build in there as well. So it's like that roll up. It's got ES build. It's like this crazy thing. And the other feature that it has that I think is really cool is. It had glob imports. Again, this is just such a silly thing because you can just get a glob library in that, but just out of the box, it just had a number of these pieces. And I looked at it and I'm like, I realized I was like, I could just take like a solid starter template I have right now, add the SSR entry point, have it basically work with just like this one plugin that'll do make the server client build in the dev build. And then I can just take my router, import. the files using this glob import and like basically in like a paragraph or like half a page write a really basic file system router. Like the whole thing basically wrote itself. Like I remember like it was in February that it came out and like two weeks later I had like the first version of Solid Start. And I remember it was great because like it wasn't just about you know releasing it to people at that point. I just wanted to like build on it. this test bed to kind of run the stuff. Other than Node, the first adapter I believe I wrote was for Cloudflare. So I could use Cloudflare workers, and I used that to test out streaming deploys on the edge, right? One of the very first things, I think it was in March, we released one of the first Solid Start demo, and it was a Cloudflare workers at the edge Hacker News demo using streaming, out of order streaming. And yeah, I mean, Suddenly I had these pieces and I remember I was like I was like, okay, I just take my router I take my meta head like head library for like the meta tags and I kind of jam these together and then I I knew I knew right from the beginning. There's like a few pieces that I wanted to have And then I think one of the other ones was yeah. Yeah, I had these proxy based RPC calls Essentially so I was like, okay if we control the server and the client Why can't we just like call a function and have it run on? on both sides. So it wasn't nothing fancy. It was just, I basically in the server build, like we could just import different versions of the thing. And then on one side you got like, it just called the function. And on the other side, it basically created a URL based on the path you went through this proxy. And then it just, when you called it there, we'd call a fetch function and... call it on this server. I know kind of funny stuff, but I call those actions. This was like February or March, 2021, I think. And I was like, okay, cool. This is kind of a meta framework. I should, you know.
 
Dan_Shappir:
It I'm really amused because just to detour a little bit about this RPC discussion and there's something we will probably talk about More in the context context of bling But it's really funny to me because people keep in reinventing this the RPC mechanism over and over and over again I mean, I'm old enough to remember korba and decom and and and and now we're reinventing it in the context of the web and even in the context of the web we've got what you're doing, I guess with Tanner, which is bling. And you've got what the guys at Quik are doing, which are doing something that's actually syntactically very similar, although semantically some was slightly different. And I don't know if you know this, but Wix, we had Joav Abahami on our show talking about Velo by Wix. They actually have this RPC mechanism of calling server functions from client side code. Like they built it like, I don't know, like six years ago. So it keeps on happening like over and over again. It's really amusing. And to an
 
Ryan_Carniato:
I think
 
Dan_Shappir:
extent
 
Ryan_Carniato:
it's...
 
Dan_Shappir:
and to extent, you might say even that react server components to an extent are also that. To an extent.
 
Ryan_Carniato:
To an extent, yeah. Yeah, I mean, you
 
Dan_Shappir:
They're
 
Ryan_Carniato:
wouldn't
 
Dan_Shappir:
mostly something
 
Ryan_Carniato:
be a-
 
Dan_Shappir:
else, but they're also slightly there.
 
Ryan_Carniato:
Yeah, yeah, yeah, I agree with you on that. Yeah, you know what it is? It's because when the rise of the single page app came up, we wanted to distribute everything, right? So like, like, our PCs were popular, like way back, like even like a sense, like some, some nasty stuff, like soap or whatever, like, and other, you know, things we went. And then we were like, okay, no, we need to distribute to have stateless servers, remove the load, you know, and scale up and all this stuff. So we rest API's became popular and then we got, you know, microservices, the whole thing burst outwards and it kind of went coincided with the rise of the single page app, which was like, okay, let's, you know, have these clients, smart clients that like maintain the state. And I feel like those things coming together at the same time worked really well, cause then it was like, okay, you had, I, what's the term? It's like jam stack, right? You, you had your like JavaScript framework and the client. and then your APIs, right? And that was just like the design, you had these distributed rest APIs. I think RPC starts looking more, how should I put it? Like it looks more beneficial in like the front end web world when you're dealing with monolithic architectures. And one of the ones, the thing that brought RPC back this time, in my opinion, although it wasn't my primary driver, I just was like going like, why do I want this extra complexity if I'm just starting up here, was TypeScript. Because, that you could literally, if you put the function in this isomorphic code, because most stuff that we have now runs, you know, on client and server when you're like writing a JavaScript modern declarative JavaScript app, it was like, okay, if I can just declare a function and then just call it in both sides, what's cool about this function then suddenly is like, it has the types. So like, you could literally be in a client component, have the server function and the types line up. And I mean, It's so funny back in languages and stuff. They're like, yeah, of course type systems, you know, like, but like for JavaScript world, you know.
 
Dan_Shappir:
Yeah, I mean the whole point of RPC. Well, for those of our listeners who don't know what RPC stands for, RPC stands for Remote Procedure Call, which basically means that you invoke a piece of remote code running somewhere else, usually a different computer, but it might be a different process on the same computer, as if it was a regular function call. It looks like a regular function call within your own, you know, process. but it's actually running somewhere else. So effectively, the parameters that you're passing in undergo this process called marshalling, which basically transform them into some sort of representation as JSON or XML or whatever, sends it over the wire, other side gets it, deserialize or demarshalled, runs the, and the other thing is that the client side is effectively quote unquote blocked on this. on this call, so it behaves as if it was synchronous. Although in JavaScript, that really means that you're returning a promise, and you can do an await on it.
 
Ryan_Carniato:
Right.
 
Dan_Shappir:
Although in other programming languages, where they had that mechanism, they were actually blocking, because they were multi-threaded. So they would actually block that particular thread until the procedure returned.
 
Ryan_Carniato:
Yeah, yeah, no. These pieces together made it really seem like a powerful mechanism. And I saw once I was doing that, I'm like, oh, this is great. I can use these not only to do mutation, because I wanted a mutation story, but I could use these also to do the data fetching. And this was important to me with Solid, because Solid's a reactive library. So we do changes in a fine-grained way. based off these signals, which we talked about a bit at the beginning. And one of the things that we saw is like, things like get server side props are very tied to the specific, is an export that's like part of the framework. And it was like, this is async, this always runs on the server. And in our isomorphic world, we do need to call out what only runs on the server because most code runs on both sides and you have to go like use this on the server only. And I didn't want the data fetching mechanism to be that this new thing that I added in the framework, so to speak. Again, this is about looking at the primitives. And Solid's router already had something called like a route data, which was this idea that whenever you change to a route, it could be nested. We could basically run this function and fetch all the parts of the route and do the data fetching in parallel. I used this in client side benchmarks for years. And I was like, I just wanna pull this over here. I just want my API call or resource in Solid it's called run their function always on the server in one place rather than do the server initially and then do the client side afterwards. So these RPC calls made a lot of sense to me in terms of coming up with a pattern. So I didn't have to introduce a specific mechanism of the framework specifically. And don't get me wrong, these actions things I had were a specific mechanism, but the reason that I liked it like this was if someone brought in like TanStack query, you know, some other like library for data fetching, you could just go, OK, now TanStack, you know, use query, always run this on the server. Like basically, this mechanism, because it was isomorphic, it could, for the like the triggers for the fetching, it could basically. leverage reactivity for fine-grained. You could have like multiple loaders on the same route. And if one query parameter change, only update the one that changed, like fine-grained wise. And then you could also basically have that power with any third-party library that like you, like Tanstack query, you know, use query worked just as well
 
Charles Max_Wood:
Mm-hmm.
 
Ryan_Carniato:
as Solid's own resources or turbo query or whatever, like data fetching Apollo, like maybe not Apollo because they have the GraphQL
 
Dan_Shappir:
Just
 
Ryan_Carniato:
stuff, but.
 
Dan_Shappir:
to see that I'm getting what you're saying, the fact that everything looks like a function and behaves to an extent as if it were a synchronous function enables you to basically look at all these things kind of the same. That's what you're saying?
 
Ryan_Carniato:
Yeah, all these APIs that are like promise to signal in Solids case or promise to state could be pluggable. Any third party library could basically be pluggable with this mechanism because they all just accepted functions that return promises, basically promise factories.
 
Dan_Shappir:
So once you basically resolve the general case, which is I pass in parameters, I get back a promise, then anything that can handle that scenario can plug in, basically is what you're
 
Ryan_Carniato:
Yeah.
 
Dan_Shappir:
saying.
 
Ryan_Carniato:
Yeah. And
 
Dan_Shappir:
And you didn't
 
Ryan_Carniato:
yeah, any.
 
Dan_Shappir:
have to invent this sort of sophisticated custom mechanism like React Server Components.
 
Ryan_Carniato:
Well, I mean, reactionary co-incidence are a different thing. I'm not gonna go, we will go there,
 
Dan_Shappir:
Yeah,
 
Ryan_Carniato:
but.
 
Dan_Shappir:
I know they're different because they're out For them the fact that it's RPC is almost incidental. It's it's a
 
Ryan_Carniato:
Yeah.
 
Dan_Shappir:
side effect of what they're trying to achieve It's for
 
Ryan_Carniato:
It's
 
Dan_Shappir:
for them. It's
 
Ryan_Carniato:
the
 
Dan_Shappir:
about
 
Ryan_Carniato:
thing
 
Dan_Shappir:
the
 
Ryan_Carniato:
that...
 
Dan_Shappir:
data flow for you. It's about function calls for them. It's about the data flow. I think
 
Ryan_Carniato:
Right,
 
Dan_Shappir:
Kind of like
 
Ryan_Carniato:
the reason-
 
Dan_Shappir:
observables versus signals again
 
Ryan_Carniato:
Yeah, I mean, it is at a different level. For me, it was, it was, this was allowed me to get rid of get server side props and not, and loaders essentially, this is how I could unify the loader pattern with the client only pattern. Cause again, so I'll start in my head. I'm like, this is a starter. So someone could go in and make a non SSR version of solid start. They can just go in and just use the same patterns and have the same data loading experience and everything in the file system routing with a pure client side rendered single page app. And it also works in SSR. You just go SSR mode. you know, like, and essentially now it's server rendering and then you can static generate and you know what I mean? Like, so I, so these all kind of scale them because any third party query library built on solid internally uses our resource mechanism. Um, this is also important because I knew they would, because basically we internally have this promise to signal primitive. Um, and the reason this is important is because this is how suspense. works or transitions tie into it. So all the third party solid libraries are data fetching, use this internal primitive. Now these actions or whatever, later we drop that name, but we changed the meaning of it, but they could basically get passed into that resource ultimately. And what this meant for the people writing these libraries, which was amazing, again, primitive power here, is that not only did the instantly work with suspense now, that meant like out of order streaming instantly worked. You could just like, literally pick up, you know, again, I mean, keep on using 10 stack query, but you can pick it like, you know, that's, you know, solid query, the Quimly React query. You can just literally just stick it in your app and presto, it will, you know, maybe use the server function here and have it call first time on the server, like you expect to SSR, do this out of order streaming with suspense, auto serialize the data. You don't have to worry about it. And then they tie in some hydration lifecycle hooks so that on the- in the implementation. So when it starts up, it automatically precedes the cache with the data and doesn't refetch it. Everything streams in as it's supposed to do and using the suspense and then you're good. And then when you do a mutation, do the invalidation, go through the whole cycle again and it would work as naturally as if the framework like the meta framework had built it itself. All the pieces were there pretty much automatically. with these libraries, you can just go pick it up off the shelf. And I knew that was what I wanted to do here.
 
Dan_Shappir:
By the way, just to clarify, and again, I know that a lot of people are familiar with the term because of the use in React, but I don't know if there's a formal definition that I've seen. But basically a suspense boundary is that point within which everything needs to be synchronous with each other, but everything to the outside of it can be asynchronous with it. Is that the proper definition or is there a better one?
 
Ryan_Carniato:
Yeah, that's interesting way to put it. It's basically, yeah, I guess that's fair. The idea is you have certain async state that if at some point it isn't resolved, showing it would make your view
 
Charles Max_Wood:
Thanks for watching!
 
Ryan_Carniato:
inconsistent. That's the whole thing. So like essentially you can wrap a boundary around what part of the view. goes together, like how much of it you're okay throwing away based on this async states. I said the same thing almost backwards, but like essentially if you're doing some data fetching, based on where you read it, it walks up to the nearest suspense boundary and goes, put a placeholder here. Or in the case of streaming, it's like everything outside of the suspense boundary is okay to stream to the client. And then we'll wait to stream this part. which means that what you see is you actually see the shell of the app, a loading placeholder. So the second, like let's go to the beginning, sorry. Second, the server gets the request, starts rendering, starts fetching the data, hits a suspense boundary, keeps on rendering, gets to the, we call them resource reads or the, you know, like awaiting and react opponents, goes, okay, this needs to suspend. Kind of finishes off there. And React's case tradition is throw a promise, but now they have async components, a little different. But in any case, you kind of stop there. And then the boundary goes, okay, I'm suspended. But if the thing outside isn't suspended, it actually to the client gets the shell of the app and streams this placeholder. So you're looking at the screen with like a loading spinner, let's say. But the data fetching happened immediately on the server, not on the client. Even if it looks kind of like client-side rendering. the data fetching happened earlier. Then while the connection's still open, when the data finishes, it actually renders that HTML for the inside section, inside that boundary, on the bottom of the document, kind of streaming it in. And then when it gets that, there's a script tag inline that actually inserts it to replace the placeholder. And it continues hydrating from there.
 
Dan_Shappir:
Yeah, I think you gave a really complex technical explanation that kind of said what I said before, but bottom
 
Ryan_Carniato:
I'm gonna
 
Dan_Shappir:
up
 
Ryan_Carniato:
go
 
Dan_Shappir:
like
 
Ryan_Carniato:
get some water.
 
Dan_Shappir:
you
 
Ryan_Carniato:
I'm
 
Dan_Shappir:
said.
 
Ryan_Carniato:
gonna go get some water. I'm gonna go get some water. I'm gonna
 
Dan_Shappir:
Yeah, it's about a really sophisticated way about handling the fact that you want to render what you can, but some pieces are still missing, and when they'll get here, we'll use them. And until they do, we are probably showing a spinner or something, which is why I like to joke. that the key difference between an old style web app and a modern web app is that we used to have one big spinner. And these days, we have lots of small spinners.
 
Ryan_Carniato:
Right. Although suspense hopefully gets us back to larger spinners again. I think there was a time period with client side rendering where we had the most spinners, right? Because like, like we pre-suspense client rendering, you'd like load a page and then you just see them like all kind of come in and cascade. Suspense because of that inversion of control, where it's based on read and then you set the boundary. Hopefully that like makes it more stepped, so to speak. So instead of having like a bunch of them, you can go like look. If I got like 50 images here, I'm not going to bother like spitting them all in. I mean, you might for images, but like essentially you're like this block when it's finished, show it. Um, and that's the power of, of it. It lets you group it.
 
Dan_Shappir:
By the way, I have to say that Jack Harrington, who's one of the hosts of React Roundup, also does a whole lot of videos, did an excellent video
 
Charles Max_Wood:
Mm-hmm.
 
Dan_Shappir:
in which he literally shows how this mechanism works in Next.js and Remix, and also he builds it by hand on top of Vite. This whole
 
Ryan_Carniato:
Nice.
 
Dan_Shappir:
thing that you talked about, the suspense boundaries and how the stuff keeps streaming and arriving and gets inserted into place. So if somebody is really interested in the technicalities, You can probably put a link to that video in the show notes.
 
Ryan_Carniato:
Yeah, that's very cool. Where was oh yeah, right. So we, we had these primitives and I kind of like knew this is where I wanted the baseline. So it's like, okay, if this is like summer 2021, like, well, why, why isn't this thing out yet? Um, well, building out a lot of adapters and stuff did, did a bunch of work and we wanted to improve the data fetching story. Um, or sort of the data mutation story. Um, and one thing that I saw during that time period was remix and spell kit. Um, basically they both, a couple months later, after these RPC streaming demos I talked about released, uh, early versions of their, uh, stuff. And it's funny. It was like within the same week, rich Harris and the, the Ryan Florence and Michael Jackson both gave demos where they, um, basically showed off, uh, progressive enhanced forms,
 
Dan_Shappir:
Hmm.
 
Ryan_Carniato:
right? And I was like, okay, yeah, I want to, I want this too. And the thing is.
 
Dan_Shappir:
And again, if I can interrupt you just to clarify to our listeners really briefly what this means, it basically means that if the JavaScript is already loaded, then you're working like an SPA. That means you intercept the form submission and you send the data using some sort of AJAX, like a fetch command, and you handle the response using JavaScript to do everything as a single page application. But... If the JavaScript isn't loaded or simply hasn't finished loading yet, and you click the Submit button, then it basically just works like a regular old HTML form and does the actual action. And the funny thing is that you, as a user of the framework, don't have to distinguish between the two. The two just, on the server side, the two go to exactly the same endpoint from your perspective. So, in effect, it just works. And that's one of the things that I think that Remix was the first to really promote it, was this whole concept of progressive enhancements. That if you've got the JavaScript, you leverage the JavaScript. But if you don't have the JavaScript yet, you make do without at least until it arrives, maybe not at all.
 
Ryan_Carniato:
Yeah, it's always interesting to me because like, I don't know who was first because like, I mean, it's hard to kind of tell on that. Like, cause I mean, Rich Harris had the, that one talk and maybe that was later in the year, but they both actually did the form demo. I think remixes was much nicer because they fooled everyone because remix. I remember this later sitting there and they're doing a stream and they're like just playing with remix and showing off the features and then like 45 minutes. No, it was longer. It's like an hour in there. We're like, Oh, by the way, JavaScript has been turned off in the browser this whole time. And like no one like watching the stream even picked up on it. They literally were building out this app, adding all the remix features, showing all the stuff. And then it was like, oh yeah, we actually weren't using JavaScript. Let's turn JavaScript on so we can show you how to do optimistic updates. I mean,
 
Dan_Shappir:
That
 
Ryan_Carniato:
I could
 
Dan_Shappir:
is cool!
 
Ryan_Carniato:
talk. Yeah, I
 
Charles Max_Wood:
Yeah.
 
Ryan_Carniato:
could talk a ton about that. But I mean, essentially the biggest thing that remix had figured out, because progressive enhancements and forms have been a while. done similar things manually was that they realized a pattern around optimistic updates, which was that most systems like Tanstack or Apollo stuff had this idea of cash writing for optimistic updates. See, the thing is what's happened over time, and I've talked about this before in a couple of places is that cash writing is always like a recipe for challenges. Let's just say that. And people had gone so tired with their big GraphQL clients that they weren't even bothering doing all this cache mutation, they'd just be like, screw it, I'm going to invalidate. And we saw this all the time with React query, test query, essentially React, where people had gone to a point where instead of trying to update the cache, they'd be like, let's just do the mutation, then invalidate the keys that changed. And it's two fetches, but whatever. And Remix kind of took that mentality even further in that. Even for those libraries, doing mutations would be like a preemptive cache update. And then if it failed, you rolled it back. Otherwise you replace remixes, like get rid of the cash altogether. Like at least the client side, JavaScript manage class, you can use the browser cache,
 
Dan_Shappir:
Yeah,
 
Ryan_Carniato:
but get rid of that.
 
Dan_Shappir:
I think that's the key point. And I think, Steve, this is a saying that you like to give, to say, which is that there are like three different hard things, well, you say it better than I do.
 
Steve_Edwards:
Oh, the hard three hardest, the two hardest things in computer science are caching naming things and off by one error.
 
Dan_Shappir:
Exactly. And basically, literally everybody does caching wrong. And everybody tends to build caches, their JavaScript caches on top of the HTTP cache, which is to an extent, like from my perspective, like the worst thing that you could possibly do, because the server, it's a server that decides how long things should be cached. And once you add the JavaScript client side caching, it means that you're basically ignoring whatever caching the server is saying. And if you're using the HTTP caching properly, then you don't really need anything else. Yeah, go for it.
 
Ryan_Carniato:
And that was like the insight with Remix. I don't know if they acknowledged this in their head, but for me watching the trend line, we've already seen everyone invalidating and then they realized like, okay, they're optimistic updates. We're just gonna feed your request back in as a ephemeral state essentially, like this temporary state. So you just get whatever's in flight as state so you can render it. There's your optimistic update. Like, and it's harder than maybe they do like really truly global optimistic updates, but optimistic updates are hard anyways. But once they did that, they're just like, Now we have no reason for that client side cache outside of using the browser's cache. And suddenly like this simplification felt, you know, really, really powerful. And I, I, it's a huge thing because this is influenced obviously
 
Charles Max_Wood:
Thanks
 
Ryan_Carniato:
our,
 
Charles Max_Wood:
for watching!
 
Ryan_Carniato:
uh, solid starts, um, APIs and it influenced a react server components and next, uh, APIs here.
 
Dan_Shappir:
Well, that brings up an interesting point, because their simplification to an extent was saying, you know what, all this work you've been doing with, let's say, Redux, you don't need that. Just keep the state on the server side and forget about all this global client-side state that you need to manage and keep in sync to an extent. But you're not saying that exactly, because for you, that client-side state is what uh, solid ears.
 
Ryan_Carniato:
Right, right. I mean, it is interesting because like, that understanding there for me happened earlier on because I think there was a time period, I don't know, 2018, 19 when things like SWR and React query came out and people suddenly realized like, okay, I don't need read. I mean, even before that, when GraphQL came out, like Apollo, people started going, okay, if all my states in Apollo actually don't need Redux. But Apollo itself is a very crazy, sophisticated state management system. And then SWR and 10 stack or React query came out and like, look, you don't need a 40 kilobyte library to do this, you can do this in like, five or 10 kilobytes. And then remix was like,
 
Dan_Shappir:
You don't need that, you just need fetch. Ha ha ha!
 
Ryan_Carniato:
yeah, right? Like, so like it went down the scale. I mean, you just need your router essentially, but the router was present
 
Dan_Shappir:
Yeah,
 
Ryan_Carniato:
in
 
Dan_Shappir:
the
 
Ryan_Carniato:
all
 
Dan_Shappir:
router,
 
Ryan_Carniato:
of them, but yeah.
 
Dan_Shappir:
exactly.
 
Ryan_Carniato:
So like, and the approach, with solid it's interesting because you're right, reactivity is a client side trigger mechanism, but it's fairly lightweight. So like it depends, like it's perfectly fine to delegate a lot of the stuff to the server, right? With solid resources, we base the API a lot on react query, like that kind of thing. It's lighter weight because it's built into primitives in the library itself, like into the actual core solid, but like essentially we just needed like this promise to signal mechanism that could handle serialization. And then we have ways that you can create your own cache, but we didn't ship with the cache. That's how we made the savings, right? Cause React query and those ship with the cache. So our solution is like, it's not in the router exactly, but it's also doesn't have a bunch of the caching stuff and like the extra stuff that SWR or that. But yes, there is an acknowledgement that, compared to remix, I did have to... figure out what we're going to do. Cause remix was kind of very streamlined. And it's like, this always runs on the server. And I was like, I don't want to make that decision. And I want any library. Like if you want the client side cash, you can't. Cause there are apps out there that like, it is difficult to take that invalidate everything mentality. Like it is
 
Dan_Shappir:
That invalidate
 
Ryan_Carniato:
especially on the more app
 
Dan_Shappir:
mentality
 
Ryan_Carniato:
side.
 
Dan_Shappir:
works really well when you're building crowd applications, I think.
 
Ryan_Carniato:
Yes.
 
Dan_Shappir:
And it works really well when you're building e-commerce application, which is not unsurprising given their relationship now with Shopify. But
 
Ryan_Carniato:
Exactly.
 
Dan_Shappir:
it's not that great maybe if you're building sophisticated dashboards, for example.
 
Ryan_Carniato:
Right. So I wanted to leave it open, but for Solid I wanted my own primitives like Remix. So what we did was we to connect, this is how we finally put the pieces together, was we took Solid's resources, which was the more basic lightweight version, and we added actions on top of these kind of server functions. I added the term action again. And it was around this time that Nikhil, who started joining the team, kind of working on Solid we're playing around with these proxy things. And he's like, why don't we just use a compiler? Like we can just like essentially be like, like just server, say this wrap it with a function, call it server. And you know, instead of doing this proxy thing you're doing, we can just generate the URL at compiles time instead of via proxy.
 
Dan_Shappir:
Was this done independently of what QUIC is doing?
 
Ryan_Carniato:
Yeah, yeah, we, I mean, we didn't, we weren't really, I mean, I was aware of QUIC, but QUIC wasn't really solving, QUIC was splitting stuff into modules so they could lazy load stuff on the client, you know, like piece by piece, but I wasn't really thinking about it this way because like, it's almost like the opposite side. QUIC was like, how do we handle all these boundaries for client code that now needs to run in these little bubbles? And we were, it's funny, like in hindsight, I can see the similarities. We were like, how do we... create these bubbles for server code to run in these books. Like it's the opposite direction, essentially.
 
Dan_Shappir:
So you were like, things were like bubbling up to the server and they, and in their case, things were like, I don't know, trickling down to the client.
 
Ryan_Carniato:
client. Yeah, exactly.
 
Dan_Shappir:
Okay, interesting. And people
 
Ryan_Carniato:
So
 
Dan_Shappir:
can see
 
Ryan_Carniato:
I didn't.
 
Dan_Shappir:
me like I'm waving my hands up and down.
 
Ryan_Carniato:
Yeah, like it wasn't immediately obvious for me that it was kind of the same thing. Because I'd started from these proxy RPC things. And there are differences in the rules, which I can get to in a minute. But essentially, we were we realized I could make these primitives I server function, like the ability to make a function server, I could make isomorphic primitives again. So I was like, why don't we make like a route query and a route mutation, which we ended up calling route data and route actions, primitives, and they could work without the server function or with it. So we kept that isomorphic thing so that we had this ability there, again, built off the resource mechanism. And the difference is the actions would also like you'd go create action and you could either just call it with the arguments. Or you can go dot form and get a form component that you could put on your page, like remix. So it basically handled both progressive enhancement and non-progressive enhancement. You can just call it as like a function, like a promise, like, like just a server function. And the key part about it is because we need these pieces because they need to tie together with the knowledge of the route so that when you posted a form, it could automatically invalidate all the data loaded for that particular route. Like
 
Dan_Shappir:
Yeah,
 
Ryan_Carniato:
along the route.
 
Dan_Shappir:
but it's important for me to stress, and correct me if I'm wrong, we use the term progressive enhancement here, but really unlike remix and react, you don't see solid and solid start running without JavaScript on the client side.
 
Ryan_Carniato:
Yeah, I mean, I don't think Remix actually does though, like even when they advertised it, like it's
 
Dan_Shappir:
Yeah,
 
Ryan_Carniato:
a good thing
 
Dan_Shappir:
putting
 
Ryan_Carniato:
for...
 
Dan_Shappir:
it aside, they can do it. I don't know if anybody would actually use it this way. And if people do, they might as well use Rails or PHP or something. I'm not saying that I'm talking about the practicality. I'm just saying that they build it so that it could. You're not building it with that intention. That's what I'm trying to say.
 
Ryan_Carniato:
No, no, no, it completely works without JavaScript.
 
Dan_Shappir:
But then how do you do the whole reactive thing without JavaScript?
 
Ryan_Carniato:
Well, then then then you don't. But I mean, that's the same. How
 
Dan_Shappir:
Okay,
 
Ryan_Carniato:
do you do
 
Dan_Shappir:
then
 
Ryan_Carniato:
the state
 
Dan_Shappir:
it's
 
Ryan_Carniato:
thing?
 
Dan_Shappir:
just SSR, basically is what you're saying.
 
Ryan_Carniato:
Yeah, yeah, but I mean, it has forms and you can post forms with no
 
Dan_Shappir:
Hmm
 
Ryan_Carniato:
JavaScript and navigate links with no job. It's the it's that same experience. I like
 
Dan_Shappir:
Okay, so you did build that.
 
Ryan_Carniato:
Yeah, yeah. So we built it as a hook instead of as like, or as a primitive instead of as like a use act or instead of like a export action export thing. We just made it, you could have multiple actions for pages. You could put the actions actually anywhere along your route. And then basically, so you load your route data at the, with your data functions at the front top. So it could be pulled out, parallelized and fetched. And then you could define, instead of being based on the route. we could do the fetches anyways, cause they're anywhere, cause they're RPC based. And I got this idea from GraphQL, cause GraphQL when you fetch, you have this like tree of data you pull out essentially, like, you know, you, you kind of go through and get all the data you need and pull it out into this tree. But when you do mutations, it's kind of like this flat RPC structure. And that was kind of my mentality here. I wanted the data fetching to be kind of part of the route. So you have nested sections and you can pull the data out, but when you do RPCs, you can define them anywhere to do these actions as many as you want. then it kind of had that same parallel,
 
Dan_Shappir:
Yeah,
 
Ryan_Carniato:
like split.
 
Dan_Shappir:
but just to clarify, you're not actually using GraphQL.
 
Ryan_Carniato:
No, no, no. It was, it inspired the API design of basically having these kind of like this tree, essentially like the page tree for, for the gets, and then doing the mutation via a bunch of like independent RPC calls.
 
Dan_Shappir:
Now that's when you came up with this whole concept of bling, this whole thing that you described.
 
Ryan_Carniato:
Yeah, yeah, exactly. At this point, Solids, like we built this mechanism into Solids, Solids Dart. And like that's basically leading up to the beta release, right? The big headlines of the beta release was swappable file system routing. So you could opt out of it. You could do these data fetching capabilities with RPC calls. And then the last one, I guess I would say, is that we... we did these, what was I calling it? The route data progressive enhanced form stuff that I was just talking about. And we'd been working with Tanner and Tanstack a little bit because we've been building all these, I mentioned solid query and those kinds of libraries. And he was like trying to think of like, okay, if this reactivity stuff's really performance, it would be really good for my libraries, like my table libraries. He saw AG grid, if anyone's seen like, basically
 
Dan_Shappir:
Yeah,
 
Ryan_Carniato:
the solid.
 
Dan_Shappir:
we actually spoke with Tanner exactly about that, like what was it, two or three weeks ago. So hopefully by
 
Charles Max_Wood:
Mm-hmm.
 
Dan_Shappir:
the time, yeah, so certainly by the time people listen to this, that episode will have been out.
 
Ryan_Carniato:
Perfect, okay. So then essentially we had all the pieces and Tenor and I like had kind of talked and when the kill him, we're like, he's like, I just want to do what Solids doing, like Solids start doing. I just want Solids start for React. Like he didn't care about server components. He just wanted these RPC calls. He wanted these data fetching. He was already building a router. He saw the similarities. He's like, can we just like combine our efforts and put this together? He's like, I am in React. where I am sitting right now. He's like, maybe one day I can get to solid if it makes sense, you know, where I'm at, but let's just work together. And we looked at it and we're like, yeah, you know, these pieces are kind of extractable. And at the same time, Nikhil had been busy. This is the tricky part with open source, you know, he was moving back to India and like, I was sitting there maintaining. So I'll start myself just fixing the adapter bug after adapter bug and I'm done. And I had like a Theo in my ear going, Astro's the platform. Astro like this is this is a thing he's been like saying for about a year. He's like he's like you go to Fred and be like when are you gonna realize that like Astro should be competing with VEET not with NEXT and I'm like and like he just kept on like saying that it's funny because Astro's built on VEET so everyone's like looking at him with puzzled looks He's like no no no like what we need is VEET is really good from Like all the stuff we talked about at the beginning stream But what it doesn't give you is like the like it says here, make your server entry. Everything down below that like middleware deployment, like all those kinds of pieces VEET doesn't provide, but Astro is kind of like this agnostic home. And, you know,
 
Dan_Shappir:
Because
 
Ryan_Carniato:
because.
 
Dan_Shappir:
of their plug-in architecture because the
 
Ryan_Carniato:
Sure.
 
Dan_Shappir:
because they're need there what they did with the whole islands thing where they wanted to They didn't really have like a framework built in so they created a mega plug-in mechanism for inserting the framework So you're basically saying okay? I'll I'll I'll insert solid in and then I'll start expanding from there as it were
 
Ryan_Carniato:
Yeah, exactly. And funny enough, I've been working on that integration. It looks like that. Instead of just doing the normal solid island plugin, in the exact same way you just insert the solids, like the start plugin, it's like the exact same thing. And this realization of shuffling, and this kind of coincides with all the timing of the other stuff, was that a meta framework, as we like to call it, consists of three pieces. The deployment. middleware server, you know, kind of like runtime part, the bundler, which is handling all of the, you know, like how do we build this package, module split, do all that kind of stuff. And then the router, which is as much as me and Tanner tried to make it agnostic, today was still a challenge. And we kind of both realized that we will, we'll keep our React and Solid Router separate. We'll just learn from each other in terms of patterns and. Because the router has so many ties into the framework in terms of like change management, like the reactivity, like we had some challenges between, you know, reacting mutability and solids mutability and like making them play together. We were just like, okay, let's, let's not worry about that, but we can isolate those like split into those three pieces. And when you look at it from that perspective, um, Astro was, you know, very reasonable approach for that first part, like setting up the middleware and the deployment adapters, right? Everyone, every framework remakes that, uh, every, sorry, every metaphor, Nuxt and there are other agnostic solutions like Nuxt has I think on JS or something or yeah I think that's on it but like there's a bunch of ones out there but we were just like look Astro is already this kind of agnostic home let's kind of work with that and not have to worry like leave the adapter stuff. The bundler side is interesting because you're kind of like what do I do here? could this be made agnostic? And that's when we started looking at what we'd been doing in Solid. We had those server functions I mentioned, like the RPC calls, but we were also using them for stuff like saying, like doing lazy imports for stuff that was only client only. And we were using them also for islands. We'd made like an islands almost server component like solution experimentally for Solid. So we had like, again, like island function. And it's kind of funny that those ones actually haven't got the dollar sign yet. Uh, these days you mentioned that quick has, you know, the same kind of semantics, like the server dollar sign. We added the dollar sign because of quicks influence, because I was looking at it right before beta release. And I was like, man, no one's going to understand like server is special. How do we make it like show people that it needs to like, like separate out? And I'm like, let's, let's do it like, you know, quick, you know, like if you put a dollar sign, this is a clear serialization boundary. Let's
 
Dan_Shappir:
It's basically,
 
Ryan_Carniato:
just
 
Dan_Shappir:
it's
 
Ryan_Carniato:
do.
 
Dan_Shappir:
an indication both to you and the compiler. Obviously, the compiler
 
Ryan_Carniato:
Yeah.
 
Dan_Shappir:
doesn't really need it. The compiler can make do with anything, but it's, you know what, I'll backtrack on that. It's really, it can be said to be an indication to the compiler, but it's really an indication to the programmer, telling the programmer something different is happening here. This is not a run of the mill function, scope, whatever. It's something else.
 
Ryan_Carniato:
Yeah, yeah, for sure. And it was fun because like, that was a realization last fall right before the beta release. And then I met with the quick guys when I was in conferences. And like, I met with Manu and he was like, I saw that thing you're doing, you know, we could do that in quick really easily. And I'm like, I know, like, I realized like after the fact, when I add the dollars, and I was looking at them, like this is like you guys, like you guys already have the serial closure stuff. So yeah, it only took them a couple months to just flip out like their own version of that as well. Which is funny, because sure or not, like the react proposal, the next 13 proposal for mutations is still not officially out there. But if you look at the next repo in the Canary branch, you can see similar things. They have a, they call it use server, but it also has a similar mechanism around these RPC calls that again, do kind of a similar thing. And you start seeing these primitives. So I was talking about the bundler for me. or for us, bling is kind of like our idea of what bundler primitives would look like. It's their macros essentially, and there's different ways to tackle this. We like the decorator form because it lets us like configure them a little bit easier. Like we can
 
Dan_Shappir:
I
 
Ryan_Carniato:
pass
 
Dan_Shappir:
think that
 
Ryan_Carniato:
arguments
 
Dan_Shappir:
macro
 
Ryan_Carniato:
and
 
Dan_Shappir:
is
 
Ryan_Carniato:
stuff.
 
Dan_Shappir:
the perfect name for it, by the way.
 
Ryan_Carniato:
Yeah, because so, you know, whether it's server dollar sign, island dollar sign, or whatever we want to call it, you know, secret dollar sign, like this was only on the server client only, like we're still playing around with the potential there. Some people have taken this pattern even further and created whole TRPC clients. There's a there's something out there called PRPC, which is like the bling inspired TRPC client. I think we need to figure out a way of almost standardizing on building these things so that like what's cool about functions is they're kind of composable. You can like wrap functions and functions and you pass arguments to them. It gives them a little bit more power than say like the I think then like the use directives. It's interesting though, because there's a bit of competition because obviously React is like saying use client use server and we're like, we're like these yeah macros work a little different but can accomplish the same things right because we could use our you know our client component or island. thing to generate React server components for a React-based framework, and then use those same mechanisms to do something different for a different style of framework. So we've been kind of playing around with this idea of these macro bundler primitives to handle the bundler side. So we did deployments, bundler, and that just leaves us with worrying about the router, which for me is a lot simpler of a proposition because that's where I started with. I was working on my router. before I picked up this whole thing. So that's like the big wide scope look of it. Cause then I got Astro doing the deployments, working with the community on these bundler plugins. And then, you know, that just leaves basically the router. And then we have essentially solid start being those three pieces together. And it...
 
Dan_Shappir:
So basically, like Viet would raise the floor for you with regard to bundling, Astro raised the floor for you with regard to deployment. And you basically just really needed to go all in on the router.
 
Ryan_Carniato:
Yeah, yeah, that's the plan now. Solid start today is all the stuff that I've been working on for the couple of years with the contribution from the community. But I am slowly by slowly, funnily enough, moving the pieces around a bit. Bling is taking over all the server function stuff. Astro taking the deployment adapters and base middleware kind of stuff.
 
Dan_Shappir:
Wait a minute, so
 
Ryan_Carniato:
And
 
Dan_Shappir:
Bling
 
Ryan_Carniato:
the.
 
Dan_Shappir:
is a separate project?
 
Ryan_Carniato:
Yeah, it's under the Tanstack organization right now,
 
Dan_Shappir:
Hmm
 
Ryan_Carniato:
because what's cool about Bling is, sure, we're using it with Solid Start, and Tanner's using it with what he's working with. He's making a Tanstack Start framework. But we've seen people play with it using Nuxt. We've seen people play with it using Analog. Like, basically, across the VEAT ecosystem, you can just install this project and now have server functions in your
 
Dan_Shappir:
And besides
 
Ryan_Carniato:
framework.
 
Dan_Shappir:
server dollar, what else is exposed as part of bling's API?
 
Ryan_Carniato:
Right now it's server dollar, secret dollar, which is like a server only thing and import dollar, which means it's like, this one might go away obviously, but it's an idea of inline modules.
 
Dan_Shappir:
Hmm. Oh, yeah for something like web workers or something like that
 
Ryan_Carniato:
Yeah, I mean, we haven't made a worker dollar sign that's on the list. But yeah, the idea is like, the way we've been approaching some of the problems with bling was we were like thinking, what can we do in a single file, because anything we do in a single file, we can then extend to multiple files, right? Like, like we can like, if you don't like that convention, sure use a file system convention, but like one of the experiments that Nikhil did was he took react router, not remix router, react router 6.4. Basically they have these. client-side loader and action patterns. And he plugged in Bling's import dollar sign and server dollar sign, and basically has an SSR app built in VEAT using React router that, and using server, like using their loaders and actions on the client side, but with these dollar sign functions to basically get code split, parallelized data fetching, action invalidated. run on the server only. He basically remade remix minus the forms, all in like one file
 
Dan_Shappir:
Yeah,
 
Ryan_Carniato:
using these primitives.
 
Dan_Shappir:
okay. Look, once you have a working, fully functional RPC mechanism, you can do a lot of things. I'm thinking, you know, we're starting to run, you know, the episode is starting to be long, and to be honest, I'm starting to think that maybe we should bring you and Tanner on again together just to talk in more detail about Bling. because there was so much stuff here that we didn't cover, like, for example,
 
Ryan_Carniato:
Right.
 
Dan_Shappir:
how you would deal with initialization or how you would deal with, and kind of related to that is how you would deal with scopes. And because I mean, server dollar works great if you're working serverless, but I can foresee all sorts of issues if you've got a node server where you want to retain state. for example, between server dollar invocations and stuff like that, especially if you're writing everything in one file. I don't know exactly how that would work. And anyway, I think it's starting to go a bit beyond the scope of our show for today. So, you know, I always love having you on. So if there's, that's a justification
 
Ryan_Carniato:
Haha.
 
Dan_Shappir:
for bringing you on again, I'll jump on it, you know, immediately. By the way, to our listeners, just in case you don't, well, I've spoken about it a bit in previous episodes. I'll be visiting all sorts of conferences during the upcoming months. And luckily for me, I'll be meeting Ryan at a couple of them because I think you'll be doing quite a bit of traveling as well. And we're kind of coinciding a bit. So if you do have a follow-up episode, it will probably need to be after all that.
 
Ryan_Carniato:
Definitely. Yeah, there's, there's so much stuff coming up. I'm looking forward to seeing you in London next week,
 
Dan_Shappir:
Yeah.
 
Ryan_Carniato:
coming up here. IJS, it's going to be fun. And yeah, yeah, we got, we got a few conferences coming. It'll be great.
 
Dan_Shappir:
Yeah, that'll be great. Also seeing Mishko there as well and other people. Yeah, it should be great. So just to finish up before we get to wrap things up and get to PIX, what's the situation with Solid Start right now? You're still in beta, but how, but so on the one hand you're beta, but on the other hand it seems like you're making some really significant architectural changes. Maybe you're not changing the public API, so it doesn't really matter that much. But the question is, is Solid Start something that people should feel comfortable about starting to use, let's say, in production?
 
Ryan_Carniato:
Right, yeah. This is the, this is why I want to get this Astra move as soon as possible. So that as, as, as you mentioned, it, it isn't changing the API surface. Like, um, the source folder just copies straight across. It's the same. In fact, you just have to change the dependencies and change from a beat config to an Astro config. But there's differences obviously in dev, um, some of the capabilities because the adapters are different. And I, I would like, I'd like to see, you know, that get to a good place. I know that there's going to be a couple API changes before we get out of beta as well, just because we have to think forward looking to server components, mostly around the entry stuff, just small stuff around the router. So I'm aware of some changes that are coming. So you always have to take that into consideration for production. That being said, it is the only, I guess, really production, not production, but like, it's the most mature to date, solid SSR solution. So people are using it. Um, there are sites in production using solid start, um, and a post.news, um, recently released their solid start, uh, app in production. Uh, there's, there's other projects coming down the pipeline. I I'm always wary of people about beta cause stuff will change. I don't want people come at me too angry. Um, but, uh,
 
Dan_Shappir:
Then let me
 
Ryan_Carniato:
people
 
Dan_Shappir:
ask
 
Ryan_Carniato:
are doing
 
Dan_Shappir:
it
 
Ryan_Carniato:
it.
 
Dan_Shappir:
differently. Do you have a guesstimate as to when version 1.0 will be released?
 
Ryan_Carniato:
Yeah, it's always so tricky. I know I should try and nail it down. It's the hardest part right now is because other than myself, I'm the only person, you know, like it's my day job. Other people come and go
 
Dan_Shappir:
Ha!
 
Ryan_Carniato:
based on the community maintenance stuff. And even then I can't give it 100% of my time. So it's always hard for me to get the exact estimates on this stuff. The astro migration should be coming through in the next few weeks. And then we have to do the work. It's mostly stabilization, to be fair, like. This has been the problem with the solid start this whole time. It's just been chasing down all the bug fixes because of the amount of scope you get when you consider like all this stuff. And I'm largely hoping, well, anticipating that the move to getting in line with Astro is going to help a lot there on that side so that we can expedite the release of solid start. But yeah, I mean, I would love to get 1.0 out.
 
Dan_Shappir:
I can tell you the piece of advice that my dad used to give to me in this context is that better is the worst enemy of good enough.
 
Ryan_Carniato:
Yeah, yeah, yeah, for sure. It's just, I, this is, we didn't talk about this much today, but we're at a very interesting tipping point right now on the stuff. It's been actually most of the same for years and years and years. And the server component stuff is definitely changing the perspective on stuff. And I have a good idea of what approach we're taking with Soli because we've done prototypes and stuff. I just want to make sure that the API is like basically all aligned with that. And I have to make sure that For Project Legars, we have to make sure that the doc release and everything align as well. Like, so realistically, you know, that puts us at the late summer, early fall probably. So, I mean, I'm just roughly putting it out there, but that's what I'm seeing.
 
Dan_Shappir:
Yeah, okay, we'll be looking out for it. For sure. Steve, do we have anything else before we move on to pigs?
 
Steve_Edwards:
No, I would say that was a pretty solid episode.
 
Dan_Shappir:
Hahaha
 
Steve_Edwards:
But I certainly don't have anything else. So yeah, let's move on to picks. Picks are the part of the show where we get to talk about anything else we want to talk about. May or may not be tech-related, books, movies, games, in Chuck's case, whatever the case may be. So Dan, why don't you go first?
 
Dan_Shappir:
To be honest, I haven't really come prepared today in context of picks. Yeah. Yeah, it is what it is it
 
Steve_Edwards:
Well, you have your one pick that you always do.
 
Dan_Shappir:
Yeah,
 
Steve_Edwards:
You could at least
 
Dan_Shappir:
I have
 
Steve_Edwards:
do that
 
Dan_Shappir:
a couple
 
Steve_Edwards:
one, right?
 
Dan_Shappir:
I'll start well the only pick I have is a bit of a bummer or a downer It's the fact that today is the date that we're recording it is in Israel It's the eve of the Holocaust Memorial Day. So it's a it's a good time to reflect on the fact that You know how you want to avoid authoritarian leaders and make sure that you always retain your freedom of speech And freedom of expression and how important those things are because when we lose them terrible things happen And that kind of ties into my other points, which is you know Supporting us in our struggle for to remain a democracy in Israel and the struggle of the Ukrainian people to just survive in the face of aggression and yeah, those are my unfortunate picks for today. I'm sorry about that, but that's all I have. So yeah, maybe it's time for a bit for some dead jokes to liven up the mood, Steve.
 
Steve_Edwards:
I would argue that we're sort of facing that same fight here, but I'll leave it at that. So lighten things up here. Let's go with the dad jokes of the week. So this is just more of an observation than anything else that pigeons, our lovely birds, must be extremely wealthy because they have no problems putting large deposits on expensive cars. Right? Um, so I used to own a pet store as one of my previous lives, many previous lives. And a man walked into my pet store one day and said, I'd like a dog for my son. I said, I'm sorry, sir. We don't do swaps. And then back when I was looking for a job before I had gained all my mad skills as a software developer, and I went to interview at a blacksmith shop, some real physical labor. And he said, are you good at shooting horses? I said, no, but once I told the donkey to get lost.
 
Dan_Shappir:
Okay.
 
Steve_Edwards:
Thank you. Those are the dad jokes of the week. And I must mention, by the way, I'm sort of a little, uh, patting my own back here. Uh, somebody had tweeted out about podcasts, about view, and I do views on view, another podcast here, and, and somebody replied about the awesome dad jokes that I do. So kudos, thank you to that, uh, little acknowledgement. It's rare, but I knew, you know, there's that silent majority out there. Uh, Ryan, what do you have for us for picks today?
 
Ryan_Carniato:
Oh yeah, no, you gave me a long enough run in that I should think of it. I used like my, my picks when I was here, like a month ago, I'm trying to think of like anything recently. I've been like so heads down recently, like just working on, uh, on, uh, the, this astro migration, I, I can't think of anything off the top of my head. I was like recent TV show. Um, I don't know. Yeah.
 
Steve_Edwards:
What about
 
Ryan_Carniato:
I,
 
Steve_Edwards:
offhand?
 
Ryan_Carniato:
I, I.
 
Steve_Edwards:
I always check both places, off the top of my head and offhand.
 
Ryan_Carniato:
Yeah,
 
Dan_Shappir:
By the
 
Ryan_Carniato:
no,
 
Dan_Shappir:
way,
 
Ryan_Carniato:
I...
 
Dan_Shappir:
you have kids, right?
 
Ryan_Carniato:
Yes,
 
Dan_Shappir:
How old are they,
 
Ryan_Carniato:
yes.
 
Dan_Shappir:
by the way?
 
Ryan_Carniato:
Four and seven, yeah.
 
Dan_Shappir:
Oh, that's a wonderful age. It's amazing that you're able to do all that you're doing, plus the traveling that you're planning and the kids. Kudos to your wife. That's what I've got to
 
Ryan_Carniato:
my,
 
Dan_Shappir:
say.
 
Ryan_Carniato:
yeah, exactly.
 
Steve_Edwards:
Yes,
 
Ryan_Carniato:
Yes,
 
Steve_Edwards:
exactly.
 
Ryan_Carniato:
definitely. Yes, very much
 
Steve_Edwards:
Yes.
 
Ryan_Carniato:
so.
 
Dan_Shappir:
Yeah, my advantage, by the way, is that given the fact that my kids are older, my wife is actually traveling with me. So I'm actually,
 
Ryan_Carniato:
Mmm.
 
Steve_Edwards:
Oh, fun.
 
Dan_Shappir:
so yeah, so all these conference talks are also doubling as vacations, which is a great way to pass the summer months.
 
Ryan_Carniato:
That's it. That's stuff.
 
Steve_Edwards:
Yeah, I'm in sort of a combination of those in that I have two older kids. And as it turns out, they're both about to leave the nest probably within a month of each other this summer.
 
Dan_Shappir:
Oh man.
 
Steve_Edwards:
Still trying to figure how I'm gonna adjust to that. But I also have a just-turned 12-year-old. I talked my wife into a third child a little later in life. So I've got the kids leaving, but I've still got the slightly younger one taken care of. So it's sort of the... best of both worlds, at least in my opinion. I like having my kids here for sure.
 
Dan_Shappir:
Yeah, I can
 
Steve_Edwards:
So.
 
Dan_Shappir:
appreciate it. We are approaching that stage as well. It's interesting times. But yeah, but for sure, the big advantage for us is if we want to decide that we want to go on, you know, to go together on some vacation, we just, you know, as long as I can, like, swing it in terms of how it fits in with the job, we can just pack up and go. which is a great stage to be in life. You're not bringing your family with you on all these trips though, are you, Ryan?
 
Ryan_Carniato:
No, no, too young. And yeah, I mean, yeah, we talked about at one point, like, like, in the summer, we're like, one, one of them, we're like, Oh, maybe we could do that. But, you know, when I go the trips, I'm it's mostly work and travel and work the long flight and then you're you know, I mean, I mean,
 
Steve_Edwards:
Alright.
 
Ryan_Carniato:
I guess we could stick around at one, but you just got to work on timing. What's actually happening is when I get back, we are doing a family trip to Utah, going to Zion and going to Bryce Canyon
 
Steve_Edwards:
Zion?
 
Ryan_Carniato:
and a bunch. Yeah, Zion.
 
Steve_Edwards:
Yeah.
 
Ryan_Carniato:
Yeah. So yeah, doing a bunch of that stuff right when I get back from Finland at the end of that for like a couple weeks.
 
Dan_Shappir:
I do have...
 
Steve_Edwards:
Yeah, that's down Chuck's way, Chuck and
 
Dan_Shappir:
Yeah,
 
Steve_Edwards:
AJ's way.
 
Dan_Shappir:
yeah,
 
Steve_Edwards:
Because,
 
Dan_Shappir:
exactly.
 
Steve_Edwards:
sorry, Dan, about a year ago, spring break, my daughter and I, I've mentioned this before, took a road trip from Oregon down there. And we did the, we did a big loop around Utah where we came down through Salt Lake, Ogden, that whole area, and then went east and went down to Moab and then went down to Monument Valley and came up and did, oh my gosh, can't believe I forget, not Zion, the canyon. I'm completely blinking
 
Dan_Shappir:
Bryce.
 
Steve_Edwards:
on it. Anyway, Bryce Canyon, yeah, we did Bryce Canyon and that area is beautiful. I love that area down there,
 
Dan_Shappir:
Yeah,
 
Steve_Edwards:
it was
 
Dan_Shappir:
it's
 
Steve_Edwards:
gorgeous.
 
Dan_Shappir:
amazing.
 
Steve_Edwards:
And then, yeah, we had dinner with AJ and his wife and kids while we were there. So yeah, there's a lot to see. It's beautiful, you should really like that kind of
 
Dan_Shappir:
So just
 
Steve_Edwards:
scenery.
 
Dan_Shappir:
to say that one of the conferences where both Ryan and I will be speaking is in Portugal in this university town called Coimbra. And I just have to say that the fact that you probably won't actually tour Portugal is a huge miss because it's
 
Ryan_Carniato:
Yeah.
 
Dan_Shappir:
supposed to be such a lovely country. I mean, my wife and I visited Lisbon a while back. We were actually supposed to do a big tour in Portugal and then Corona hit. So now we're actually jumping on the opportunity So we will be touring a couple of days both before and after the conference, which which would be great
 
Ryan_Carniato:
Nice, nice, nice. Now that is, yeah, it's one of those things where it's like, that one's like a straight, straight, straight, cause I'm in Amsterdam
 
Dan_Shappir:
Yeah.
 
Ryan_Carniato:
for JS Nation and then Portugal and then Finland. And it's literally like within like a seven, I'll be in all three locations within seven days. So, yeah.
 
Steve_Edwards:
Oof, a lot of moving around.
 
Dan_Shappir:
Yeah.
 
Steve_Edwards:
All righty,
 
Ryan_Carniato:
It is what it
 
Steve_Edwards:
with
 
Ryan_Carniato:
is.
 
Steve_Edwards:
that, we will wrap up this episode. Thank you for coming on again, Ryan. AJ wanted to tell me his bumby couldn't be here, but he was really glad to be able to come back. So with that, we will wrap up this episode, and we'll talk to you next time on JavaScript Javer.
Album Art
SolidStart with Ryan Carniato - JSJ 581
0:00
1:26:04
Playback Speed: