Search

467: New Frameworks, Astro, New React, and WWDC 21 Thoughts

Download MP3

Where are my paaaants? What to do with new frameworks? What to do with new React? Building in Astro. And WWDC 2021 reactions.

Tags:

Guests

Chris Coyier and Dave Rupert in silly sunglasses and a sign that says Shawp Tawlkk Shough DOT COM

Chris Coyier and Dave Rupert

This episode is with just Chris & Dave, ShopTalk Show's hosts. Chris is the co-founder of CodePen and creator of CSS-Tricks, and Dave is lead developer at Paravel.

Time Jump Links

  • 00:53 Business pants and athletic pants
  • 01:51 The mess of new frameworks
  • 07:10 Astro
  • 19:43 Sponsor: WooCommerce
  • 21:36 Building CSS TrickZ in Astro
  • 32:39 New React
  • 39:20 Sponsor: Hubspot
  • 41:46 WWDC updates

Transcript

[Banjo music]

MANTRA: Just Build Websites!

Dave Rupert: Hey there, Shop-o-maniacs. You're listening to another episode of the ShopTalk Show. I'm Dave--wearing new pants technology--Rupert and with me is Chris--in the booth--Coyier.

Chris Coyier: Do they have a USB plug?

Dave: No.

Chris: Don't tell me you have to plug your pants into USB.

Dave: No, no, no. You know Athleisure. Mm-hmm.

Chris: Sure.

Dave: It's sweatpants for grownups.

Chris: It's just like what people wear.

Dave: [Laughter] Yeah. Yeah.

Chris: Yeah. I assume it's a trillion-dollar industry these days.

Dave: A trillion-dollar industry. I have a pair of Athleisure, but they're just parachute pants, like from the 1980s in a breakdance band. It's great. I love it.

Chris: I do like how it ranges from definitely sub-Walmart. I feel like I could go to the Dollar Store and get some decent pants that are in the Athleisure category.

Dave: Yeah.

Chris: All the way to the, like, look down upon Lululemon's style. You know? Just like pfft.

Dave: Yeah. You go to Athleta, there.

Chris: A really wide range.

Dave: Ladies kind of have it made because you have business pants that are just jeggings or whatever. [Laughter]

Chris: Yeah.

Dave: But they have little cuffs on the bottom and they can go to business. You know?

Chris: There's a little place right here that's an Orange Theory and Athleta and yoga studio.

Dave: See--

Chris: Just all three in one little building.

Dave: Just a turducken of health products.

Chris: [Laughter]

Dave: Lifestyle products.

Chris: That's right.

Dave: Anyway--

Chris: I'm going to open a fricken' Jamba Juice right next door and make sure they....

Dave: That's it, Chris. You've got it figured out. You find the market.

Chris: It's all about the brand combos.

Dave: Yeah.

00:01:52

Chris: There was a little Twitter chatter (I noticed yesterday) about the "Oh, no! New frameworks are bad," kind of thing. They're always -- some of them are really heartfelt.

Dave: Mm-hmm.

Chris: Some of them are just funny. You know?

Dave: Yeah.

Chris: I think Eric Bailey had a funny one, like, "Everybody reinvent in PHP."

Dave: Yeah. Yeah.

Chris: Because it's kind of true, you know, like PHP is 100 years old and does all kinds of stuff. What if nobody did anything but that? We'd probably not the Web....

Dave: If you replaced every curly brace in all these template languages with question mark PHP [laughter]--

Chris: Yeah.

Dave: You would literally not know the difference. I mean maybe some dollar signs missing. I mean it would just look so similar.

Chris: Maybe not entirely fair. In fact, I saw -- what was it? Devon Govett had a tweet about ESM. It was a little mad. It was a little like, "Was ESM worth it?" tweet.

Dave: [Laughter]

Chris: Because it caused a shitload of churn. Maybe not on the browser because the browser just sits around waiting for new APIs and then you use them. But in Node land, it was a mess. It's still a mess, and it's been half a decade of a mess. It's unclear when that mess is going to be cleaned up.

His point is, ten hears of churn, is it worth it so you can type import X from Y? Was it? It's too late. The ship sailed. Can't A/B test history - whatever.

Dave: You know he's intimately -- he works on Parcel; is that right? I believe so, or was involved, maybe. You know, I just--

Chris: Let's see.

Dave: Yeah. Maybe--

Chris: That's right. Parcel.

Dave: Okay, so fact-checked. I'm fact-checked - Snoped. You Snoped me and I'm correct. [Laughter]

Chris: Yeah. [Laughter]

Dave: He was maybe more intimately involved in the quirks and idiosyncrasies. I remember talking to, I believe, Bradley Mack. He was implementing ESM in Node. He just was like, "It's weird."

Chris: Oh, sure.

Dave: It's not the same as require, and so it had a bunch of hairpullers, I think. It was really tough.

Chris: Even if you get that perfect, that doesn't answer, "What about the million packages?"

Dave: Yeah. Yeah or now, written for the old style, but I think we're already getting a taste of what's good. We're starting to see. Esbuild is so good. It's so fast. It just zip-a-dee-doo-dahs.

Chris: But doesn't it kind of not care if what it's pulling from NPM is ESM or not? It jiggers them to work either way.

Dave: Yeah.

Chris: Maybe we would have got that tool anyway.

Dave: Yeah.

Chris: I don't -- it's just interesting to think about (a little bit). Certainly, having it in the browser is a good idea because I flippin' love it. Maybe they did it just for me.

00:04:55

Dave: I think we haven't seen the full - whatever- manifestation. I think we're getting close to import maps. I think we're getting close to Deno style where you import a URL, you know, import foo from URL.

Chris: Yeah.

Dave: That's just what we do. Maybe it's your own URL. It's probably unsafe to hotlink from somebody else's URL.

Chris: Yeah, and I think browsers are pretty close to telling us. HTTP 2 was a big deal. Now, browsers are supporting 3, whatever 3 is.

Dave: Mm-hmm.

Chris: You assume it's better.

Dave: Yeah.

Chris: In saying that the days of bundling even being necessary or a good idea are probably limited.

Dave: Well, and that too. Maybe we overdid it, like we went kind of hyper tiny modules, like this is a left pad - or whatever- and it adds a zero to your number. You know? Maybe we overdid it. Maybe that should have been part of the number extension or something.

Chris: Possibly. You know what comes to mind when you say that is how this conversation came up. I'm sure it's come up for a lot of people, but in our CodePen Slack, because we've been writing a lot of GO code.

