with Fred K. Schott
Resources & Links
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
Jason: Hello, everyone. And welcome to another episode of Learn With Jason. Today on the show we have Fred Schott. Fred, thank you so much for joining us.
Fred: Thank you so much. Pleasure to be here.
Jason: Yeah, I'm super excited to meet you. I feel like we -- I hit you up on Twitter like yesterday, two days ago, and here we are today. I had a reschedule, and the timing just worked out. We're going to talk a little bit about why that timing was so quick, but first I want to talk about you. For people who aren't familiar with you or your work, do you want to give us a little background on yourself?
Fred: Definitely. Yeah, so this time is perfect. We just launched a perfect called Astro on, I think, it must have been Tuesday or Wednesday. Hit up the DMs, like, yeah, let's do it. Instant turnaround. Yeah, so I just launched a project called Astro with a couple other developers working on it. It's a site builder. We're obviously going to get more into that. Previously, this work is really being built on top of something called Snowpack, which is one of these next-gen build tools that promises to be way faster than the traditional bundler and uses all this compiled language stuff under the hood to make that possible. Before that, I calmed on Palmer for a while, on tooling there. I've just been a web developer for coming on ten years now. I just love the space and this tooling stuff is just kind of where I see that I can make the most impact.
Fred: Yeah, it's a huge undertaking, going from one module system to another. That's a huge moment for a community.
Jason: And this is exciting because this was always -- like when you heard React introduce, this was the promise of React. It's intended to be a component system. Hello, everybody. Thank you for the raids, for the subs. What a great time. I'm so happy to see y'all here.
Fred: I don't know how you talk with all the like noises and GIFs. I'm so impressed right now by your stream of focus.
Jason: I have to just go dead-eyed and forge ahead. But no, I think it's so exciting to me -- well, now I did lose my train of thought. I was saying with -- oh, with React, like the original promise of React was you have content, most of your content is there, and then React is a component framework that lets you take an individual div on a page and make it interactive. Over time, we've realized that's not really how it shakes out in practice. You end up making a React website, so the div you make interactive is the whole website. So this has the potential to be kind of a return to the roots of React where you are saying, like, well, most of the content we ship isn't dynamic. We're not usually -- like, my blog posts aren't interactive. My blog posts might have one interactive piece. So what you're saying with Astro is that's the intention, right. We get to keep the static things static and only be interactive when it's time.
Fred: Yeah, and you'll see when we dive in. This whole framework is a love letter to the PHP tag. Make some HTML, server logic, back to HTML.
Jason: Okay, okay.
Fred: This is like a new thing, but it's really leaning on, no, those things were cool. Can we make those work in the modern web developer? I'm sure I just lost all your audience with that statement. But it's cool.
Jason: No, I think that's an important thing to talk about. It really is true that a lot of times we're coming out and saying like, hey, look at this new thing we build. Sometimes we forget to call back to, like, well, we didn't invent this. We just took a good idea and polished it up for today. And you know, I think that's a really good way to look at it because it reminds us that this all goes in cycles. We're not, like -- this isn't magic. There are very few net new things in web development. It's usually a repackaging of an idea that worked at the time and then didn't keep up with demands. So now we figured out a way to take that idea and keep up with today's demands.
Jason: So I'm really excited to see how this works. So I guess I have a couple questions about Astro itself before we dig in and start coding with it. There are a few things in the announcement post that I'm very excited about and I'm just curious how y'all are thinking about it. So the first thing that I saw is, you know, you were shouting out to frameworks like Remix and other open-source -- not necessarily open source, but people who are building on top of open source in ways that make it sustainable, that make it into a business. You mentioned that this is kind of the goal for Astro. So your intention is not to turn Astro into a business, is that correct?
Fred: Yeah, I mean, Astro the thing, that is like not ever going -- it's always going to be free. I think everyone is tackling this differently. I don't know if Remix would consider itself open source. I don't mean that to be a spicy comment, but it's literally closed source. You need a license to use it in production. That doesn't feel -- that's definitely not the model we're going with here. It's early days. We're still trying to figure out where we fit in and where we can build more enterprise-focused features on top of this. That's how we see it as a team.
Jason: Yeah, and I think there's -- this is a whole episode in and of itself. Sustainability of open source. It feels like the hot topic today is how do we make it sustainable without everybody needing to turn their open-source project into a VC funded business. It's challenging, right. It's hard.
Fred: Yeah, it's a weird time for it. I've come from projects that didn't do that. Just kind of was either me working on it myself or trying to get donations. That was the original project. A couple years back, you have to really hustle and go out and get donations. It becomes this full-time job in itself. It's not sustainable if you're trying to then also on top of that build open-source software to the degree and maintenance that we're trying to provide.
Jason: Yeah, and so there's a question in the chat about with everything that y'all are shipping -- because the team mind Astro is the Snowpack and Skypack team, right?
Fred: Yeah, so Drew Powers, Nate Moore, Matthew Philips have all been instrumental in building this out.
Jason: Yeah, so there's -- the question is just kind of like how do you see, you know -- is the future of Astro dependent on those products or how does it become -- I know this is kind of a vague question. But how do you make this sustainable? How do you keep it going?
Jason: Sort of like the WordPress model. The software is free, but there's this ecosystem of themes and plug-ins and paid, premium things on top of that.
Fred: Yeah, this kind of got lost in the final blog post, but we really see this as a platform we're building. So right now it's a static site builder. We want it to have dynamic support. We see this as building a platform you would kind of buy into, totally open core, but things on top of it you can opt into that some would be paid, some would be free. Trying to play around in that space.
Jason: Okay, yeah. Cool. And so that actually reminds me of another question I have, which is you did something that I would have thought is extraordinarily hard, which is you're promising you can write for Astro with any framework. You can use React, Vue. So hearing that as a developer, we have to build the same thing in every language, every time a feature comes out. I'm curious, how are you approaching that? How does that shake out in practical terms?
Fred: Yeah, so it's React, Preact, Vue that are supported out of the box. We're really biting off something here. I don't think we realized this until we really started getting into it. This is kind of a conceptual part of Astro. We say we support all those as UI, like build a component with this. We are moving a lot of the data-loading, almost website, appy things out of those languages. So there's this idea of having a based Astro application where Astro is the one handling, okay, when I hit this, it gets loaded. I want to build these pages, so let me build a paginated collection of pages. We're trying to move a lot of what has become just because whether it's React is the one building Create React App or the Next JS team is so bought into React. We have this idea that all this gets integrated into the UI framework. So it can do these things, but it doesn't necessarily have to be where that lives. So we're kind of stripping down like all the things you learned about React. But we're not adding get static props like nextJS would. We're trying to move that out, keep the UI layer relatively tight and focused on rendering, and then we own like the app part of your site.
Jason: Yeah, yeah. For sure. And I commend you on keeping a straight face as the chat attempts to bury us in boops here. But no, yeah, and that makes sense. I think this will become clear when we start looking at the code as well. Honestly, maybe this is -- see, I don't want to --
Fred: Do we have to stop talking when we start drowning in boops.
Jason: You either have to stop talking or start sounding like you're under water. (Laughter)
Fred: I'm drowning. Sounds like a horse.
Jason: (Laughter) Okay. So chat, I apologize for what I'm about to do, but I'm going to switch us over into paraprogramming mode, which is going to undo all of your hard work. Oh, no.
Fred: Jason couldn't hang.
Jason: Sorry, everyone.
Fred: Jason couldn't hang with the boops.
Jason: Foiled again, chat. Foiled again. But okay. So let's do this. We are over here. We are looking at learnwithjason.dev because we have live captioning happening. We've got Rachel here with us today. Thank you so much. She's here from White Coat Captioning. They're working to make this site more -- or the the show more accessible to more people, which I really appreciate. That is made possible through the support of our sponsors. Netlify, Fauna, Auth0, and Hasura all kicking in to make the show more accessible to more people. We have Fred on the show today. So if you're not already following, make sure you get over there and make that happen. See, look what's happening. We just have to strategically position things.
Fred: No, my plugs. (Laughter)
Fred: Yeah, we really like this idea of the pit of success, which is the idea that like by default, a site should be fast. That's not the case with a lot of tools right now. It's like you need to go out of your way to make a site fast. You really need to understand the performance trade-offs. We talk about that in the blog post.
Jason: And I like this. This is a good way of talking about it. Well-designed system makes it easy to do the right things and annoying but not impossible to do the wrong things. So I've repeated the phrase make the right thing the easy thing. I think setting good defaults is another way of saying this. The pit of success is a nice, well-known way to do it. But I think I really like this as a general design methodology, thinking about the fact that we've got studies. Over half of people are going to choose the default. So by default, dot right thing, and you immediately have improved whatever ecosystem you're a part of, whatever community you're a part of. Thank you for the hat, chat. And I think that really is something that is so easy to overlook as a designer. You're like, oh, well, we'll make the defaults quick so you can see how it works. Then don't consider that like 50% of people are going to ship that to production.
Fred: Yeah, or like at its worst, it's like you're bad for building a slow site, which you see. It's not like people taking pot shots on Twitter. It's not real, but it kind of gets soaked into the mentality a little bit. Oh, yeah, you don't know what you're doing, versus you didn't have time or you're just trying to build a product so your company survives. Yeah, it's a really wrong, lop-sided way of thinking about performance. We feel, at least.
Jason: Yeah, absolutely. I mean, I could talk about this from a philosophical angle like all day, but here's what we should do. Let's actually build something. So if I'm a new developer, I want to try this out, what's the first thing I should do with Astro?
Fred: I would go to the launch post, where we have the snippet for getting started.
Fred: That's still kind of our pre-launch place holder that we haven't gotten around to updating. It'll take you here, and this is kind of the snippet to run.
Jason: Okay. So I'm in a project. I made a read me. I might have to delete this to get it to work.
Fred: Oh, great question. I think we might just override it.
Jason: We've got Fred in here. We're going to do a collaborative session today. We're using VS Code live share for that. And let's just see what happens if I run -- what was it? Npm init Astro. Let's see what happens. I love this init -- let's see.
Fred: Oh, this is so good. We actually see this a lot, way more than I expected when we launched. What version of Node are you on?
Jason: Great question. Let's find out. I need to use 14?
Fred: Or the latest version of 12. So this we totally didn't expect. The latest LTS, which I think is 12 now.
Jason: I think I have 14 installed.
Fred: That works too.
Jason: Downloading a new version of Node, sometimes it's nice and fast, and other times it takes like eight minutes. We'll just use this one and let's try init Astro again. All right. Directory not empty. Continue? Yes, I would like to continue. We're going to set up -- what do you think?
Fred: Let's do the starter kit, but they're all pretty great. We really wanted to have a couple example sites here.
Jason: Okay. Into the starter kit we go. Oh, here we go. We've got a read me. We've got an Astro.config. No settings in it. Comes in empty, nice and easy. Let's look at the source folder here. We've got components and pages. I see the first thing that sticks out is .astro. So we have a new suffix for files.
Fred: Can't wait to talk about that. TLDR, it's HTML with like some JSX kind of things going on.
Jason: Gotcha, okay. And looking in our index, this is a standard HTML document. So we have our doc type, our HTML tag. So nothing is coming out of Astro. I'm feeding it all. Is that a safe assumption?
Jason: Okay. Then down here, I've got -- is there a -- am I going to find a .astro syntax highlighter?
Fred: That's what I was going to say. Get a syntax highlighter. We have not bumped them up. That's like a dead extension. We're gunning for that top spot.
Jason: For that number one spot. Okay. So let's do this. Oh, get out of here.
Fred: If we're just going to jump right into it, let me give a little bit of overview of what this file is and what a .astro file is.
Jason: Yeah, let's do it.
Fred: So the whole idea here is HTML is our base language. We want to think in terms of HTML and make it easy to use and give it superpowers. The quick analogy would be it's like JSX but for HTML. The two ways we did that, the main one is the idea of bringing components into HTML. So it's a superset. If you just put in an HTML snippet, it's going to render totally perfectly. But that tour is a great example. When it gets to this part of building your site, it'll actually go and use that HTML or the rendered markup from that component.
Fred: No, no. Think of it as a setup script. You can put in const hello equals world. You can do anything inside of there.
Jason: Okay. So we have the ability to embed a component here. Then this tour component looks like so. So I'm importing markdown.
Fred: We got to talk about markdown at some point. It might be a little advanced for where we're at now, but we let you mix markdown with HTML, which is so cool.
Jason: Okay. And is that -- that's through this component here?
Jason: Nice. So and this is really something that I'm a fan of. I don't want to write my content as HTML. So being able to drop this in, this is slick. I like this approach here.
Fred: Yeah, there have been a couple times where I've built marketing site material and it's like, okay, cool, I have six things on the page highlighting something. Now I have to go paragraph, strong, and all the sudden I'm back creating my a-link tags. This gives you a little hook into a more markdown focus without having to throw it all out and use a file. It lets you intermix.
Jason: Yeah, yeah, yeah. Well, cool. So, okay. Now we've got -- here's our basic site. I can see here that we've got, you know, the access to markdown. Looks like there's a section of components. So I can see this working. So let's see if I can just run it. I'm going to run npm run start. Let's see if we can get this thing doing what I want. Uh-oh, what doesn't it like? Oh, I need to install my dependencies.
Fred: We don't do that for you by default.
Jason: Thank you for gifting the subs, Ben. Very much appreciated. So welcome to everybody who just came in. You now have access to the boop emote, as well as the holy bucket. You can have me doing some thumbs ups. You got all sorts of options now. Make sure you use those boops now that you got access.
Fred: This is way delayed, but someone was in the chat saying ham stack. just a huge shout out to that person.
Jason: Ham stack is how I make sandwiches. What ultimately is going to happen is I feel like at some point in the future, I'm going to just fully burn out from being a developer, and I'm going to open up a food truck, and it's just going to be a food truck that only makes sense to developers because all the sandwich names are going to be puns. You'll be able to get the ham stack. Let's see if I can come up with another one on the fly.
Fred: You really set yourself up. Right now you've just stolen mine or the chat's.
Jason: Yeah, that's all I got. Oh, lisp and onions. No, gross. Oh, toast. Toast was so easy. Such a low hanger. But yeah, I think this is -- okay. So I've installed my dependencies here. Then I can run start again.
Fred: Steamed YAML. You got a funny chat.
Jason: What else you got, chat? Sandwich names, sandwich puns.
Fred: This would be a good time to say, the one thing about where we're at right now, this is definitely beta release. Even this output is noisier than I want it to be. Maybe you didn't notice it. I'm sure most people don't. We're doing a bunch of stuff this week to kind of tighten up a lot of the first user experience. So it's only getting better from here.
Jason: Yeah, okay. And I can see we've got some Vue in here.
Fred: Yeah, this is built on Snowpack internally. This is just handling your dependencies for the first time.
Jason: Nice, okay.
Fred: Totally don't need to worry about it if this is your first time seeing that. I know, it shouldn't be that noisy.
Jason: Ruby rubens. Okay. Now if I go in here, let's play a little bit. I'm going to get in here, hide the side bar, and open up my tour. Let's just add some new content. I'm going to take out this part. Let's save it. Does it do hot reloading? Do I have to do anything?
Fred: We just fixed the bug that was causing it not to. As of this demo, no. Probably by the time people see this in the future, probably yes.
Jason: Cool, okay. I can command R. So I didn't have to stop or restart the server. I just made the change. So I can pop this one out of here.
Fred: So it's really just HTML. If you've ever copied a snippet of HTML into a React component and you're replacing class name or it doesn't work because it's actually JSX. The whole idea is this is valid HTML. An HTML snippet can be thrown in here, and it'll work.
Jason: Yeah, so talk to me about styles here. What do we have going on with the styles?
Jason: Oh, interesting.
Fred: So when you're writing your styles, there's a fallout if you want to use global styles. By default, these styles are actually scoped. They won't bleed out of the component and impact any other component on the page.
Jason: So yeah, we can see the things here are kind of tagged in like that.
Fred: It supports SaaS by default. So that's built in as well. Tailwind is supported, although I can't remember the exact instructions.
Jason: Yeah, it looked like there was a list.
Fred: We did our due diligence.
Jason: Supports TypeScript, Scoped CSS, CSS Modules, Sass, Tailwind, Markdown, MDX, and any of your favorite npm packages. That's a bold claim.
Fred: Any good package. No, because we're building on Snowpack. It's pretty good at handling your dependencies.
Jason: Yeah, no, this is pretty exciting. The fact we're here is good, right. So let's talk about practical use cases. There are things we're going to need to do as developers when we build sites. So I think you had a list of things that you were hoping to cover. I'm going to let you drive on what we should look at next.
Fred: Yeah, I'd say there's one other big part of this that's definitely worth diving into. There's two parts of Astro component. One is the idea of being really HTML. We kind of talked about the Markdown a bit. The other is how you intermix like -- again, it's a static site builder so it's not interactive content, but dynamic content you can call it.
Jason: Right, right.
Jason: Okay. Let's grab it. I'm going to pull that out.
Fred: Then down in the strong that you just took this out of, do the curly brace, name, and that should render it exactly the same.
Jason: With the dollar sign?
Fred: No, this is JSX so no dollar sign.
Jason: Oh, JSX.
Fred: I mean, it isn't, but that's the inspiration. Maybe give it a change so you can see it's updated.
Jason: There it goes. So it does what we want.
Fred: So you can do that with variables in the markup, attributes if you have a class name.
Jason: Yeah, this is great.
Fred: Let's do more advanced. If you want to create that in an array and loop over it, I can show you how a more advanced snippet would work. Grab some names from chat or something.
Jason: Oh, you want to loop over it like -- are we trying to do a list of things or pull one at random or what's the angle?
Fred: Yeah, let's do a list.
Jason: Okay. So ideas.
Fred: Do your sandwich names.
Jason: Yes, okay. So we're going to do HAMstack. That's one. What else? The Ruby Ruben. What else?
Fred: Steamed YAMLs was my favorite. It's not a sandwich, but.
Jason: That's okay. It's a general purpose food truck. That's good enough to start. So here we go. Oh, crispy-fried steak sandwich is good.
Fred: Is it bad that -- oh, wait. I missed that one.
Fred: Oh, nice.
Fred: I'm actually a little embarrassed I didn't get that.
Jason: Toast. Got to have toast. Now we've got our ideas. I'm going to call them sandwich ideas. Okay. So I've got an array.
Fred: Now really treat this like JSX. How would you create some looping markup content? Exactly.
Jason: So I'm going to do sandwich ideas map. Then I'm going to get an idea. Inside of this, I would do a list item, and I would put out the idea.
Jason: Do I need to do keys or any other kind of specialty stuff here?
Fred: No, we can talk about that a bit, just more as a conceptual thing. There's no keys to worry about. There's no reactivity.
Jason: I have made a mistake.
Fred: I don't think you have is the problem.
Jason: So I I've got my sandwich ideas.
Fred: Did any console logs happen in the browser maybe?
Jason: Oh, good question.
Fred: Trying to think of where this could happen. No.
Jason: Did I mess this up in a way that it's like --
Fred: It looks so solid. If this is just a parser error, try getting rid of the curly bracelet at the end of 25 and at the start of line 27. Just give this a more -- so to make it -- sorry, no, at the end of the line.
Jason: Oh, I'm not returning it. That's what the problem is. That was the whole --
Fred: That's what I was hoping.
Jason: Okay. Well, good. So the good news, chat, is that I'm a doofus, which is always the best news when we're running into problems in code. Okay. So here we go. We've now looped over an idea. This is very straightforward. We're mapping. We've got this set up here. It looks like, you know, if we were doing this true JSX style, we'd have a parentheses to show we're just returning this outright. I don't know. We get to define our own preferences now. This is a whole new world of .astro syntax highlighting suggestions. But yeah, so this makes sense. This makes sense to me. Like, I get it. I see where we're going.
Jason: Yeah, let's do a little React component. Am I just going to do this the way I always would? Create like a .jsx file?
Jason: So menu.jsx. Then inside of it, I don't need to do any importing of react. So instead, I'm going to export function menu. Our menu is going to take -- let's take ideas, right? Then that can return our list of ideas. So actually, we can just pull this part right out. So let's take our list of ideas, and we're going to map that. I got part of this wrong.
Fred: Parentheses on the end of line 4. Oh, you got one.
Fred: Actually that, probably will work. Tour is in the components directory, so you can do dot, slash, I believe.
Jason: Oh, you're right. So we'll get it from menu. Then instead of this, I'll do a menu and my ideas will be sandwich ideas. All right. Will it blend? Whoops. No renderer found for menu. So I did not add a renderer to my astro config.
Fred: I forgot we made these opt in. That's a great call out. You need to add one of those.
Fred: I actually thought those were on by default. Maybe we pulled that out.
Jason: Okay. So to do a renderer, I need to go here somewhere. Project read me, maybe.
Fred: Yeah, it's in the astro config. I'm just trying to pull up the -- yeah, find the astro config doc.
Jason: Config. Then we've got renderer. So I can do a renderer down here. And we're going to use -- I'm assuming it's like astro JS renderer react.
Fred: So the big problem we were hitting was how do we know if you wanted Preact or React there. I think that was the main reason we're like, okay, you got to opt in by name at least.
Jason: So actually, I could use like Preact here because we didn't write any React specific stuff. So I could grab that. So let's use Preact. Let's try it. So we're going to do Preact. I'm assuming I need to install this.
Fred: Yes. Try running it. You should install it. That would be the right thing to do.
Jason: Yeah, let's do the right thing.
Fred: Let's do the right thing.
Jason: Looks like it updated one package. Yeah, so it didn't need it, but we've updated it. Now when I go back here and I load this page, it doesn't like it. Renderers, did I spell this wrong? That's a distinct possibility.
Fred: If this doesn't work, let's check out the menu -- or how are you importing it?
Jason: I'm importing it as import menu from menu.jsx.
Fred: Huh. That's surprising.
Jason: Oh, wait. What does it not like? No renderer found for menu.
Fred: Yeah, there it is.
Jason: Do I need to import React or something?
Jason: Oh, it's Preact. Do I need to set the pragma?
Fred: You shouldn't. Do an import something from Preact. Maybe we actually had a trigger by that.
Jason: Maybe I should use React because I can't remember the Preact pragma off the top of my head.
Fred: Let's not complicate things.
Jason: Yeah, let's do this the way I have the syntax by default.
Fred: Let me check another project to make sure.
Jason: Oh, yeah, H was the one. So let's try this and we'll npm run start. Let's see if it just does the thing.
Fred: The last thing I would say is what is your renderer -- go back. No, that is spelled right.
Jason: Yep, and we've got renderer react.
Fred: That's so strange. I have another project where this is working fine.
Fred: (Singing) beta software, beta software.
Jason: Let's just pull in React and see if it needs to -- yeah, so it just needs to be identified as React in some way. So that's something that can be improved. But it definitely works as expected now. And we get our HAMstack. As a question, is this HTML right now?
Jason: Yeah, and it looks like we can see, you know --
Fred: You can see the tour CSS coming in.
Jason: We pulled in 7 kilobytes. That in and of itself is pretty exciting. In a standard -- like in a standard project running React, I think you're pulling in close to 30 kilobytes just for a React core. Again, there's a point where that trade-off makes sense, but when you're doing content on a page, it doesn't necessarily make sense for that to be a thing. So for something like this where I just want to show you a list of stuff, I want to be able to write React to display my content, but I don't necessarily need you to load React to view the content. So I like this as kind of a let's use React for the DX but not necessarily put that into the user's experience.
Fred: The worst offender of this is like how many layout components I build in a React site that get shipped to the client, render once, and then never change.
Jason: Right, yeah.
Fred: This is my page layout. This is the layout for this. It's architecture.
Jason: I do that constantly. I'm always taking some piece. I build out these elaborate, like, layouts in HTML that are literally just layouts. They're not dynamic. They're not intended to be interactive. They're just there to look like something.
Fred: So this is actually the one thing I want us to -- it's such a subtle thing because your first instinct is something didn't work. Remember, that's kind of the trick here. Everything is static by default. So this shouldn't work by default. That's the trade-off here.
Fred: Yeah, we just never sent it to the client. Exactly. So that's obviously not idea here. That's not what you wanted. So the next thing to look at would be how do we actually opt in this component for interactivity.
Jason: Okay. And I want to do that by --
Fred: So go back to where you use the button. It's all about where you use the thing. Let me make sure I got this right. Just take the name button and like button: Load is the simplest way to do it. So add a colon and write the word load.
Fred: That's it.
Jason: Okay. And let's look at what happened here. So we've got our -- what's yelling at me? Text content did not match.
Fred: Yeah, and it changed --
Jason: Oh t probably changed it to like a tokenized string or something.
Fred: I was going to say it changed the styling of it as well. I don't know if that's a React thing. Maybe a bug we need to fix. The idea here is that it should look exactly the same in both cases, but now it's hydrated. Now it's doing some cool stuff.
Jason: So in our network panel then, what changes is now we've got -- oh, we've got development React. That's going to be very, very different from what we would get in production. But it does bring in, you know, the things we need. Here's React. Here's React dom, and the pieces we need to make this function. And if I turn this off again, then those pieces don't show up anymore. So, okay. This is clever. This is really nice. Now this colon load, that's not the only way you can do it, though. There are other options?
Fred: Yeah, that's just the simplest. You can see this in the read me. It's basically saying that'll render it on page load. It's the simplest way. It'll hydrate as quickly as possible. There's also colon idle, which will use a request idle call back. So once the page has stopped loading, now we're going to sneakily hydrate is behind the scenes.
Jason: Let's watch that happen. So what we should see then is there should be like work and then it'll do more work at the end. So here we go. There, see that?
Fred: Yep, there it is. That's it loading this component. We're doing it in development, so I think you can see a lot of different smaller things loading. In production, that would be one JS file getting loaded.
Jason: Right, right. But still, this is slick because this part happened after the fact. See, this is -- these are the metrics that Chrome is looking for. So the fact that we're waiting for the browser to be done and then hydrating things, this in and of itself is a huge win for performance. It's not a win for like parsing performance. So if you on a low-power device, you still have to parse all this. But for loading performance, this is great.
Fred: The last one is my favorite because it's easily the coolest. This is colon visible. We talk about this a lot because it's such a feature of this way of thinking. We can actually take this button, say you want to render it when visible, that means if it's not on the page, it's not going to load.
Jason: Okay, so look. We've got no React. I see this visible.js. So let's get it on the page.
Fred: And you can even click into that. It's an intersection observer.
Fred: Everyone who loads a blog post reads it all the way to the end, right?
Jason: Exactly. Clearly.
Jason: Yeah, okay. That makes sense. So there's a question about how does visible work if one component is depending on some other component that's not yet visible? I feel like I have a suspicion of what the answer is.
Fred: I'd love to hear your suspicion.
Jason: So here's my suspicion. Components can't depend on each other without some kind of a context, right? And so-so put that context in, the context would become visible, which would make all of the components load as soon as the first one becomes visible. Is that right?
Fred: I'm trying to think through. I think -- not because I think we've done it, but I think it ends up being smarter than that. And this is a really cool thing about this model. All the sudden you start thinking in components and not pages. Traditionally when you're bundling a site, the easiest thing is this page will have this bundle, this page will have this bundle. Anything shared will go into a common bundle. And that's that. Our model, because we're no longer thinking a page is a page, a page is static by default, we start thinking of each island as its own entry point, its own bundle. So this button gets its own -- I mentioned it like in production. It's a single JS file. The button gets a button.js bundle that runs that thing. If it shared that with another component, like they have some common state, like a store they both reference that, would get pulled into a common chunk they would share. So we're kind of letting the bundler do the magic here. If code can be separated and chunked and bundled, it's going to be as efficiently as a bundler lets it be. So two components sharing some common state, you're loading the button bundle and the common bundle but not having to trigger the loading of the top-level other components that might be on the page.
Jason: Okay. That makes sense. I was trying to think of a way to do that, but for me to share state between this button and something else, I would have to add context or some other way of them to share.
Jason: Yeah, okay.
Fred: In the future, I want to add that you can define the context that's the root of all these things. So a global context that would get applied to all trees. It would allow you to that idea of every individual tree but sharing that context reference.
Jason: Yeah, gotcha. That is a tricky part. If you want global state in the React app, you're wrapping the entire app in context, which means the entire app needs to be React. That's a thing that is not unique to React but it isn't necessarily required for all frameworks because I think other frameworks have different ways of approaching this that don't require that, like, shared global context to be wrapped around everything. So there are ways to solve this. I think you might have talked about it in your post. Is it in here?
Fred: Probably in the read me.
Jason: Okay. Let's get that.
Fred: State management is where we see a lot of people run into this problem. And it kind of just depends.
Jason: Yeah, so with React, there's Redux, partial support, for the reasons we talked about. You have to wrap a provider, which makes everything into a React component. Or, let's see, Recoil works. Svelte Stores work. And yeah, so depending on how it's implemented, it can work. That idea of split bundles and sharing -- the things that are shared are shared and the things that aren't, aren't. You need to load the pieces you need at any given time. That part is compelling and really, really interesting to me. But we have about 30 minutes left, and there's a couple things I want to make sure that we talk about today. One of them is you have a pattern for like loading data. I think you had talked about collections. So I think collections is one thing we wanted to look at. What was another thing? You put a couple things into a tweet about what you wanted to cover today. I want to make sure we have time.
Fred: Right. Yeah, let's kind of go through data loading and see how far we can get. There's a couple things in there that would be interesting.
Jason: Okay. So if I was going to go with my gut, I would say I'm going to add node fetch and load some data.
Fred: Yes, you don't need add node fetch, though. We provide fetch support out of the box.
Fred: Access it like you would in the browser. Just fetch. We'll kind of poly fill that.
Jason: Okay. Let's get some data. We'll pull some episodes and I'll do it as JSX because that's what I know. I'm going to import.
Fred: Oh, that's a good point. We don't -- let's do this in an Astro component to start and we can talk about what happens in a React component.
Jason: So here we go with an Astro component. I'm going to do a fenced code block. In this, I'm going to get episodes -- I have an API for Learn With Jason. So we'll use that.
Jason: And we'll do https -- see if I can remember my own website. Learnwithjason.dev. Let's use the schedule because that's smaller. That'll give us back a list of episodes. Then we'll get the response. We know that's JSON. So we'll res.json. Now that we have that, we have a list of episodes. I can't remember what's in it, so why don't we just dump it.
Fred: That should work. There's one thing missing from this, which is such a subtle thing but one of my favorite things secretly. Right now the way this is written, episodes equals fetch is going to give you back that promise. So how do you get that actually into a string?
Fred: Yeah, no, we support top-level await.
Jason: Oh, interesting. Okay, okay. So now I have episodes, which means I need to go in and use it. So let's go to the index and drop in episodes. I forgot to import that, so it's arguing with me. Let's go up here. And there's our episodes. So let's go to -- here's our page. I'm going to close the network tab. I hit the wrong button. There we go. And I screwed something up. Didn't I? No, I didn't. Good. Okay. So here's our data. My pretag got blown up, which is fine. That's a problem I know how to solve. So let me add a style tag here. And we'll do --
Fred: Oh, I'm so happy you just said that. That's a problem I know how to solve is like the backbone of what we're trying to do here. Why didn't this render? I have to read some docs or something. The whole idea is, no, this is like HTML. I know how to do CSS. I know how to do data software, obviously, but that's totally the vision for what we're trying to do here.
Jason: Let's go with width, 500 pixels and make that a little narrower. There you go. Okay. So here's our data. Now we've got some data, which means I can pull a list of titles. So why don't we do that. I can make another UL we'll iterate over this the same way we do the other things. Episodes.map, and each one is going to give us an episode, which we will then turn into a list item. And we can do -- let me think. We can do a link. We'll do an href equals and drop in the episode -- oh, look what I did that was foolish. I didn't make a link. Learnwithjason.dev, then we'll do the episode.slug.current. Okay. Inside of this -- get out of here -- I can put the episode.title. Then we can do like width, episode.guest. Why have I done this? Name. Okay. So then having done that, we should have a list.
Fred: The one thing is the href needs to be wrapped in a JSX curly bracelet to get the template variable going in there.
Jason: Yes, okay. So let me clear that part out. Don't need that anymore. So I need to do it like this. No, I screwed it up. Oh, I forgot to keep my quotes in.
Fred: Yeah, see if that fixes it.
Jason: Yep. And it works. Links work. So there we go.
Jason: Look at it go. Hey! So this is exciting, right? Now we can do upcoming episodes, and we're building a website with third-party data and look at it happen. I can do like an h2, give it margin top so we can breathe a little bit, you know.
Fred: I love what the site has turned into. It's half pun restaurant menu and half subpromotion of the livestream.
Jason: I think that's ultimately what I'm going for. Half helpful, half utter nonsense. So we were able to pull in some data. We've got top-level await, which is -- this is handy. I love that I don't have to write a function and, you know, do some extra stuff. I can just pull in the thing I need, which is handy. What else should we look at here?
Fred: I think the collection stuff might be a little overkill for how much time we have left. We can just talk about it. You can basically take this data and take this template and turn it into a collection of pages. So it actually would render this, you know -- like if you wanted a page for every episode. It would essentially iterate over that and create a page and actually multiple pages would get generated from this one template. So we have support for that.
Jason: Should we try that?
Fred: How much time do we have?
Jason: We've got 25 minutes.
Fred: Then that'll work. I wasn't sure if there was a wrap-up included. Yeah, let's do it.
Jason: Okay, yeah. I'm ready.
Fred: Let's pull up the documentation on the read me just to follow along.
Jason: There's the config. Let's get to the docs themselves.
Fred: Yeah, look for -- it's called --
Jason: All right, here's collections. So we figured out the fetching data part. So I can do source pages.
Oh, so we would need to add code?
Jason: That's right, that's right, chat. So deciding on a URL schema. We can do schedule or something. Or episode. Good. Oh, like this.
Fred: It's a special type that starts with an asterisk. That enables this feature. This is like the more beta kind of feature here. None of this is finalized for release, but this is where we see, you know, the actual what we've accomplished here is really clean in terms of pagination.
You hackers, you dirty hackers.
Jason: Okay. So now I have -- I've got my episodes.astro. So then we can take a look in here. So I make a collection. And is this in a fence block?
Jason: Okay. So I have my fence block. Inside I'm going to export, let collection. Do I have to write TypeScript here?
Fred: No, don't have to.
Jason: Okay. Then I have export async function, create collection. So this is like the API. This is an Astro thing. It looks for a file with this thing exported. Then I return and I've got async. Let's get that --
Fred: Yeah, so when I talked earlier about that idea of moving data, app building, data loading, all that stuff out of the UI framework and into a kind of common place, this is like the first peek into what that looks like. This is something that happens in an Astro file but doesn't actually complicate how we have to do UI rendering.
Jason: So does data need to be a function like this?
Fred: Yes, yes.
Fred: We'll start to add a couple other things to get the perma link right and a couple other things.
Jason: Async data. Then in here, I'm going to get my episodes. So now I've got my -- whoops. Now I've got my episodes. Then what happens?
Fred: Oh, I should say what we're doing here -- let me double check this. It's actually been a while since I've tackled this. We can do it together. I don't need to get ahead. This is great. What this definitely doing is giving you a paginated list. Let's scroll down the read me a bit.
Jason: So in each collection, we've got our data. Then we have -- so these aren't quite what we're using. So here we go in. We're getting all of our posts. So we're not using local content. We're using external content. Instead, we can -- we return all posts. Then we have got page size. So I'm just going to return my episodes. Then page size. Is there a thing I'm doing with this? Like I'm limiting the number we show?
Fred: Yeah, so if this for some reason returns like a hundred things. We can keep going, but this tutorial is actually creating a paginated index. So if you wanted basically to list ten episodes on every page, like a paginated collection, this is helping you build that.
Jason: Okay. Should I do like a page size of one so that we can create each --
Fred: Oh, yeah, let's try that.
Jason: So we've got a page size of one. Then in our -- let's see. We don't need that part.
Fred: Okay. It's been a while. So I helped work on some of this, then I went out for paternity leave, and my brain has been fried since. I'm actually learning a bit with you. Drew and Nate and Matthew have, I think, taken the torch on a lot of this stuff. So this is a learning experience for me as well.
Jason: Okay. So we exported the collection. It exposes a prop to the page for Astro return with all your data loaded. It must be named collection. Then we have to export create collection with data. And then we can collection data map.
Fred: There's an example. I think we're jumping into the advanced option here, which is great, but there's a code snippet that I think will help you out.
Jason: Is it in the reference? Or where am I looking?
Fred: So example two. It's right below where you're at. We'll talk about both of these. I think they'll both help. This is what this would eventually end up looking like. So you have that idea of perma link down there, routes kind of tells you -- we're basically trying to give you a framework for loading these things as data so then the actual template rendering itself is lightweight and quick.
Fred: So the pieces here are that we're loading the post. That's your fetch there, which is great. That's our episodes array. In this example, it's sorting it by tags and trying to give you a filter. I think what we're doing is saying, no, let's basically do one on a page, and it'll be the post itself. Routes is where you're basically taking that episode object and turning it into the thing that will get perma linked. Basically, let's write the routes thing first.
Jason: So we've got our routes. Then our routes is going to be episodes -- whoops. Episodes.map. For each episode, we want to return an object that has the slug, and that's going to be episode slug current.
Jason: Okay. Then down here, I'm going to get the slug in my perma link, so I need to return schedule slug.
Fred: Yeah, that should work.
Fred: It might force you to make it within -- yeah, this might give an error later, but it's an easy one to fix if that's the case.
Jason: So then I have my collection --
Fred: Yeah, so now you can go up to that HTML connection. That shows the template rendering here. We're kind of hacking this a bit, but I actually kind of like it. We might actually redesign this to double down a little bit. Collection now is the variable you have access to. That's going to be rendered now full of content. Like every slice of the collection this template will be called on. So collection should be essentially -- and let's actually log what it is on every page if you can. Exactly.
Jason: So let's do a pretag. In this, we'll JSON stringify and set in the episode.
Fred: And actually, I think you'll get better data. Just stringify collection itself. So instead of doing this map, just stringify the whole collection object.
Jason: Works for me. So we'll get that out of there. We're going to stringify collection and do that style tag again so our pre is 500 wide. And we'll overflow scroll so we can see it. Close this tag up. And let's give it a shot.
Fred: All right.
Jason: So we didn't go to any of these pages, so I should be able to go to like -- oh, you know what I can do, I can change our episodes. Instead of being a direct link, we can go relative link. That should take us into pages.
Fred: Nice, nice. All coming together. So I think this is the bug I was talking about, which should be a little more obvious. Because you called this collection file schedule/episodes.astro, I believe the perma has to be that same schedule/episodes. So let's edit that.
Jason: Like here?
Fred: Yeah, there.
Jason: Oh. So if I want it to be at the top, I would just call this schedule.
Fred: You can do that as well. That might be easier.
Jason: Yeah, that'll be easier, I think, than -- let's go schedule and then move this out and delete this folder we don't need.
Jason: Then we'll go in here and get rid of that part.
Fred: The last thing is are you putting the slug in the link? Oh, that looks like it worked.
Jason: That looks like it worked, but we didn't get any data in collection, which --
Fred: So I'm wondering if the slug matches.
Jason: Good question. Can we see the output somewhere? It says --
Fred: Yeah, it is episode select current.
Jason: So let's see here. Did I do something wrong in my -- we've got our episodes, got our page size. Maybe I make my page size ten.
Fred: Yeah, see what --
Jason: No. Let me try one of the other ones. It's not the one that's happening right now. No, it's not that.
Fred: So, beta software. Doing the build, we'll at the very least show you what are the kind of places you're expected to -- although, you're not getting a not found. So it's just an empty collection.
Jason: Yeah, it's giving me an empty collection. But let's see what it builds. We'll do npm run build. Let's see what pages it's trying to build. Poke around in here.
Fred: Yeah, so pages built.
Jason: It gives us schedule and only index.html. That's also empty.
Fred: Someone said did you return in the chat. No, you did, yeah.
Jason: Let's check. Definitely possible I didn't.
Fred: No, I think you did.
Jason: I returned the episodes. We did it async.
Fred: This is definitely like a let's try. Yeah, log there and also the doc example. Permalink with a slash. I can't imagine that's it, but worth a shot.
Jason: So let's npm run dev again. Nope, that's not what it was. It was start. Okay. Let's try one of these.
Fred: So interesting. It runs on the server, so a console log should show up there.
Jason: It's running something.
Fred: Oh, you know what -- no, create collection is async. Hmm, what could this be?
Jason: We've got our data. We are returning.
Fred: Put a console log and create collection. I wonder if that's not even being run. I mean, this serves me right for being like, yeah, let's throw an experimental feature at the wall in the last 20 minutes. Let's end on a high note.
Jason: No, so something is not doing what we wanted it to.
Fred: That's so strange.
Jason: A view port is not specified. Do I need to add more -- like do I need to make it into an actual doc here?
Fred: Maybe. Oh, yeah. Maybe. Right because this is a page.
Jason: It is a whole page. So let me get the rest of our page here. We'll throw this in and see if it makes a difference.
Fred: Good call on that.
Jason: I mean, it's rendering, right. It's pulling in the right template, but we're not getting our data. Is it because I typoed a thing? Export let collection. I'm going to make it TypeScript. That wasn't it. We found a problem TypeScript can't solve, I guess.
Fred: Specifically that any can't solve.
Fred: That's always my when in doubt.
Jason: In the docs example the data was outside the return statement.
Fred: No, I think this is a bug. We went through some pretty active development as we were getting this ready for release. I wonder if we're just hitting something.
Jason: Yeah, well, that's okay. We're in good shape for the most part. So what else should we look at in our remaining five minutes? Is there anything else you wanted to show?
Fred: Yeah, we can end on something that's definitely in the template. I know this works. The idea of taking those components for HTML example, that whole idea. There's one other part, and I think it's really related to you pulling in the page content here, which is the idea of head and body and layouts being parts of your component. Your component tree, at least. Now you have two pages, right. You have your index and schedule. You can start to see already there's a lot of common head data here. You have your meta, your title, your link.
Jason: Are we about to make a header.astro.
Fred: Yeah, let's make like a common header component here.
Jason: So we've got a common header. I'm going into my index. I'm going to grab -- how much can I template out here?
Fred: Sorry, head instead of header. So let's look at metadata on the page. So what's in the head of the index.astro.
Jason: Yeah, so in our head we've got all of this stuff. We've got the view port, our favicon. We have a hit that will would need to change. Eventually we would need like open graph tags and all that good stuff. So let's go back to the common head. If I drop this in, I would want this to be a variable.
Jason: And maybe that's enough. So how does that work in Astro?
Fred: Let's keep this a bit more composable. Let's remove the head so you can mix and match this. Strip that line, strip that line. Good to go. Let's use this now as a component inside of index. So now you can go into index.astro and replace that with an import.
Jason: Okay. So I've got common head.
Fred: Just strip it all out.
Jason: I've now saved my common head. If I go back to my home page, hit it, and we can see like things still work. If I go to my elements -- let me close the console up. We can pop open the head and see that all those pieces came in.
Fred: Yep. And then the last thing which we haven't really talked about, but it's an important part of making this a fully functional component system is that you can pass props. So let's pretend we have multiple page, multiple titles. Let's add a title that equals astro or maybe give it something different so we can tell it changes. I don't know, anything.
Jason: Okay. We've done it.
Fred: Now we need to accept that in the common head. So we borrow a lot from Svelte here. Define your code frame. Same idea as Svelte export let title equals. Nothing. That's it. So that's defining title as a prop.
Jason: So if I want to default -- actually, let's try this first. So I'm changing this, and I can see if I hover, it did change. If I pop open this part here, it changed. Okay. Great. Now if I then use this and forget this part -- let's just delete that for a second -- then I get an empty title. If I want to make this default -- whoops. Common header. Then I can just -- can I just make that equal?
Fred: You got it.
Fred: Yep, that's exactly right. That static and click by default. You opt in where you need it. If you don't do anything, you're just getting a side without really trying. Versus the flip of to have a fast site, it's like a checklist almost.
Fred: Yeah, it's a really exciting time.
Jason: So for somebody who wants to learn more, what are some good next steps? Where should they go next?
Fred: So for Astro specifically, we've definitely ran out a lot of docs. We're constantly working on that, especially so close to launch. We're getting a ton of feedback on GitHub. Our Discord is probably the best place to come.
Jason: And where I do find that?
Fred: It used to be hidden. You had to open your console log. We thought we were so clever. It's just a link on the page.
Jason: Get down here, get that. Where else? Anywhere else? Make sure you go and follow Fred for updates. I imagine you're going to be tweeting about those.
Fred: Yep, yep. Definitely. That's a great place to kind of find out what's going on. I'm trying to tweet about it. Then astrodotbuild is the official Twitter account.
Jason: Twitter, astrodotbuild. There it is.
Fred: Yeah, especially if you have a framework you love that hasn't been mentioned, if you have a feature you love that you want to learn more about, you know, we're trying to really build a great contributor community, a great open-source project here first and foremost. So we're definitely looking for people to get involved, join us in the chat, join us on GitHub. It's really early days of this project. So there's a lot of cool stuff that we can go from here that we're excited about.
Fred: My pleasure. Thanks for having me on.
Jason: Chat, stay tuned. We're going to find somebody to raid. We'll see you next time.