Dave: Mm-hmm.

Chris: GO has this. More or less, kind of official stance of GO is just copy code when you need to.

Dave: [Laughter] Just copy it now.

Chris: You would say, for left pad, it would say -- yeah, don't. There should be no universal resource for left pad. When you want a left pad, put the function in that does a left pad right in the file that you need it in and so be it. The abstraction isn't hidden away from you. I think that became kind of the GO way. Not that I should be speaking on behalf of GO because I really don't know.

But that's true and the language itself, like, GO does not have a map. That's not a thing in GO. It's like, write a for loop and do the thing in the for loop. There's one loop primitive. It's for. Use it.

Dave: Yeah.

Chris: Very weird. Very weird. In JavaScript, we're like, [singing voice] "Give me the sugar. Sugar it up. Sugar town."

Dave: Yeah. I use--

Chris: [Laughter]

Dave: I don't use for loops anymore. I just use a series of Russian characters that make it ten times faster.

00:07:11

Chris: That's pretty funny. About the Node version thing, it was interesting. Some of that -- you know I started this thing talking about framework stuff. I'm hoping to get to the level of talking about Astro because it just dropped this last week. I'm a little excited about it, and I don't want to contribute to the world of "You need to learn every new framework that drops in the world!"

Dave: Hype. Hype. Hype. Hype.

Chris: "You should feel bad about yourself."

Dave: Hype. Hype. Hype. Hype. Hype.

Chris: Yeah. Yeah. Yeah, but sorry. There's going to be some hype from me because I think it's cool. I don't care if you actually learn it or not, but I do think it's done some smart things. I think it's a cool evolution. I think it's symbolic of what's going on in Web development overall - whatever. It's just kind of interesting.

I spun up a little site quick. I can tell you about that. It's not useful. It's just a demo, and it's related to things we've talked about here on the show before. Then I deployed it to Netlify and it just failed. Build fail.

Dave: Oh, no!

Chris: Dead. But interesting, I was able to get help on it really quickly, notably because they have a Discord.

Dave: Yeah. Yeah.

Chris: ShopTalk Show has a Discord.

Dave: [Techno voice] Discord.

Chris: As you know. If you were like, "I'm not going to join the ShopTalk Show Discord because, why would I join if there's only one thing I have in Discord?" But for me, it's like I have my video game, I have my framework, and I have my podcast. Now it feels very--

Dave: Very wholesome.

Chris: like a nice little place in Discord. Yes, very wholesome. Their Discord is active and useful.

Somebody noticed in the build logs that some flag got thrown for Node that said, like, "Turning on experimental ESM support," and that would only throw if your version of Node was super old because ESM is just built into Node now.

They said, "Oh, you're on an old version of Node." I run NVM and, for some reason, the default Node on my machine is like 6.

Dave: Oh! Whoa! [Laughter]

Chris: It's super old. It's like 1970 Node or something.

Dave: Yeah. Do you have to hand crank it or what?

Chris: Yeah. [Laughter] Yeah, totally. You have to feed it butter out of one of those churn things while wearing a super long dress.

Dave: You have a donkey in your backyard that drives your computer.

Chris: [Laughter] All I did was NVM use, and I put an NVM RC file in it so that hopefully it respects that when I go to that directory. I think you can put something in your package.json now, too, that says, like, "Node versions that." But I'm not sure how to get my computer to automatically switch to that version of Node while I'm in that directory. I'll have to learn about that.

Dave: Oh, NVM. NVM.

Chris: But anyway--

Dave: It's like NVM local - whatever - 12.13 or whatever.

Chris: But still. I open it up in VS Code, and then I type yarn run start - or whatever - or NPM run start. It will be on the wrong version of Node until I type NVM use. What I want is when I open that project, it's already NVM used to the right thing.

Dave: Oh, yeah. That's--

Chris: I want it to be automatic.

Dave: You just need that NVM RC in there and it should--

Chris: It should do it?

Dave: You "just" need it.

Chris: [Laughter]

Dave: But that tells the command line. It triggers it to do something.

Chris: I haven't actually tested the automatic nature of it, but anyway. Then I deployed it to Netlify and it's fine, so it certainly wasn't Netlify's fault.

Dave: No.

Chris: But it definitely is a thing that they should put. You know this is a brand new framework, so now they have to update the docs and be like, "These are our supported versions of Node." Maybe even ship with an NVM RC somewhere or something. I don't know. Interesting.

00:10:34

Dave: Astro, you like it, huh? It's new from Fred K. Shott.

Chris: Yeah, we've had Fred on the show before about Snowpack, so this was kind of, let's build a framework on top of Snowpack - a little bit. It certainly uses Snowpack. In fact, at the moment, it uses Snowpack too much.

Dave: Okay.

Chris: They run two Snowpacks while you're running it.

Dave: Why not? Yo, dog. Yeah. [Laughter]

Chris: Yeah. [Laughter] I'm not sure why. That's pretty deep in the weeds stuff. I don't think you have to worry about it that much as an average Astro user, but that's where they're at as a framework is early days. Let's fix some pretty serious rough edges and get it going.

To back a minute, what is Astro? You could almost think of it like 11ty (a little bit) in that it's designed to build static websites. Like 11ty, the ships zero client-side JavaScript. Not that you can't put a script tag in your 11ty site and run some JavaScript. You totally can. But 11ty itself doesn't put any JavaScript on your site, which is different than something like Gatsby, Next, Nuxt, or whatever.

Sure, it makes a static site, but it puts its own JavaScript in there too because it hydrates. I know those things are optional (to some degree) but the defaults are it's going to ship some JavaScript too.

Dave: Mm-hmm.

Chris: 11ty and Astro ship none at all.

Dave: None at all.

Chris: Zero JavaScript. But whereas 11ty is like, you're going to write in things that you really mentally expect to do that, like, it doesn't feel like a stretch for 11ty. To me it's like, yeah, it runs Nunjucks. That doesn't have anything to do with JavaScript, really. I mean I know that it technically kind of does under the scenes. But mentally, I think the model is, yes, these are just some templates. They get smashed in the HTML. Why would it need client-side JavaScript anyway?

Dave: Mm-hmm.

Chris: That makes sense. But with Astro, you're writing components that look like a Vue component or like JSX or like a Svelt component. When I say like-like-like, I mean they can be literally those things and they have a format called .astro, which is their own version of those that kind of smashes all of them together.

Dave: Yeah.

Chris: Which is just really weird.

Dave: It is because it's like--

Chris: But very satisfying.

Dave: Instead of Nunjucks where you put YAML front matter to be like, oh, the title is this, or something, Astro files -- because you write .astro files -- they have kind of like YAML front script. It's like dash dash dash and then you just write JavaScript. It kind of is like this single file component. I think somebody in the Discord mentioned it looked kind of like Svelte sort of, but upside down or - I don't know - with fences. You know?

Chris: Yeah. It has aspects of Svelte, for sure, and it has aspects of a Markdown file because it definitely has front matter. But like you said, it's not YAML. It's JavaScript. But it is within three dashes, which is -- [laughter] okay.

Dave: Okay. Yeah, so--

Chris: Yeah. [Laughter]

Dave: I guess it's just a fence. I mean it could be a script tag, but it's like a fence around the script and the template.

Chris: Yeah. Yeah. Well, it can't be a script tag because it allows you to put script tags--

Dave: In the thing.

Chris: --down in the HTML. So, below that is just "some HTML." But the HTML is a little magic, just like in Vue it's a little magic. There are V4 attributes and stuff. Svelte has a little magic. You know? JSX has less magic for some reason. It's just like--

Dave: But where Astro and maybe other things are different is, Astro's goal is to not spit out JavaScript (unless you want it to) - sort of. It just says, "I'm going to just -- oh, you put a fetch in there. I'll go fetch. I'll execute the script. Then I'll render the template or the partial." That's cool.

Chris: It is cool. It compiles definitely to HTML. The output of it is HTML. Just like Next would - or whatever. It wants to make a static template, and so data fetching is a part of that. It's a little bit of a mind trip of how this works, to me.

You could put a fetch for external data up in the fences of your component. You know? Say remote data equals fetch. This fetch is Node fetch. It's whatever. It's not client-side fetch like you might expect it to be. You're kind of writing Node up there.

Dave: Yeah.

Chris: So, if you do a console.log up there, guess where it executes. It's not in your browser, so that's the kind of mind trip. You can't open the console and see the console.logs from up in your fences. You have to be looking at your command line to see the output from that.

Dave: Whoa! Interesting. That's a mind-bender.

00:15:20

Chris: It is a bit of a mind-bender to me. Okay, so then you do that and then the data is available for the template, which is prebuilt then. That's happening during your build process.

Dave: Mm-hmm.

Chris: So then, if you were to deploy it to Netlify, it's not going to fetch anymore. The fetch happened during the build. It will not -- there is no client-side JavaScript, so that fetch is over. That was a one-time fetch.

If you want it to do a client-side fetch, I think you could, but it's not philosophically opposed. It's just not like the primary philosophy of Astro, I don't think.

Dave: That's what's cool, too, is how it has built-in hydration. In my opinion, a lot of hydration is kind of like just ship a static thing and then we'll just go do everything later. You know? But it's kind of like partial hydration. It's like if you write -- I'm looking at the docs right now -- my component (like bracket, open bracket, closed bracket, my component), that will render the HTML only version. My component colon load renders the component on page load, so now it's a dynamic component. Now it's probably in JavaScript. My component--

Chris: Right. It's real easy to tell your component to be dynamic, if you want it to be.

Dave: Then my component colon idle will wrap it in a request idle callback, so it'll only render when the CPU is like, "Cool. I'm done with my jobs. What's next?"

Chris: That's some next-level fancy shit.

Dave: Maybe I am request idle callback, like in my spirit. Am I realizing that right now? [Laughter]

Chris: [Laughter]

Dave: That's like my whole MO. Anyway, okay. I've seen this person, too. My component colon visible is when the intersection observer -- like when it's in the viewport, then it will fire. It wraps it in an intersection observer.

Chris: Right.

Dave: Just like some people only do work when somebody is looking at them. You know? Like, "Hey, buddy. How's it going?"

Chris: That's a callout moment.

Dave: "Oh, yeah. I was totally just working." My thermostat is intersection observer. [Laughter]

Chris: [Laughter] Oh, my God. Yeah, when you go to the doctor and you just happen to be fine that day.

Dave: Oh, yeah.

Chris: The waiting room intersection observer fired. I say it's a callout moment because that does then inject a little bit of client-side JavaScript because, you know, it has to for the intersection observer. But it's pretty minimal, of course, and it's not like - whatever. It's just the way it is.

Dave: For me, I think this is a framework for writing apps, and even you can use React and Preact and Svelte and Vue inside of Astro files or inside of that Astro system. That's really cool. More recycle ability if you have a design system in Vue and you have to just spit out a static homepage.

Chris: Right! That is notable, isn't it? We talked about Astro files. They don't have to be Astro files. They can be .vue files. They can be .jsx files. They can be .svelte files, and Astro knows how to deal with them. I think it's limited to those three at the moment. It's designed, of course, because it supports all three, to be very extensible in what the compiler is - or whatever. I'm compelled by the .astro files. If I was going to build a new Astro project, I'd probably use those because they look cool.

Dave: You know what it reminded me of, .astro files, Chris? HTML imports! What a novel idea here in the year 2021 that no one is talking about HTML imports and why that would be good. No one has ever done that before, on this podcast in particular.

Chris: Fair. Fair.

Dave: [Groans]

Chris: There are weirdnesses. The props are weird, I think, but kind of cool. I'm so used to JSX where the standard procedure is to de-structure all the props in the argument of the component.

Dave: Mm-hmm. Mm-hmm.

Chris: Then you know what you have and it feels like a little menu of what's available to this component. The menu then moves up into the fence above where you have to declare them all as variables that are coming in. Fine. It's just weird. They're, for some reason, typed, which I don't totally understand, but fine.

Dave: It was like export let title colon string - or something, I think was in your little--

Chris: It's like not TypeScript. Yeah, it's pretty weird. I don't know. Maybe I haven't experimented that much, but--

00:19:44

[Banjo music starts]

Chris: This episode of ShopTalk Show is brought to you by WooCommerce. You know it's a plugin for e-commerce for your WordPress site.

I run it on CSS-Tricks. For example, you buy a sweatshirt. It's drop-shipped, so you buy it and a company prints it and puts it in the mail and sends it to you. How awesome is that? Pretty cool, right? The sweatshirts are super nice. it's easy for me. You get what you want. I love it. We sell membership and stuff, too.

With WooCommerce, you could sell a haircut appointment, whatever. It's amazingly flexible in that way. You want to offer your customers multiple ways to pay, so maybe you throw the Stripe plugin in there, and now you're taking credit cards. It's not the only one that can do that, but it's a super popular one because Stripe is nice.

But, hey, you don't want to lose a sale just because somebody prefers to pay with PayPal, right? Maybe they just like dealing with PayPal. I've been in that mode in my life. I want to offer PayPal. I download the PayPal plugin. I turn it on in WooCommerce. Now I can take PayPal. You know there's some setup stuff you've got to do, but I had a PayPal account anyway. It was no big deal.

Guess what. They offer Apple Pay now, too. That's significant for me. I didn't just turn 40, but I wrote this blog post "40 for 40," like thoughts from my 40th birthday. You know, "Oh, me, Chris. I'm so cool."

One of them I wrote was I never regretted being a life-long Apple fanboy. I just kind of am. It's not like I don't like other platforms. I do, but I just like Apple stuff. I have their computers and their phone and their TV thing. I just like how they look and work and do, and a lot of stuff that Apple does.

They have this product called Apple Pay, which means my credit cards are on my phone. I literally go to the grocery store by my house, buy the stuff, and I just whip out my phone, double-tap, and do my face recognition thing so it goes through. It's just a really nice way to pay. I don't have to touch anything. It's super secure. I put it on the credit card I want to put it on. It's just a nice system.

Well, wouldn't that be nice if you could offer that not at my grocery store but on my e-commerce site? Yes, I can do that now with their integration. It's just a plugin like the other two are. Pretty cool. Now people that like Apple Pay (like I do) can check out from my store with Apple Pay. Cool!

[Banjo music ends]

00:22:05

Chris: So, remember in a previous show, we talked about Alex Riviere's Netlify thing where he made a site at first that did a client-side fetch and it hit the WordPress API of CSS-Tricks, grabbed some data, blasted it onto a page, and then he refactored it as a cloud function. Then he refactored it again as an on-demand cloud function from Netlify. All very cool, right?

Dave: Mm-hmm.

Chris: But I was like, "I could do that." But instead of doing it -- you know, because it's like - whatever - 50 lines of Node, wouldn't you say, that he did that? You have to run the Node fetch, import that, and then template it all out and all that.

Fine, but this Astro thing is conceptually the same thing, only it runs during the build process and not as an on-demand builder. It just moved where that happens to a different place. I was able to build the exact same site, pretty much. It took me like 30 minutes.

Dave: Yeah.

Chris: And I've never used Astro before, so I'm a little stoked about the Astro thing. It's pretty cool.

Dave: You kind of use less technology because you're not using the on-demand builder. You're just using the function, basically. Or you are still using an on-demand builder?

Chris: I don't think so.

Dave: No. Yeah.

Chris: No, because it's just static. It's just static files. If you were to push again, because remember Alex set up an "if this then that" cron, essentially, or maybe he used a GitHub action -- I don't remember which -- to just run every day and get the new content, break the old cache, and then have the new one. This would literally be the same. You just run the build again.

Dave: Yeah.

Chris: The build then runs again and breaks the cache and has the new file and whatever. I didn't even bother to set that up, so if you use my demo, it will be the same content from the last time I run the build process, which I'm sure I will forget about and never update again.

Dave: By the time you're listening to this, that was weeks ago. [Laughter]

Chris: Yeah. [Laughter] Maybe I'll bother to set it up, but this was more of an exploratory thing, for me, with Astro. Of course, I hit a WordPress API to build the site, so doesn't that immediately make you think about, "Well, this could be an in for headless WordPress"? That's a type of site you could build with this.

Dave: No.

Chris: It just feels so natural to me. What I'm big on is building in components - period. I want to build that way. The fact that I still maintain a WordPress site that's not done in that way, it doesn't feel bad to me. CSS-Tricks does not have any of this technology going on. It is just fricken' PHP templates, the classic WordPress way. I don't necessarily regret it, but I do feel the DX burn a little bit when I go back to it.

Dave: Mm-hmm.

Chris: My PHP doesn't have Prettier, so I'm hand-formatting those files. I'm like, meh-meh-meh. There's no great hot module reloading, so I update some stuff and I go back to the browser and I hit command refresh to do the thing or wire up some third-party thing to help me refresh the page. But it's not that fast, good, refreshing experience that you're used to.

Notably, when I was playing with Astro, it was broken, and they know it's broken.

Dave: Okay.

Chris: There was no hot modular reloading in Astro either. I assume they're going to fix that because they literally have to or nobody is going to use it.

Dave: I think it's on the....

Chris: I feel like those are table stakes.

Dave: I think it is. [Laughter]

Chris: Yeah. [Laughter]

Dave: I think it says "features."

00:25:30

Chris: You've got to have that these days. I'll tell you; I worked on two different Next sites recently. It's awesome. The fricken' reloading speed and action in Next.js is excellent.

Dave: Yeah.

Chris: CSS -- I change a hook in my React and it knows exactly what to do. Nothing changes. I just go hit the button again and have a different console.log somewhere and it just fires. It's just perfect.

Dave: I use -- I'm on two Nuxt projects, and it's the same.

Chris: Similar, yeah.

Dave: It can be surprising because I'll hit save and I'm like, "Oh, you just did it. You just knew." You know? Sometimes, it gets beefed, like when you switch to like scope styles or modify something like that, like the scoping.

Chris: Oh, sure.

Dave: Then all these tools are built on a big Webpack system, so it's kind of hard to debug. You get an error and it's like, "Error in Runtime JS." You know? You're like, "Hmm. That could be a big one."

Chris: Oh, right.

Dave: Might find that later.

Chris: Async iterator.

Dave: Yeah.

Chris: Yeah, that's another kind of bonus thing. I tried to ask around about that the other day because when you have an error in Next, they use some third-party thing, which this is what I'm curious about. What is it? Did they write it or what? It definitely feels like a third-party thing that a really bold error message comes up as a modal with a stack trace in it and syntax-highlighted code that shows you the line of code that it broke on. That experience is tremendously good DX as well.

Dave: Mm-hmm.

Chris: That I just don't have in other projects that I work on, and I fricken' love it. It's so well done.

00:27:17

Dave: Like any kind of auto-complete. Tailwind, I'm not the biggest fan. That's fine. If you use it, that's awesome. I support you.

Chris: Yeah. Where are you going with that? I think it is built into Astro, if that's where you're going.

Chris: Well, I was just going to say, like--

Chris: Well, I think it has some kind of support.

Dave: Tailwind auto-completes and stuff like that are really good. Even if you're -- I feel like auto-complete and stuff like that really enables you to write Tailwind. I've been thinking about utility classes. I'm not sure if they're super helpful until we had really good auto-complete, or if you're in the browser and you can hit the class thing and start typing a class, guessing a class, and then it'll show you which one.

The auto-complete stuff makes Tailwind and stuff like that easy because you can just start guessing what it's probably called and then it'll auto-complete for you. I just want to put that out there. That's a very helpful feature. One day - I don't know - we'll all--

Hopefully, HTML or Web components or our own components, they'll do a good job at just auto-completing the props that you need and stuff like that. I think we're pretty close here with Intellisense and all that stuff.

Chris: You want to write in TypeScript, you can write in TypeScript in it. You put a style block in it and it's automatically scoped, like Svelte, and you can do it in Vue. Pretty cool.

Dave: I love it. Oh, scope styled. What another novel concept. Man, maybe some browsers should not implement it. You know? That would be good.

Chris: Oh, my God. I've heard chatter. I think we're going to get it.

Dave: Get it back? Is it coming back?

Chris: It's going to look.... I think so. I think it will, as well as the super weird Miriam Suzanne imported CSS @layers.

Dave: Mm-hmm. Mm-hmm.

Chris: You know? That's hard to describe. It's not loaded up into my brain at the moment, but at one point it was.

Dave: Yeah, because you have -- I think her idea is, like, you have a hierarchy of what renders. The user agent style sheet and then the author styles and then the browser or user overrides and stuff like that.

Chris: Yeah.

Dave: I think the idea is you can create layers, so if I know this is my bootstrap layer, I can say, okay, bootstraps at this level. Anything else should be above bootstrap. If I write some bootstrap class, it should override the bootstrap class - or something.

Chris: Right. But the point is that you could still load bootstrap last. The source order won't matter like it does now.

Dave: Mm-hmm.

Chris: You could be like, even though I've loaded this last for some godforsaken reason, treat it like I loaded it first.

Dave: Yeah, and now my stuff comes--

Chris: So that any other stuff--

Dave: It overrides it, basically.

Chris: Yeah. Yeah. It's not scoped, but it helps with that stuff. Not as much as scoped does, though. Scoped is amazing.

Even in Astro, I don't think they -- it looks like CSS modules, but it's not really because it's like Vue. You know how satisfying Vue is because you write a style block and you just target stuff above it. You don't have to use a class. In CSS modules, you have to use a class. Whereas in Vue, you just use whatever the hell you want to use and it scopes it.

Dave: Yeah. It just kind of injects a data attribute on everything.

Chris: Yeah. This does and it adds another class, so it layers up the specificity of everything. Even if you type H2 color red (in both the HTML and the CSS) it'll be like, h2.astro dash blah-blah-blah. Then the CSS will be h2.astro blah-blah-blah, and that'll do the color red, so it adds extra specificity but it does target it very, very specifically. [Loud exhale]

Dave: Scoping....

00:31:11

Chris: Tailwind is in there if you care about that. It ships a Markdown component, so you just import Markdown from Astro and then do an angle bracket Markdown. Then just [barf] some Markdown in there.

Dave: MDX vibes. I mean this is so--

Chris: Well, if you want MDX, then you import that, which is a little different because it's like Markdown that also supports components inside of it.

Dave: Oh, yeah, yeah, yeah.

Chris: It's really getting inception-y.

Dave: Right. Okay, yeah. No, that's true. It'd be a little bit different, but this just parses Markdown. That's great, too. Smart of them to ship that because--

Chris: Well, that's why you would use 11ty or one of these other SSGs. I've got a folder full of Markdown files, like you do for daverupert.com. I need to use those.

Dave: Mm-hmm.

Chris: I can't just change formats or go put them in a database or something.

Dave: Yeah.

Chris: I want my folder full of Markdown files. That's what I want.

Dave: Yeah.

Chris: In Astro, I think you then fetch them weirdly. In 11ty, I think you make a collection, right?

Dave: Mm-hmm. Mm-hmm.

Chris: Don't you specify where some crap is and it turns into a collection that you iterate on? I think, in Astro, you fetch it but it doesn't make a network request. It's internal. That's its mechanism for grabbing internal content.

Dave: Yeah. I don't know exactly what Astro is doing. But, yeah, in 11ty you just can say, "Go get files from this folder," and make a collection. Then you iterate on that and so special things with that.

Chris: Sorry to hijack that. We're half an hour into this thing and I've just--

00:32:40

Dave: Well, but you know this is just exciting. I mean it's worth mentioning, too, the React 18 beta - or alpha. I should know. I'm a news podcast. But the new React is kind of coming out, a version of that, launched on the same day as Astro, which is kind of weird. Probably enhance those feelings of, like, I can't keep up-ness. [Laughter] But it's out, and it has the suspense in there, so kind of a similar thing.

Chris: Oh, they shipped it stable. Oh, wow.

Dave: I think....

Chris: Or no, not really because it's alpha.

Dave: Yeah. So, stable-ish. That's where you go suspense -- this is a higher-order component like a wrapper thing, you know, wrapper component.

Chris: Yeah.

Dave: So, you write suspense, which is sort of like saying everything inside here is going to kind of change or shift around. But then you say fallback equals--

Chris: Spinner.

Dave: Squiggly spinner component. You know?

Chris: Skeleton.

Dave: Skeleton component. And so, you get kind of like a default, like, this is going to go fetch data, sort of like in this partial hydration system in Astro. When this goes fetches data, you're going to do this instead; do this while that's happening. Or, if it fails or whatever, just show this. You know? So, I think that's really cool.

That got me thinking [laughter] just because it's -- and I'm coding in Nuxt and I'm writing all these fetch requests to API endpoints and stuff like that. I was thinking about how much we have to -- now that we're in client-side development, we have to handle every single failure, the loading, the error, the "Oh, it came back with zero items." You have to handle all those states in every single component that fetches data. It's exhausting to code. You know? Of course, I should be using X state, but I'm not, so I'm using, like, if this dot is error equals false. Ugh.

I feel like when we did server-side development, PHP - whatever - Rails. You got 200 300, 400, 500 errors all for free out of the box. It just failed. It gave you a big screen that said, "Oops. I didn't make it, dude. Sorry," or whatever.

Chris: Right.

Dave: But now you just have to handle everything at the component level. It's a lot of work.

Chris: Right.

Dave: In my opinion--

Chris: We have a very fancy component error wrapper machine at CodePen that we had to handwrite that's like, if one particular component fails that it will catch them.

Dave: So, it's a giant tray catch.

Chris: And not fricken' white page of death.

Dave: [Laughter]

Chris: Yeah, basically, but that you can import at whatever level you want it to. We have, for example, if you're looking at CodePen, you see the grid of stuff. There are probably four of them that you're looking at. That's four opportunities for something to be wrong.

Dave: Oh, yeah.

Chris: You know what I mean? Some kind of data discrepancy or something. If something were to throw in there, you could white screen the whole page because React isn't super cool about that. It'll just be like, "Oh, my God! I'm dead!" Unexpected -- ack!

Dave: One thing went wrong. Sorry, everybody. We're done. [Laughter] Yeah, yeah, yeah.

Chris: Yeah, so we have this little wrapper that's like, we'll put it around that, for example. Did anything at all go wrong in that component or any of its children, it just then doesn't render it. It's just a blank space, but at least it didn't kill the entire page. Then it can throw out a century, too, and we can be like, "What the hell happened?" We have some log of what it was.

Dave: Oh, see, that's kind of cool. Their logger, sort of.

Chris: A lot of times it's like something was deleted that we just weren't ready to have not be there.

Dave: I wonder, too, if I should wrap in that or the result is nothing if there's an error. You know? Just pop it off the page. Usually, you try to render something, like a title, hoping that then the content is magically going to show up, and then it doesn't.

Chris: [Laughter]

Dave: Anyway--

Chris: The trick is, Dave, just to put a question mark after every single variable and function that you write in your entire JavaScript.

Dave: Yeah. Yeah.

Chris: That way nothing can ever be a problem.

Dave: Error question mark.

Chris: Like optional chain everything.

Dave: Oh, yeah. That's good.

Chris: [Laughter]

Dave: I do have a few of those in there. Thank you for code shaming my codebase.

Chris: Yeah.

Dave: Definitely use that.

Chris: Oh, they have their place.

Dave: [Laughter] I have no idea what it's transpiling out to. I really should know, but probably just a gross, gross ternary operator. But whatever. It's fine.

00:37:29

Chris: Yeah. I always think of them as objects only, but I watched a YouTube the other day where they used it on a function. I was like, "Oh, that's interesting that you can check if a function exists before calling it with that, too." It looks extra weird because you go .?()

Dave: Yeah.

Chris: The dot is in a weird place.

Dave: Oh, really? Okay. It's not question mark dot?

Chris: It's not function?. -- no, because the question mark, I think, is valid. It could be part of the name of the function.

Dave: Okay. Okay.

Chris: It has to be dot question mark.

Dave: I'm going to see what this -- oh, okay. All right. I just did foo?.bar in the Babel REPL, right?

Chris: Yeah. Did it compose? Was it gross?

Dave: It's kind of gross. It's like--

Chris: [Laughter]

Dave: Underscore foo, because that's what I called it, right? It underscores all these variables, right? _foo=foo==nol or _foo==void0? void0:foobar. Yeah, it basically just makes a giant ternary that it's kind of assembling on the fly. It's not the end of the world. Yeah, it's gross, but it's not the end of the world. Yeah, it just keeps nesting ternaries to get you there.

Chris: Right, and there is a world in which you just don't transpile it because you just don't care.

Dave: Yeah. Yeah, I just assume not every browser on the browser spec is doing it, especially if it's showing up in the REPL here by default. But anyway, that's interesting. Anyway, not as bad as I worried, so that's fine.

00:39:25

[Banjo music starts]

Chris: This episode of ShopTalk Show is brought to you in part by CMS Hub by HubSpot. Maybe you know HubSpot as a CRM. It is that. It has a bunch of different hubs, you know, hence HubSpot. [Laughter]

There is a marketing hub, meaning lead generation and automated marketing type stuff. A sales hub, which is the CRM which does stuff like schedules meetings with your leads and provides quotes and stuff. They have other hubs.

But CMS Hub is what we're talking about. It's a content management software that's super flexible. You can build whatever you want on it. In fact, it's like any other CMS. You work locally using whatever tools you want and then deploy to HubSpot. It's your host and it's like a framework for content.

What's cool is that the CMS part of it is tied to the CRM parts of it, meaning that you can build a website that people log into and use in that way, but then you're also customizing it because you know who they are and the fact that they're a lead and you know some information about them. You can customize the website around that. That's pretty darn cool.

This is an interesting example, I think. They have a real estate site where, normally, you think of a CRM as people in the CRM, but in this case, properties are the things in the CRM, so like 123 Elm Street - or whatever. That way the website (powered by CMS Hub) is grabbing that CRM data and making a website of real estate listings. But the real estate listings are in the CRM, so you're gathering leads on it, like Julie wants to go see the property at 123 Elm Street. I think that's just a really cool and interesting idea.

It's loaded with other built-in features, like this is pretty advanced style hosting. They have serverless functions, for example, which is a pretty modern, cool idea that I use all the time. There's membership management in there. Again, these are websites you log into, not just brochure sites or whatever.

There's search built in, for example. You don't have to reach for some third-party search. They've got search handled for you with it.

That's all I'll tell you for now. That's CMS Hub by HubSpot. Thanks for the support.

[Banjo music stops]

00:41:51

Chris: Let's see. In other news, the big Apple event happened. We had a little Discord watch party. That was kind of fun.

Dave: That was fun. Yeah.

Chris: Web-wise, the biggest things were the metatag, so the new design of Safari. Took some notes from the Firefox playbook, I think. The tabs are now pills.

Dave: Yeah.

Chris: You might say.

Dave: Tabs are now floating tabs.

Chris: But there's very little UI - very little UI. It feels like they -- even that was part of the hype videos, right? They had some icons that flew up in the air and then went into a hamburger menu, essentially, like, "Sick, of those buttons? We'll put them behind another button, and you're going to fricken' love it."

Dave: You love it! There are tab groups, I think, is kind of a big deal for Safari. I will actually use this because I have so many tabs on my iPad or iPhone, just thousands of tabs at all times. [Laughter]

Chris: [Laughter]

Dave: I can usually break down those tasks into, like, I'm on a shopping quest or something, or I'm whatever. I'm just like, whatever, these are blog posts I want to read, or something request. So, it'd be really easy to drop those into a thing. That's cool.

Yeah, that meta-theme color stuff is really cool. Then there are also some implications.

Chris: Well, it's extra cool. That's where I was going with the minimum UI is that so the theme color then can bleed up into the URL bar and the whole thing.

Dave: Mm-hmm.

Chris: If you set the theme color, basically your entire screen, or definitely your entire browser window can look super integrated.

Dave: Yep.

Chris: It looks fricken' great, I think.

Dave: Even the URL bar is inside the tab when you click it. They basically made it a one-liner.

Chris: Yeah, it's cool.

Dave: You know that's really pretty cool.

Chris: Right. Chrome is now the one with the, ew, what's up with all the UI? But Chrome being the last one that actually connects the tab to the content, but whatever.

Dave: [Laughter]

Chris: I'll get down off my horse for a minute. They didn't invent something kind of for once. Sorry, Apple. You deserve that. But Android, Chrome has meta theme color, too.

Dave: Mm-hmm.

Chris: That sets the URL bar and stuff, so kind of Chrome did this first, and Apple is just like, "We'll use that same standardized fricken' tag."

Dave: Yeah.

Chris: Thank you. Great. That's totally the way to do this.

00:44:15

Dave: Well, you know, the floating tabs, iOS is kind of an interesting thing because they removed the location bar. There's now a floating tab at the bottom of your screen that you click into. In some ways, this is awesome because it maybe eliminates that 100 VH bug that we've all experienced where you're like, "Make this--"

Chris: Did they say that, or is that your insight?

Dave: That's my theory because they've removed the Chrome. The VH bug was because you'd slide and the UI would shrink and move and warp. You know? To me, it seems like it's maybe fixed, but if you ever anchor tabs to the bottom of the viewport, which is what every blog says is better than the hamburger menu, guess what. That floating tab is now over your tabs or it's over your....

Chris: Yeah.

Dave: Now we have--

Chris: Do we get an ENV for it? Can we be like, bottom ENV--?

Dave: We're recording this on a Thursday. Behind the scenes here, removing the fourth wall.

Chris: Oh, that's right. All this info comes out tomorrow, doesn't it?

Dave: Yeah. I think Jen Simmons is doing an Apple talk about how to style for the browser on Friday, so it should be up on the WWDC talks or whatever. Jen is smart. This has been thought of, considered, or whatever.

All things aside, I'm into kind of these. Firefox had floating tabs, too. I'm kind of into these radical kind of switch-ups just like, "Hey, let's just go funky with the browser for a minute." I don't know. It's not that radical. It's just ten pixels of gap. [Laughter] Let's just see it get weird. I don't know. I'm interested.

00:46:02

Chris: There's the meta-theme stuff. Maybe bigger, I mean that's just quality of life stuff, which is interesting. I don't know if just that would get me to make Safari my primary thing, in part because their dev tools are a little behind, I feel like, and Chrome has been innovating a lot there and Firefox, especially for front-end HTML, CSS people, it's kind of been the winner. They had really quality stuff.

Safari is kind of the last of the three, really. So, why would I use that one? All day long, every day, that's all I do is front-end development. But they've said that there's a bunch of good quality changes. I don't know what they are. I assume we'll learn tomorrow. Anyway, cool. Maybe they'll be really good. Maybe they'll just be usable and on par with everything else. That'd be cool.

I always thought that there already was a Web standard for Web extensions already. Don't Chrome and Firefox? I think they're a little different, but they're largely the same.

Dave: Yeah.

Chris: Certainly, you see a lot more Web extensions for Firefox and Chrome than you do for Safari. Maybe Safari was the standout holdout. You had to code something in X Code to make it work, or something. They're now saying that's not true anymore. We're going to use that same Web standard, too.

Whether it's that exact Web standard or they're evolving it or something, I forget. But that's freaking notable because, if Safari can support all the same Web extensions and everything, I mean, think of all the ones. I use a bunch of them that I love.

Ghostery, although, that's a privacy-based one, so there's something to talk about there.

1Password is massive. I use the crap out of 1Password on my Mac.

Dave: Yeah.

Chris: Then Notion Web Clipper. I use Appcues at CodePen, which is just an app. I don't have time to talk about all that, but Buffer. There are just a lot of them that these are life plugins. These are like, I need these to do my job.

Dave: Yeah.

Chris: The fact that I could maybe port -- that all of them will be ported to Safari is, like, if you're shooting for browser market share, well, good idea. And the kicker; they're going to work on iOS Safari too. Great. Good move.

Dave: This could be a big deal for Coil, the Web monetization platform, because you had to use a weird browser.

Chris: Yeah. Right.

Dave: If they can roll out and I'm just plopping my Bitcoins in people's wallets, my Ripple coins in people's wallets, then great.

Chris: Yeah.

Dave: Let's go.

Chris: They say that mobile traffic now -- remember when it cusped over desktop traffic?

Dave: Mm-hmm.

Chris: It was like, yeah, it's about 50/50 now. I think that was years and years ago. Now it's like 80/20, 90/10.

Dave: Yeah, I heard--

Chris: Global traffic of that stuff, it's a mobile world out there.

Dave: Yeah. I heard -- or somebody was talking about that. It shocked them that it's just 80%.

Chris: I saw a Laurie Voss tweet.

Dave: Yeah, and its average DPI is 1.5, at least, on all computers.

Chris: Yeah.

Dave: Even DPI is more.

Chris: We get all these extensions on iOS, too. Actual working 1Password, oh, my God. I just get shivers.

Dave: That would be different.

Chris: That's going to be awesome.

Dave: Yeah.

Chris: But what else can you do? All kinds of crap, like, will somebody make actual dev tools for iOS Safari?

Dave: That would be cool.

Chris: Probably.

Dave: Like Vue dev tools.

Chris: Do it. Charge $100 for them or something. Of course, what everybody wants is to make them open-source and free and awesome.

Dave: No.

Chris: That's great, but it's going to be a bunch of work, so get paid, yo.

Dave: Put the Apple tax on there. [Laughter]

Chris: Although, you know it was brought up in the Discord. I didn't know about this and ended up making a blog post semi sort of about it was that AppInspect, which runs on Windows, that allows you to plug in your iPhone, USB (or whatever else), iDevice, even into a Windows machine, and Inspect will see it and open up dev tools for that thing, Chrome dev tools.

Dave: Yeah.

Chris: If you really like Chrome dev tools, which probably are the leader (like it or not) in dev tooling, now you can Windows Chrome dev tools on a native iOS device. That's unique. You should know that that's possible.

00:50:25

Dave: Coming from a person, as a person who developed on Windows, you used to have to, you know, like, "Hey, can you pull this up, plug your phone in, and then open Safari dev tools and see why this doesn't work?" It was such a cumbersome experience to even get any amount of data out of the browser, or even debugging.

Chances are, it was on Safari desktop, too, so it's like, "Oh, this doesn't load in Safari desktop." It was like, "Why?!" You know? So, it was an issue to debug. Or like, "Can you send me a screenshot of what this looks like?"

Chris: You would just punt it. You had no -- there was no solution.

Dave: There's no solution. Yeah, I'm not having the greatest Apple experience right now in my life [laughter], but I just feel like if Apple wants developers to support their products, fringy your products like Safari. They need to help people out, so give them the APIs to debug it.

Chris: Right. I think what people were maybe hoping for something a little more bombshell-y. There is a lot of criticism thrown at Apple - period - and particularly Safari because, especially on iOS, there is only Safari for iOS. A lot of what people want is, "Let me put Chrome on it. Let me put Firefox on it. Let me put an alternate rendering engine in it. Why on Earth do you protect that?" That is the kind of -- you know it just seems unfair.

We did not get that. There is no momentum in that direction at all. It seems highly unlikely that we will ever get that.

Then the problem is, okay, well, if you're not going to do that, could you at least make it good? [Laughter]

Dave: Yeah.

Chris: You know?

Dave: Yeah.

Chris: Could you at least be on par with APIs available elsewhere and stuff? Lest you are holding back the Web, so that's a whole thing. The canonical article there is Alex Russel's recent one. I can't even remember the title of it, but it was him not just fist-waving about it but just with bucketloads of data on the APIs, when they shipped, and what it doesn't have.

00:52:47

Dave: Kind of the history. Safari is in an okay spot right now, but it's the historical sort of like this didn't come out. For eight years we couldn't use this - or something - because it just wasn't prioritized whatsoever.

Chris: Right. For us Web people, there's still plenty of gaps, like, why can't I write a great Web app and have a good install experience onto the home screen, maybe even be in the app store, maybe have the same quality of push notifications that native apps get? There are still some gaps there that make the Web a real kind of second-class citizen.

Dave: There's something to be said, like, if you want Safari to get more Apple bucks, use Safari. They'll pay attention to numbers, and they'll allocate people accordingly in time, money, and attention accordingly, so use Safari.

That said, Safari on iOS, a lot of people use it and developers are like, "Let me do progressive Web apps. Then it's just like cricket town." So, I think there's some good advice in, like, if you want it to get better, use it. And tell people to use it. Don't just use Chrome.

Then on the same side of that coin, a lot of people use mobile Safari and want features in mobile Safari and they don't show up.

Chris: Well, things look positive recently, though. Just the extensions thing is a big deal.

Dave: That's a big thing. I'm looking at the release notes here. There's top-level await showed up. That's good. A few more things. I think it's been in the kind of betas, but they just did focus visible, so focus visible made it.

Chris: That's not dropped yet, but Igalia is working on it.

Dave: Yeah. I think it's--

Chris: But it's in there, though.

Dave: Yeah. Yeah, and then aspect ratio, LAB, LCH color, so like a whole new color thing.

Chris: Ooh...

Dave: It's going to get--

Chris: I thought they were first to launch with that already? But they have even more now.

Dave: Yeah, I think, it's going to be in there.

Chris: Oh, they had display P3 or something.

Dave: Yeah. Yeah.

Chris: That one. That was the first one.

Dave: Yeah, predefined. Added support for predefined color spaces: SRGB, display P3, A98, RGB. All right, we're done. I don't know what these are. XYZ sounds fake, but anyway, there are.

Chris: [Laughter]

Dave: You know Apple prioritizes what they want to prioritize, like color and looking interesting. I think they just may think that makes a big impact, so it's more important. And it is. It's fun. It's interesting. I played around with it, so it's fun.

Chris: You can download 15?

Dave: Well, some of that stuff was in Safari technical preview.

Chris: Oh.

Dave: Notably, aspect ratio, which will release me from my Fitbit's Horcrux. That's going to be in Safari 15.

Chris: Yeah.

Dave: Come September, Chris, I'm free to spin up another open-source repo. [Laughter] So, you know that's great.

Chris: Well, it was you who opened up Safari TP and then did the color contrast.

Dave: Color contrast.

Chris: Which is the world's coolest CSS function.

Dave: I hope that makes it. I don't know. It's not listed here specifically, but that would be cool.

00:56:14

Chris: Yeah. Yeah. What's the other one that's so exciting? I need to look into this more. What was his name? Pollard, I think, wrote a Smashing Mag post. I'm trying to find it, but that's bad. Yeah, Barry Pollard, "How to Fix Cumulative Layout Shift Issues." No, that's not the one I'm even talking about. It was a Smashing Mag article that Barry wrote about the new font properties that you put in. I think you put them in the @fontface. Oh, I forget.

Dave: Oh, yeah. Yeah.

Chris: They do stuff like make your fallback font match the metrics of the font that you're loading in is going to do. That way there's no shift. It just looks really -- it's a really subtle shift from fallback font to correct font.

Dave: Interesting. Yeah.

Chris: Oh! It's so good. This was one of my favorite CSS-Tricks of all time was a video from the front-end center that did this exactly. They used Monica's little font fallback tester thing and tweaked the metrics so that they were absolutely perfect. There was no shift whatsoever when the new font came in, but it required the JavaScript font loader to do it, which is kind of fine. It was a pretty small little piece of JavaScript that could watch and change some classes. But that's JavaScript. That's a little dependency. That's a little thing that can go wrong. That's a little technical debt.

This is the same exact idea just moved to CSS. So cool.

Dave: Yeah. No, I think it's cool.

Chris: Okay, that's it. [Laughter]

Dave: Exciting. That's a lot of stuff to drop. Hey, exciting times for CSS in the year 2021.

Chris: I know. I know. There's so much to talk about.

Dave: All right. Thank you, dear listener, for downloading this in your podcatcher of choice. Be sure to star, heart, favorite it up. That's how people find out about the show. Follow us on Twitter, @ShopTalkShow, for tons of tweets a month.

Join us on the Discord, patreon.com/shoptalkshow. Hop into the [stutter] Discord.

Chris, do you got anything else you'd like to say?

Chris: Yeah. No, it's getting more fun every day in the Discord. Ah... ShopTalkShow.com.