464: Jamstack & New Netlify Features with Jason Lengstorf & Phil Hawksworth

Jason Lengstorf and Phil Hawksworth chat about the current state of the Jamstack including React + Jamstack, Distributed Persistent Rendering, building for ease of use, dealing with minor changes and caching, whether Jamstack needs to do all things, and a big new Netlify features announced!

Tags

, , ,

Guests

Jason Lengstorf

Web // Twitter

Jason Lengstorf works at Netlify and hosts Learn With Jason. He spends a lot of time telling people that the formula for success and happiness is to lift each other up and share what we learn.

Phil Hawksworth

Web // Twitter

Developer Experience team at Netlify. Co-author of Modern Web Development on the Jamstack (O'Reilly, 2019).

Time Jump Links

  • 00:59 Guest introduction
  • 01:56 React and Jamstack
  • 04:28 Distributed Persistant Rendering
  • 12:39 Sponsor: Dexecure
  • 13:25 Building for ease of use
  • 16:54 Does it only work with HTML?
  • 17:46 Does a minor change wipe the entire cache?
  • 23:21 Are we going to get build times down?
  • 26:23 User generated content
  • 28:14 Sponsor: Treehouse
  • 29:11 Does Jamstack need to do all the things?
  • 36:52 Sponsor: TopLevelDesign
  • 37:53 Enterprise and Jamstack
  • 46:18 Deploy previews
  • 49:50 New Netlify feature!

Episode Sponsors 🧡

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 my forbidden Wix headphones--Rupert. [Laughter] I feel like I'm in a fishbowl because there's noise cancelation or something going on. With me is Chris Coyier. Hey, Chris.

Chris Coyier: Hey, Dave. What's going on?

Dave: My forbidden headphones, what do I do to turn off noise cancellation?

Chris: I don't know. I don't know. It's probably right next to the button that stops it transmitting all information to Wix headquarters.

Dave: I turned it to five, so that's as good as I can do. Anyway -- I'm getting the sweats. I feel like I'm underwater. Let's go. Chris, who is in the studio today?

Chris: Well, this is a good one. I'm going to disclaimer right upfront. Netlify has been a sponsor of us for a long time, and we really appreciate that. Maybe never in the history of time have we let a sponsor tell us who comes on the show, so this is not about that. It's just that we happen to like these two fellows who happen to work at Netlify, and we think Netlify is an important industry thing and it's worth talking about because it gives us an opportunity to talk about JAMstack architecture and all new things, so we have two fellows here from Netlify on: Mr. Jason Lengstorf. How are you doing, Jason?

Jason Lengstorf: Doing well. Happy to be here.

Chris: Yeah, and Phil Hawksworth. Hey, Phil.

Phil Hawksworth: Hey. Hello, hello.

Chris: Hey. Really appreciate you being here. Yeah, this is cool. JAMstack is kind of endlessly interesting to talk about. It ends up coming in conversations just anyway, but it also evolves over time, right? New things are possible and feature releases come along. People think about it in different ways over time. Some of that stuff is happening now.

As a matter of fact, I just watched Matt's -- by Matt, I mean Matt Biilmann's -- React Conf talk. I don't know how long ago that was now. A couple of months ago maybe, at least.

Phil: Yeah. Something like that. Yeah.

Chris: He just did a ten-minute blaster, and he started with React because it's React Conf, so that was tasteful of him. Good job, Matt. [Laughter] He talked about how it was simple at first.

Dave: He just ... React is bad.

[Laughter]

Chris: Yeah, did you watch it? Yeah.

Phil: Launched ten minutes on PHP instead.

Chris: Kind of, but I don't know. It was measured, I thought. But he did say that it solved all these immediate problems. I felt that. It was like now we don't have to have JavaScript over here in room nine that has a query selector on it for some template over here in room three, and those two things are not particularly -- you know I used to have bugs like that all the time and React is like, "What if we just put it on click handler right on this fricken' div?" Don't put them on divs. That's bad advice, but you know what I mean. You couple the idea of -- it just solved a bunch of problems that we had at the time in development, and people still have, and it kind of changed the paradigm of how you think about building front-ends with components and how you architect things and whatnot.

Then it's around a long time. Tons of people use it. I think the React team is like, "What if we don't just solve those problems, but solve like 50 other problems too, because we're React, we're smart, and we're going to do that."

I think it keeps people excited about it and maybe keeps them around. I don't know the details of it. I think there are probably some social dynamics at play of how React thinks about things, but it's a lot different today than React was on day one. It's trying to solve more problems for you.

I'm just regurgitating what Matt said because, in that talk, he said React got old. It got more complicated. Look at that. That's a bummer, isn't it?

Phil: [Laughter]

Chris: That's React. But then made that same point of the finger then at himself and said JAMstack is like that, too. It started so simple. Let's just throw some static files on a thing. Then if you need it to do more, just ask JavaScript to do it. Ta-da, JAMstack. You know?

But along comes, "But what if we could do lots more stuff for you? Just tons of more stuff. Let's solve every use case under the sun and provide tools for that." That same kind of thing can happen.

Now, JAMstack is not simple no more. [Laughter] It's got all this stuff. But is that true? Is that fair? I don't know. Let's get into that.

Maybe we'll start with the big announcement because, at the end of that very video, it was like, "Okay, Netlify is going to do this thing that is going to help sites with their build times. It's going to be more predictable, the sites and stuff." The term that was coined is -- let me make sure I get it right. Jason, what's the term: DPR?

00:04:56

Jason: DPR (distributed persistent rendering).

Chris: Okay. Should we just do it? Are you guys excited about this? Is this big news at Netlify headquarters?

Jason: Yeah, I absolutely think it is. I guess maybe to set a little context on what it is, we have been looking at what's good about the JAMstack and what's really challenging as you start to use it for more and more complex projects. What's good about the JAMstack is this predictable mental model. You've got templates and data, and you have a build step. Then you get a static asset at the end that you can put in a folder. You put that folder on a CDN, and things just work. You know that no matter how many times you hit it, how busy the site gets, you're always going to get that same result.

Chris: It's funny when it's one of those true things but also weird. It's not like I'm like, "You know what I like about JAMstack? The predictable mental model."

[Laughter]

Chris: But it turns out you're kind of right. Maybe that is subconsciously what I like about it.

Dave: It's like the code that runs on my machine that "works on my machine" is 1% different than the code that goes out into the cloud or the CDN.

Chris: Yeah.

Jason: Yeah, and you're eliminating all of these mental hurdles that you have to jump through to keep how the thing works in mind, right? I made this crack, oversimplified things, and said, "If you need a whiteboard to describe your Web architecture, it's too complicated."

I said that in jest. Anything will get complicated as it grows, but I do think that there's a nugget of truth in there. When you start deploying a front-end but that front-end needs a node server because you've got a protected token, but then because you've got a node server, you have to get a docker container. To make sure that docker container doesn't fall over when you hit the front page of Reddit, you have to get a Kubernetes cluster.

All these things start to happen where suddenly you are not a front-end developer anymore. Chris, you've got a whole article about this about how deep the front-end has gotten in terms of required skillsets to be a front-end developer.

Chris: Yeah. I didn't even use the word Kubernetes in it, but you would.

Jason: [Laughter]

Chris: Is it Kuberneedys? Anyway--

Jason: Kubernudies, yeah.

[Laughter]

00:07:10

Jason: To get back to the original question about DPR, when we were looking at one of the challenges, as you try to use this JAMstack model, if you're trying to build thousands or tens of thousands or hundreds of thousands of pages, your build times scale proportionately. You have this kind of temporal restriction on how much work you can do in a build step in a compressed amount of time.

Chris: Even if you've never measured it, you might just assume that. You might be like, "I am not even going to think about JAMstack because I have 120,000 pages. Get out of here. I'm not even going to measure it. I know it's going to suck."

Do you find that? Do you find when you talk to customers they're like, "Pfft, this is just not for me"? I mean I guess they're not your customers yet, so how do you know? [Laughter]

Jason: Yeah. I think one of the biggest things that we see people pushing back on with the JAMstack is this idea that it's only for small sites, it's only for static sites. That's not true.

The Peloton app runs on JAMstack. The Netlify app (app.netlify.com) is a JAMstack app. You can run really complex, very personalized experiences through this JAMstack architecture.

But as you start thinking about big experiences, like, how could you run Wikipedia on the JAMstack? The answer, before this DPR, is you probably couldn't. It would take your hours to build it and it changes so frequently that there's no way that it would reasonably be doable.

Chris: Yeah. You'd just make SPA and just assume that you're going to ask for content after render. You wouldn't even bother.

Jason: Right.

Chris: You wouldn't even consider prerendering, right?

Jason: Yeah, and so what DPR does it is allows you to take some of that prerendering and make it async. You still have a build step. You're still taking your template and your data. You're rendering it to an asset. Then you're moving that to the CDN.

What we've done with this model of DPR is we're proposing that you can take the most important content, and you render it in your build step like always. But then you leave other content to be rendered on-demand in a serverless function. It's still a build step. 11ty has implemented this now where you're calling the 11ty build function. You're just calling it for one page instead of a folder full of pages.

Chris: Yeah, so you have a Lambda sitting in the sky that runs 11ty.

Jason: Exactly.

Chris: Which happens to be a nice fit because Lambdas support Node really well and 11ty is written in Node. The stars just kind of aligned on that one. But Lambdas get more and more capable, right? you can run GO on a Lambda.

Jason: You can run--

Chris: Theoretically ... GO.

Jason: You can run GO. You can run Ruby. You can run--

Chris: Yeah.

Jason: Now, you can't run all of those on Netlify, but Lambdas, in general, support a pretty broad set of languages.

Chris: Yeah.

Jason: And so, we expect that's going to expand.

Chris: You have this URL that comes in. Some kind of knowledge, whether this page has been rendered or not.

Jason: Mm-hmm.

Chris: I don't know. Is it KV store or something? I don't know how it would know. It checks a cache.

00:10:06

Jason: What we're doing right now is, yeah, we put it in the Edge node. But as it matures, the goal is that once it renders once, we're going to move it right back to the origin. As far as the Netlify CDN is concerned, that page that got rendered by -- we're calling them on-demand builders that use distributed persistent rendering.

Chris: Yeah.

Jason: That result after it renders the first time is just going to move back to the origin and be part of the original build. So, you still get these benefits of the JAMstack--

Chris: Right.

Jason: --where it's like it's atomic, it's immutable. You hit the same result or you hit the same URL, you get the same result every time, predictably.

Chris: Right.

Jason: If you need to roll it back, you can, and you'll get those results. You've got all those same guarantees and that simplified mental model: there's a build step, there's an output, and it goes to a CDN. That's that.

Chris: You pay this little cost. One person pays this cost. The very first person that hits that page, 11ty is going to spin up and be like, "I'm going to produce one page and put it on the network," or whatever.

Jason: Yes.

Chris: That's it, and probably that's pretty fast because Lambdas are pretty fast, and running a build for one page is pretty fast and all that. So, it's just kind of trustable in that way. We've been paying the first user cost for a long time, you know.

Jason: Yeah. You can even take it a step further. After your deploy runs, you still know what your static pages are, so you can just make a big list of those and call all of those functions in parallel and build all the rest of your pages asynchronously right after the deployment.

Chris: Oh, that's brilliant.

Jason: You can make it so that somebody never pays that cost.

Chris: It's just so that your build is faster then?

Jason: Yeah, exactly.

Chris: Oh, that's tricky. I was going to ask about that because that seems like, if you were going to do that, then why don't you just put them in your build? But the point is that your builds go out faster then.

Jason: Yeah, so we're trying to -- and it's not always that. Sometimes, you're going to have -- if you don't want to burn the electricity to build a bunch of pages that only get visited once or twice a month, just wait until somebody requests them.

But if you have content that's somewhat popular but it's not your most popular content and you don't want to have to wait 25 minutes for a build because you've got 15,000 pages or something, you can just build the top 200 pages that get 80% of your traffic and let the rest of them build asynchronously. Unless somebody hits immediately after a deploy, they'll see that instant response but your build goes out in 30 seconds now instead of 15 minutes.

00:12:38

[Banjo music starts]

Chris Enns: This episode is brought to you by Dexecure, a company that saves developers time by automating mundane tasks that you all hate to do but have to do. Images, JavaScript, CSS, HTML, fonts, and third-party assets: Dexecure does the optimization with just one line of code, and you can focus on what you love doing; building new and exciting websites.

It's super easy to implement. Just one line of code needed for integration, or they've got a plugin if you're using WordPress. No matter the device or browser type, Dexecure will always have the best version of your website.

You can visit dexecure.com/shoptalkpodcast for one month free when you sign up for any basic or pro plan (or try it out for free with their free account). Our thanks to Dexecure for sponsoring this episode of ShopTalk Show.

[Banjo music stops]

00:13:40

Chris: Are you trying to build this as least proprietarily as possible? Doesn't it seem like you have to be like, okay, well, your SSG then needs to be able to be configured that says, "Build these pages but don't build these other ones," and it needs to be able to take some other config that's like, "Please run in a Lambda and have some kind of API that says, 'Build this one page.'"

How much manipulation to the SSG is required?

Jason: Not a lot because most SSGs, when you look at their config, you're getting a config file that's taking in a page path and it's feeding it in a template and some data. If you feed it one page worth of data instead of all of your pages worth of data, the API doesn't need to change very much.

Chris: Yeah. Right.

Jason: And so, there is a possibility--

Chris: But you're like, "Don't make a whole dist. folder with all my assets in it and crap. Just give me the built HTML file." [Laughter]

Jason: Yeah. Right. There's a little bit of changing. But even without it, you can run it, and then you can reach into the dist. folder and grab those assets and throw them out. There are ways to kind of solve that, but it's very much depending on the SSG. For 11ty, it was pretty straightforward because 11ty intentionally doesn't do a lot to keep the mental model straightforward for people. For something that's very React heavy, there's a little more with shared bundles and stuff that we'd have to figure out to make sure that that works. But we're working with library authors like that.

We are sponsoring Nuxt to help them with the next version of Nuxt to try to make this something that's native to the platform and something that just works. We're experimenting with other platforms as well. We've got it running for Next.js.

Chris: That'll be cool to see because it's like you've got Zach in-house, so that's not a huge surprise that you got 11ty out the door.

Jason: Yeah.

Chris: Not to mention it's kind of philosophically kind of connected with ideas like this.

Jason: For sure.

Phil: The nice thing is, as well, that although, yeah, you can start adding it to the least different SSGs, the intention is that we provide these primitives so that you can add it with anything. The first experiments I was doing, I'm using 11ty for pretty much everything because otherwise, Zach hunts me down.

I was using that in the build, but then adding routes that would be doing things that were using on-demand builders, I wasn't using 11ty for that. It was like an additive approach. I just have a bunch of routes that say, "Okay, we'll mash up a template with some data." I could already do that in a serverless function, but now I add this wrapper to it that says, "And also persist it in the build forever."

It actually wasn't -- I have no notion of what the static site generator was that I was using in the first place. I just added another thing to it. So, you could effectively add it to anything if you like. The nice thing, really, would be for static site generators to add this as a little utility so you have one completely unified workflow and all the rest of it.

Chris: Sure. Mm-hmm.

Phil: Strictly speaking, you could add a little dusting of this to anything and still be able to get that same result. That's been kind of fun to explore, if I'm honest. It's quite nice.

Dave: Does it only work with HTML? I'm thinking of the ever-popular Twitter preview card images and stuff like that. Could I generate those on demand?

Phil: Mm-hmm. Sure. Any asset you like, so I think, actually, Zach's first experiments with this were using it to generate images. I think, on the 11ty site, he's got a ton of thumbnail images of previews of different sites in like a gallery. He was generating those once rather than having those in a build step. Of course, that's quite an expensive thing to have during a build.

It's quite computationally heavy, so he just defers that until the first time they're requested and then they persist forever. He was doing that with assets but, yeah, you could generate anything you wanted, really, any resource that you then want to serve at some point.

00:17:45

Chris: Is there a--? This may be unavoidable. I don't know. Maybe you have an awesome solution for it. Truly don't know here. You have that moment where you're like, "Oh, I forgot to put a period at the end of a sentence in one blog post."

Dave: Hey, dude. I'm right here. You don't need to....

Chris: [Laughter]

Dave: --on my own podcast.

[Laughter]

Chris: Ouch! Ouch! But does that wipe the whole cache? Just totally everything, wipes it all.

Jason: Right now, yes. We're trying to figure out how to make that work in a way that doesn't reintroduce a lot of the issues of multilayered cache management. A big caveat that we should put on this is, this is nothing new. If you've ever used WordPress with a varnish cache, that's effectively what DPR is.

What we're trying to do is learn from models that worked really well and bring them forward in a way that doesn't require anything to configure, doesn't require complex cache and validation strategies, doesn't require you to think about your cache as, like, multiple layers of asset versus API versus rendered paid results. One of the ideas that we're kicking around is this idea of being able to invalidate just the result of your distributed persistent rendering and copy the cache forward so you get a new, atomic deploy without having to rebuild the whole site if none of your code assets changed. There's discussion of, like, how could we support that for maybe a subset of routes or something like that.

Chris: Mm-hmm.

Jason: The more fine-grain those controls become, the more complicated it is to manage and the more likely it is to become kind of a foot gun. The reason that we're really hesitant about that is, when I worked at IBM, we had this brilliant strategy around caching for Akamai and we were caching our assets, our images one way, and we had our API request cached another way with Redis in between. We had our static assets and then the things that were rendered by Node. Each of those had a caching layer.

Somebody very smart had figured out how to manage all of those caches and none of the rest of us could figure it out, so we all just appended a randomly generated number to the end of every URL to guaranty not cache.

Chris: Hmm.

Jason: As you can imagine, this was unbelievably expensive for IBM. [Laughter] What we're trying to avoid is this thing where the cache gets complicated enough that people can build strategies that people can understand because that's a core tenant of the JAMstack is that you can understand what's happening without having to diagram it or do a deep dive.

Chris: Yeah. Yeah. God, I can relate to that. I'll tell you what. Even on ShopTalk Show, which is not JAMstack at the moment, I have to -- if I change CSS, there's just nothing. There's a bunch of caching involved because, of course, there is. Like Cloudflare sits in front of it. It's on some WordPress host that does its own caching and whatever.

I could write some code that's just like, "Oh, the CSS file changed, so please change the HTML template to update a query string of the CSS so it breaks that cache." I just never did because it's just not that -- it's not such a daily activity for me that I'm like, "I'll just manually change the query string." Who cares? You know? [Laughter]

But it's nice to know that, in Netlify, you never have to worry about that. You're making your little baby site. You just don't even care. You don't even write that line of code.

Jason: Mm-hmm.

Chris: Which I've always appreciated. That's such a nice little touch.

Phil: Yeah. There are so many ways to solve some of these problems. Yeah, you can solve all of these things with crafty cache management and knowing what you're going to -- you know, updating different things at different times. The number of projects I've worked on over my career where it should have been fine but something wasn't quite right somewhere in the logic of what was in the cache and what wasn't, it's really difficult to get that stuff completely right across a complex project.

I'm happy to abdicate responsibility for that and say, "You know what? We've just got to simplified mental model where, when you do deploy, we update the cache."

Jason: Mm-hmm.

Phil: We don't have to think about any kind of granular control over that.

Chris: Right.

Phil: Just do it. And I think the intent was always to make deploying so mundane and so trivial that you're happy to do it time and time again and it's effectively free to do so. But then that starts just getting eroded when sites get very, very large, like we're talking about. It becomes not trivial because of time.

Although, interestingly, Chris, at the beginning you were talking about what do clients expect from that. The first conversations I ever had with clients about building things statically rather than using something dynamic, those were big enterprise clients, and so their deploy times are usually three weeks. [Laughter]

Chris: Hmm.

Phil: It's like, we'll have a two-week code freeze and then a one-week deploy process, so the idea of a build running for an hour, that would have seemed like a luxury then. Thankfully, I think our parameters have changed a little bit. I think what we expect as developers is starting to change a little bit. But some people are still in that scenario, so the faster we can get to the point that deploys just feel so trivial that you don't even need to think about it is just another push, the better, in my opinion.

Jason: Mm-hmm.

00:23:00

Chris: I wonder what are the numbers. What are you guys feeling? Do you have two minutes? That would be pretty sweet, wouldn't it? I would think your basic DaveRupert.com is looking at a two-minute blaster, right?

Phil: That was a mammoth site that was....

Chris: [Laughter]

Jason: Well, I mean--

Dave: You say enterprise. I mean that's what we're dealing with there.

Chris: There are some limits. Let's say Dave wrote a bunch of Cyprus tests. Those things just kind of got to run in real-time.

Jason: Mm-hmm.

Chris: You're just going to -- that kind of stuff, the more testing you have, there are limits that Netlify can't do anything about that.

Jason: Right.

Chris: Those tests just run. But you can -- how fast the build goes and how much it builds and all that, the things that you can control are coming down. I'd love to see zero minutes.

Jason: Yeah.

Chris: I think we'll get close to that, in time. Don't you think? Press a button and it's done.

Jason: There are a lot of tools that are coming out that are going to make this easier, like esbuild and Vite and a lot of the Rust tooling like SWC that's coming out is unbelievably fast at building sites. I did a show with Saniel Pi where we refactored Create React App to use Vite. The compile-time for a fresh install of Create React App was nine or ten seconds, or something, using the default setup. When we switched it over to Vite, it was under a second. It was so fast that we thought it was broken.

Chris: That's esbuild under the hood, right?

Jason: Yeah, Vite is an extra layer of stuff on top of esbuild. What my hope is, is that DPR is the tool you reach for after you've got very complex use cases because I want to see the building tooling all kind of keep growing the way that it is. I'm really excited to see all this new competition for Webpack with esbuild and SWC and the Rust ecosystem exploding and how fast all that stuff is because it really is unlocking a leap forward.

Chris: We'll see new SSGs on it, too.

Jason: Yes.

Phil: Mm-hmm.

Chris: Node has limits to how fast it can rock, too.

Jason: Mm-hmm.

Chris: Any benchmarks you see, Hugo tends to win and it tends to be the only one in GO.

Jason: Yeah.

Chris: I think that might get more and more exciting for other SSGs to be like, "Fine! I'll switch to GO." Rust is speedy too, right?

Jason: Yeah. I'm using an SSG called Toast.

Chris: Yeah.

Jason: It's built by Chris Biscardi. It runs on Rust, and that one bundles in -- the learnwithjason.dev has about 200 episodes on it now, so I'm building all of those pages with some asset management and stuff. That site bundles in, like, seven seconds now.

Dave: Wow.

Jason: Because of just how fast Rust is. Again, it's just like the tooling is making massive leaps forward, and using ES Modules instead of CommonJS enables some really massive leaps forward. There's some big stuff, I think, coming that's going to make builds faster, in general. DPR is a way for us to handle user-generated content or really truly massive sites, but my hope is that where you start to need it for a build, I want that number to be really, really high. I think that the current direction of tooling is going to get us there.

Chris: Hmm.

Phil: You mentioned user-generated content as well there. That was the other use case that is kind of a perfect fit for DPR. I went through some shenanigans to try and figure out how can we make JAMstack really work well for user-generated content because it doesn't feel like a natural fit, right?

Chris: Like Twitter or forums.

00:26:42

Phil: Exactly. Yeah. Yeah, right, so I made this little toy a while ago that I wrote up on CSS-Tricks. It was this, I called, Vlolly so that you could make a lollypop and send it to someone.

The biggest pushback I got was the word lollypop. Popsicle, I should have branded it, but live and learn.

Jason: They're different things, Phil.

Phil: I know. I'm sorry. I felt like an idiot.

[Laughter]

Phil: The point was that you'd have a--

Dave: That's just localization 1-0-1.

Phil: Well--

Jason: [Laughter]

Jason: I mean I'll pretend it was a mistake but, really, it was just an opportunity for me to demonstrate localization as well. But at that point, my build doubled because I had all of the content that people had submitted for all of these different lollypop pages, which then I also generated with the branding of popsicle instead of lolly on it, so I could keep my American friends happy.

The point was that there was a form on the page that you'd submit the data. It would go to a database. That would trigger a rebuild. It would generate all of the pages, including the one that you just had. Then while that build was happening, if someone went to the URL of the new page, that would be delivered by a serverless function.

With DPR, I can do exactly the same thing but I'll never need to trigger a new build because the serverless function that would return that view also persists that view into the build. Just with one step, that just handles all of the user-generated content. So, it can really simplify that model as well, and it would save me quite a lot of hassle before, but that's fine. I'll embrace it now.

Chris: Nice.

00:28:11

[Banjo music starts]

Chris Enns: This episode is brought to you by Treehouse. Treehouse is the best place for people of all backgrounds and skill levels to learn to code or learn a new programming language. Their on-demand, expert-led content library includes thousands of hours of video courses, workshops, practice sessions, and so much more.

The Treehouse Tech Degree is a boot camp to your program for a fraction of the cost of traditional boot camps with no "pay us back later" income share agreements. They've got gamified learning with quizzes, code challenges, and workspaces. Plus, they offer guided learning tracks on a number of topics like Python, JavaScript, computer science, UX design, and more, that allow you to create a custom curated curriculum.

Nearly one million students have transformed their life with Treehouse. Every Treehouse subscription comes with a seven-day free trial. Start yours together. Our thanks to Treehouse for sponsoring this episode of ShopTalk Show.

Banjo music stops]

00:29:13

Dave: That's cool. I feel like, just yesterday over in the ShopTalk Show [tech voice] Discord, somebody was kind of asking. They were trying to do a hook, right? They hit update post on their WordPress. They want to do a hook to redeploy the Netlify build or trigger another build. This would kind of solve that. I don't know. Maybe not--

How would you negotiate, like, "Oh, my WordPress changed, so now my post on Netlify, my static post needs to update"?

Chris: Hooks, man. Hooks.

Dave: Is there a tool to kind of trigger that?

Phil: I think I'd still be doing the same thing. I think I'd still be firing a Webhook and firing the deploy. But I think the pages that you choose to include in the build, the actual build step, might be different.

Dave: Like, "Hey, field these"?

Phil: Yeah.

Dave: Yeah.

Phil: It might be just some of them, but not all of them, because the rest will get scooped up when they're first asked for. There's another thing to stop you, as well, kind of pulling in all of the content, all of the data, and that then lives as part of the build. You can still reference that at the point that the DPR, the function....

Dave: It could just go a lot faster then.

Phil: Yeah, exactly.

Dave: Yeah.

Chris: Let's do a hard one, though. Part of the reason it makes me bullish on this is because people are making fun of it a little bit. I'm sure you've seen the tweets that are like, "So, you invented servers. Good job." That type of thing, you know?

[Laughter]

Jason: Yes.

Chris: If it keeps going, if it keeps getting more complicated, you're like, "Okay, we're going to push the cache forward." What's the term where you only rebuild the pages you need?

Dave: Incremental build?

Chris: Yeah. There you go. You start inventing more and more complicated things that people need. Is there some trendline that gets you all the way to WordPress? [Laughter] You're just like, "You know what? Actually, that got so complicated that we're just going to run servers again. Sorry about the JAMstack thing."

Jason: Well, and that really is one of the things that we're trying to be mindful of because I think that we're seeing some parts of the community are already saying that. They're saying, "We tried this JAMstack thing and it didn't do enough, and so we're going back to servers."

We're seeing the trend move that way. There are frameworks coming out that are full stack. You've got to deploy a server to get it. But we're also seeing a lot of the things that we were trying to get away from and the JAMstack coming back in like now you have to think about cache-control headers.

You're thinking about how do I get this node server deployed. Or if you're not thinking about how you get that node server deployed, you're paying a platform to think about how to get that node server deployed. There is a certain amount of what we're trying to do and the reason we're being so thoughtful about not adding things, we're intentionally dragging our feet on adding finer grain cache control. We don't want to do that unless we don't have a choice because it does get us closer to all the complexity we were trying to get away from with servers.

The biggest thing, one of the things, a drum I've been banging is that complexity is a code smell. If you find yourself adding complexity into a project, you're at risk of doing something that's going to make it unmaintainable going forward. Is there a way to make what you're doing simpler? A lot of times there are.

If you are trying to build a site and there are just too many pages, can you break it up by sub-routes and just build the sub-routes that you need to build and use a reverse proxy to stick them in? That's a really simplified model. That reverse proxy is the piece of complexity that comes in, but it's easier for me to manage a redirects file than it is to manage a server.

Chris: Right. It seems like there's a little complexity here, but it's not a huge turning of the dial of complexity, which is kind of good. You might hit a point (at some point here) where it's like there is kind of a sweet spot for JAMstack approach - period. We've nailed it. We can iterate on making things simpler when we can, but we're going to stop making things more complicated because we've kind of hit some kind of wall of complexity where it stops making sense to make things more complicated.

I don't know if that's the case here or not. I'm just kind of guessing. But that's tricky because sometimes it's at odds with growth. You're a company that has nailed a particular approach and the goal is growth, the goal might be, like, "Well, we have to do complication because we have to do grow and we have to solve more use cases and stuff."

00:33:55

Jason: Yeah, and I mean the primary goal of this whole thing is we want to make developers feel like they can do the things they need to do. If a developer is looking at the JAMstack and the feedback we're repeatedly getting is, "We can't do X with the JAMstack," then the JAMstack needs to evolve or, if it can't evolve without becoming something completely different, then we need to rethink that approach.

Thus far, when we've hit those repeated pieces of feedback, we've felt that we've been able to keep the mental model of the JAMstack, this idea of decoupled front-end, precompiling assets, shipping to a CDN, using serverless for the little bit of middle-tier work that you need to do so that you don't have to ship a full server. That mental model has been able to stay intact. DPR is our intention to fit this idea of dynamically server-rendered content. We move it into a serverless function, and we add a way to keep it in the cache so that it still fits that mental model. We're compiling. We're keeping it decoupled. We're keeping it in the cache.

That is trying to evolve the category to enable people to do all the things that they want to do within the JAMstack architecture. But you're right that it is a push and pull because, if we just did everything, then you're right. Yeah. Congrats. You've invented PHP. [Laughter] You know get the full server.

Chris: Yeah. I just don't know. What's that point? There is a point where you just say, "No. Actually, we're not trying to make this an architecture that is absolutely every use case under the sun." You know? It might be too early to make that call.

Phil: It's worth remembering as well that parts of JAMstack or JAMstack sites live outside of this model of pre-generating the front-end and deploying to a CDN. There are also the APIs. It's completely valid for some things you build that power the Web to live in complex things that are dynamic.

We certainly do that at Netlify. Yes, we have a whole front-end which is the marketing site and the Netlify app, the kind of admin site, which is a React app that we serve from our own CDN. It's a JAMstack site. That's talking to APIs that have all kinds of complexity in the back-end because those are doing a different job of work.

There's an important job to be done there, and use whatever technologies you like for that, but it's that decoupling which is important so that the front-end team can build out a Web experience that is exactly what you like with exactly those workflows. It doesn't mean that there's never going to be a place for all of these other languages, all of these other infrastructures because that's what powers these APIs in the first place. I don't think we're arguing that that would always go away and you're just going to only ever be serving flat files from a CDN. It's just that decoupling, which is key.

00:36:51

[Banjo music starts]

Chris Enns: This episode is sponsored by Porkbun. Porkbun is offering ShopTalk Show listeners a free .design domain name to showcase your designs. As designers, you're automatically drawn to things that are creative and unique, and every designer's online portfolio is completely different from each other, so why should the URLs all end in the same .com?

Porkbun is offering an answer to that question with a .design domain name 100% free of charge for your first year. Your free .design domain name will also come with free WhoIs privacy, free SSL certificates, a free hosting trial, and a free email trial. You can also set up a website with free WordPress or static hosting. Companies like Slack and Adobe have already used this URL strategy.

You can get your free domain by clicking the link in the episode description or by using coupon code SHOPTALK21 at checkout when you visit porkbun.com to register your domain name. Our thanks to Porkbun for sponsoring this episode of ShopTalk Show.

[Banjo music stops]

00:37:53

Chris: I'm curious about the word "enterprise" and how it kind of factors into all this. Enterprise generally means scale or are you thinking about it in a different way? Is there enterprise pushback on JAMstack?

Dave: Yeah. We have a lot of clients, but a lot of them are like, "We want to go JAMstack, but--" You know?

[Laughter]

Dave: There's usually -- I don't know. Pick your reason there. What are you seeing? Are you seeing bigger adopters in this, going kind of a JAMstack route?

Then I would be curious about the struggles you're seeing, as people are trying to adapt these big, historically behemoth Java sites to a JAMstack life. What is that like? What are you seeing?

Jason: We are seeing adoption from bigger customers. A recent example is the Tulio console. They have a beta experience up. If you look under the hood, you can see that's served by Netlify. They've moved their whole dev app is now a JAMstack app. That's built on that concept that Phil was talking about. All the APIs, those are servers. They're off doing their thing. But the front-end has now been decoupled so that they can--

Chris: Really?

Jason: --have a very--

Chris: It generates one page? [Laughter]

Jason: Yeah, it kind of does, but it's doing a lot of the -- it gives them the ability (on the front-end) to iterate very, very quickly without having to worry about breaking back-end services because of that layer of insulation between the front-end and everything else that it's talking to you. You've got these clear API boundaries. You can check whether or not those broke.

Chris: Yeah.

Jason: There are no leaky abstractions between the front and back-end.

Dave: They don't need to do an entire security audit because they changed some syntax or whatever.

Jason: Exactly. Exactly. Their deploy times, they can now deploy to production multiple times a day instead of once every three weeks because the risk has been so vastly decreased for deploying the front-end.

Chris: It solves some people-problems right away.

Dave: Think of all the people you can fire. Geez.

[Laughter]

Dave: That's great.

00:40:07

Jason: Well, the thing that's great about is what we've been seeing with bigger companies that adopt this, the initial resistance is, "That's not the way we do things," or "That's going to introduce these problems," or a certain team doesn't like it.

But when they start to embrace it, what we're seeing is the dev-ops team, who you'd think -- you know your joke about who we wouldn't need anymore. Really, what it means is the dev-ops team isn't burning all their time on release management. Now they can work on things that actually move the business forward instead of just shepherding these releases along day after day and making sure that all these fragile pieces of the deploy don't break because the systems don't quite match up together. You can get to true CI/CD, and then your front-end becomes a thing that isn't a burden on dev-ops, so they can focus on more critical systems and keeping things much healthier.

We see the back-end teams as well. The back-end teams aren't getting pulled into that middle-tier work of, like, "Well, we need to make a call to this API, but we need an API key that we can't put in public, and so we need a node server for that, which means the front-end team can't do it." We get rid of that middle tier work can actually go to the front-end team. They have the ability to deploy it and manage it and they keep it secure, so the back-end team can actually work on their area of ownership instead of getting pulled into these things.

It gives teams more autonomy. It gives teams more firmer boundaries and a clearer sense of ownership over things. Ultimately, it leads to more productive organizations because the biggest slowdown in an organization is bureaucracy and a lot of bureaucracy comes from ambiguity. If all of your systems have blurry lines, that is a breeding area for ambiguity. You're going to have a hard time figuring out exactly who owns something when it falls across three areas of ownership. When those boundaries are firm, then you know, okay, you own this, I own this, they own that. We can all work, and we all know what we're supposed to be doing. We're not stepping on each other's toes.

That productivity boost is very real and you're seeing. If you look at Loblaw, which is the largest retailer in Canada, they switched to the JAMstack approach, and they shipped -- Phil, you might know the actual numbers. It was like ten times as many things.

Phil: Yeah, it was some big number. Yeah.

Jason: Yeah. Over the previous year, they'd shipped like three or four things. Then they switched to the JAMstack and, over the next couple of quarters, they'd shipped over a dozen. It's because of this kind of clarity that comes from making things smaller. You're eliminating that complexity that causes it to be hard to reason about the whole system and giving yourself a firm boundary to work within. Now it feels like you're coloring by numbers instead of having to kind of invent the universe every time you want to do a release.

00:42:57

Phil: Going back to part of your question before about what's the biggest pushback, the pushback I've seen has been quite different since joining Netlify (from before). I used to work at an agency so, at that point, I was dealing with clients where I was trying to persuade them that this is an approach that would be viable for them. They were big old brands.

Usually, the biggest pushback I'd get there is there are some costs. They'd invested a gajillion dollars in some massive enterprise platform that they're going to use on everything. They've invested a lot of effort, and so it had to work.

That was usually the biggest pushback saying, "No, we can't. We can't not use the thing that we spent all this money on," even when quite often it wasn't doing what they needed. They'd say, "Well, we'll put more money into it until it does what we need." That was often the biggest pushback.

The experience I see now is a bit different because now, since I'm working at Netlify, by the time I talk to a customer in those terms, usually they've made the decision that they want to explore it, so they're already over that hump. Then the biggest challenge I've seen most often is, how do we service a site that's got a million pages? That brings us to the challenges we've been talking about earlier on and the kind of solutions that we're looking at.

Yeah, it's amazing to me how the tides have turned at large brand and enterprises over the last few years. I know that, for example, at Nike, I used to do a lot of work with Nike and it was really difficult to get them to build in a certain way. I know that they've gone through a big project of doing more with headless now, so I know that they've got a headless architecture that they now can put other things on top of.

I think the tide is turning gradually for more and more enterprises, for just thinking about slightly different architectural models, and that opens up the door for more things. Yeah, my perspective was very different before and after being in those two positions.

Jason: Mm-hmm. Yeah. What we're really kind of learning and what we're seeing is the conversation we're having isn't about where do you put your JavaScript. It's more starting to think about the architecture that you choose at a company has a very direct impact on your team culture and productivity. I've worked on teams where it felt like anything that I did had to go through eight layers of approval and it would maybe go live in three weeks. We deployed once a week on Thursday. Those types of processes are just so draining and it caused me to recoil a little bit from deployment, so I would save all of my changes into one big PR so that I only had to go through it once in a while.

Working at a company like Netlify where it's the opposite. When you merge that PR, it goes to production within a few minutes. I found myself feeling exactly the opposite. I'm incentivized to do the smallest possible PR because it's easy to get reviewed. It's easy to get merged. Then I see this incremental progress. The whole team culture is built around that.

We're watching that as different teams adopt these different architectures, their cultures are following suit, so it is very much an architectural decision, but it's also a culture and productivity decision. JAMstack is not the only way that you can get that outcome, but what we are seeing is that it does consistently contribute to that kind of outcome.

Dave: I think that's the piece that no one understands is how cool deploy previews are [laughter] because it's like, "I'm going to put this code up and in, like, one minute, you'll be able to see it and click around it and make sure nothing is broke."

Chris: Mm-hmm. Mm-hmm.

Dave: Everyone has that assurance. Nothing is on fire. Again, it's like 1% different than what I wrote, so that's really hard to stress to people is, like, "No, no. This is going to be so good," because you can just see it. I'm in a project right now, a Nuxt project, and I don't have deploy previews and it's like, "Ah, man! Can you spin up an AWS to show the storybook or whatever?"

Chris: Yeah.

Jason: Yeah.

00:47:06

Chris: You know what I think about? There is stuff to talk about with deploy that we can get into, but how it's anti-CD. Everybody says CI/CD. It just comes out of your mouth. CI/CD. CI/CD.

CD means that the tests run and then it just deploys. Nobody works like that. I don't know. It's funny.

This was a post by this Anton Weiss guy at the end of last year that's like, "Let's stop fooling ourselves, what we call CI/CD is only CI," which I thought was a funny post. Then it turned out to be a sales pitch or whatever, but anyway [laughter].

Dave: Buy my product.

Chris: Yeah.

[Laughter]

Chris: I feel like they're kind of right in the fact that you have a really nice pull request with a deploy preview in it that says, "Slow down. Look at the fricken' thing. Click around. See what it's like. Then press the button to push it when you're ready."

Jason: Mm-hmm.

Chris: "When the customer has approved it." CD is kind of neat, but do people really do CD? Should we keep saying that word so much? Anyway. [Laughter]

Jason: But I mean that is kind of what the JAMstack is, right? It really is CD. When you click that PR button, when you merge that PR, the tests run and it goes live. I do think there is huge value in that, and inputting that into your culture because you're giving your teams autonomy. You're giving them that trust to say, "Look. You don't have to go through eight gatekeepers to get this thing live. We trust that if you review this PR, our tests are good enough and our systems are resilient enough that you can just let this thing rip."

Chris: Yeah. That's another way to think about it, and that's totally fair. I just mean that that type of CD where you don't even review the PR because your tests pass--

Jason: Oh, geez. Yeah. [Laughter]

Dave: Yeah. Yeah.

Jason: No, I don't think anybody does that.

Dave: Maybe for back-end work. Maybe for back-end work.

Chris: Yeah, it's like a trust that your tests are so good that you're not sitting around reviewing PRs so much. Maybe for code review but, for the most part, stuff just goes, goes, goes, goes, goes live. You know?

Dave: But it's way better than, "Hey, Gary. Can you please FTP this up?"

[Laughter]

Chris: Yeah.

Dave: You know, like, it's way better than that system.

Chris: That part is kind of CD, so fair enough. It's not like a fully formed thought I had or anything. But anyway, this is airing shortly after a Netlify announcement, around a deploy preview, so let's take a moment to do that, if we could.

Jason: Yeah.

Chris: They're better now? Do I have that right?

[Laughter]

Phil: That was it. Yeah, that was the announcement. You missed it. They're better now. Enjoy.

[Laughter]

Dave: One sentence press release.

Phil: Maybe we over-rigged it with a whole announcement and a whole event for that.

Chris: Yeah.

[Laughter]

Dave: Yeah, the live event announcement was maybe....

Chris: [Laughter] Tell us. Tell us.

Phil: Go on, Jason.

00:49:52

Jason: Okay. All right. I'll do it. We just released something that we're super excited about. We acquired a company called FeaturePeek and built-in commenting into deploy previews. You're now able, in addition to seeing the code in the PR in a linkable URL, we also added this little gem in the corner that you can open up. It creates a drawer where you can leave comments, upload screenshots, do light annotation, screen recordings, things like that. Any of those comments that you create will sync back to the GitHub pull request. We've got integrations with other services as well.

The idea is that we want to bring in that really collaborative experience without the onus being on everybody to deal with GitHub. Not everybody is GitHub native. What I've noticed is that when I've worked at companies that aren't GitHub native, the developers give feedback in GitHub, the marketing team gives feedback in a Word doc with screenshots, and the product team gives feedback in Jira or Asana or whatever their product management tool is. As a developer, you have to remember to check all those places, then to go Slack to get all the other feedback that came in, and then assemble that into a place where you can actually triage and manage it.

What we're trying to do with deploy previews and this commenting feature is make it so that everybody can comment in a way that feels native to them and it gets triaged to the right place. It shows up in the pull request so that the developers see all of that feedback. We're really excited about this.

Chris: The canonical home base for the feedback is still GitHub. you just don't have to use GitHub.

Jason: Exactly.

Chris: You can use GitHub or you can use, what, a little widget thing in the corner of a pull request?

Jason: Yeah. It's like a little drawer, kind of a sidebar that'll pull out. In that, you can do -- like I said, it integrates with other services as well. But the nice thing about it is that, currently, when you have a deploy preview, we're going to show you the homepage. But this new system will let you link to the page that changed. When you're sharing the link, it's going to take you right to the page that actually needs feedback.

Chris: Oh, nice.

Jason: Then the comments will be there so you can see what people have talked about. You can resolve things as they get addressed. You kind of give yourself a little checklist and a home base to discuss (in context), like, "This is the thing we're working on. Let's discuss it here," instead of moving out to all these other services. But we don't want to lose -- you also need to track stuff that you're talking about where you work, so you want to discuss it on the deploy preview but track it in GitHub.

Chris: Right. Right. Right.

Jason: I'm blanking on the other one that we've integrated with already.

Chris: GitLab.

Jason: I think it's Clubhouse or Productboard.

Phil: Yes.

Jason: One of those. Clubhouse?

Phil: Yeah, Clubhouse, I think.

Jason: Yeah.

Phil: Yeah.

Jason: The product management tool Clubhouse, so we've got the ability to sync these comments between multiple systems with more coming. We're working on additional integrations as well so that everybody gets to work where they want to work and the comments kind of sync there, but you have this centralized location so everybody can talk in the same place.

Dave: I don't know, man. My system of 10,000 post-it notes from--

[Laughter]

Dave: --all across the Internet is working pretty good. I don't know if this one has legs.

[Laughter]

Dave: I'll be curious if it's possible.

Phil: I knew we wouldn't get the Rupert seal of approval. I knew it.

Dave: Yeah. Just don't try to fix what's not broken. You know what I'm saying?

Chris: I say, why use post-it notes when you can just keep it up here. You know?

Jason: Yeah.

[Laughter]

Dave: Yeah, the ol' big brain strategy.

[Laughter]

00:53:33

Chris: Of all the stacks I work on, the only stack that I have deploy previews on is JAMstack stuff. It's possible-ish on other platforms, but you just don't see it as much and it's behind the times and it bugs me. I'd like to see that evolve to other things, eventually. But I think it's just harder to pull off. It's more expensive. You know?

Jason: Hmm.

Chris: For my WordPress site, what are you going to do, spin up a whole staging server for this one PR and then let me see this one sentence change I made or whatever? That just seems like a lot to ask. It's a little different than, like, point some crap at a different S3 bucket, or whatever.

Jason: Mm-hmm.

Chris: Not that there's not severe technological challenges in how deploy previews work, but I feel like it's probably slightly easier than having to duplicate a database, for example.

Phil: Yeah. There are a few moving parts, right? That comes back to the thing right to the beginning.

Chris: Yeah.

Phil: The kind of messaging, Matt's talk that you referenced right at the beginning, Chris, it's like, if there are fewer moving parts, it's easier to reason about, so you don't have to walk straight as much. That's kind of the model we're trying to keep around and trying to grow.

Chris: Yeah.

Phil: Yeah. That's one of the reasons that enables this. But, yeah, keeping it all in the big brain is the other option, for sure.

Jason: [Laughter]

Chris: Yeah, so doubling down -- because deploy previews are already a killer feature, why not double down on it? That's my point.

Jason: Yeah.

Chris: Which you have here.

00:55:01

Jason: That's really what we're trying to think about how do companies grow. But we don't want to grow by making development more complex. We want to grow by making the rest of the stack simpler. We're trying to think, how can we bring the benefits of the developer experience of this JAMstack architecture?

You have all these pieces that got removed so that you, as a developer, have less to think about. Can we create similar experiences for people in other parts of the organization? What can your experience be like as a content creator or as a member of the marketing team? Can we make it less painful and create fewer leaps and fewer things to track so that your experience of working on a front-end is just as pleasant as the front-end developers who are building it?

Chris: I think the trick to making more money is just to stop paying our open-source maintainers so much.

Phil: Oh, yeah. Yeah, definitely. Yeah, good call.

Dave: I'd like to audit them all on Twitter regularly.

Chris: Yeah.

Dave: I perform performance reviews.

Chris: The second your GitHub chart gets light green, you're fired. You know?

Dave: Yeah.

Chris: It's the only metric that matters, I'd say.

Phil: I mean what we like to do at Netlify is we like to just mention them on Twitter because it gives them exposure.

Chris: Exposure.

Jason: Oh, God.

Phil: Which is....

Dave: Hmm. Hmm.

Chris: Seems fair.

Phil: That's also how I like to be rewarded for giving a talk.

Chris: [Laughter]

Phil: Exposure.

Dave: Exposure.

Jason: We send them socks, though.

Dave: Oh, good. Good.

Chris: Oh, socks. Good.

Jason: Yeah.

Chris: I go through the drive-thru at McDonald's, and I say, "Do accept exposure?"

[Laughter]

Chris: They say, "Yes."

Dave: I have 40,000 Twitter followers.

[Laughter]

Jason: How many Twitter followers is a Big Mac?

[Laughter]

Phil: I'm going to have nightmares of Chris going to a drive-thru and say, "Do you accept exposure." That's really going to haunt me.

Chris: It's only 10 o'clock here, but by 11:00, that'll be the reality.

[Laughter]

Chris: That's good. I think we covered all the notes here, so no need to stretch it out, boys. I appreciate you coming on. Dave, what do you have to say?

Dave: Yeah, thank you all. I have some zingers, but maybe they're private zingers about serverless and response times, but we can talk about that another time. We'll have you back on.

I guess for people who aren't following y'all and giving you money, how can they do that? We'll start with Jason.

Jason: You can find me on Twitter--where I spend more time than I [email protected] (the worst last name of all time) or on my website, jason.af.

Dave: You also have an excellent Twitch channel.

Jason: I should talk about, yeah. I run a show called Learn with Jason where I pair program with people. We learn something. It runs on Tuesdays and Thursdays. It's a lot of fun. Come hang out with me.

Dave: It's quality content. Philbert?

[Laughter]

Phil: First of all, I'm rushing off to Twitter to register the handle @philbert.

[Laughter]

Phil: I need that now. I mean you can find me usually fanboying over Jason in the comments in his Twitch stream because that is genuinely a good place to be. But I don't have the courage to do that myself. You can find me on Twitter as well. Phil Hawksworth is my name and @PhilHawksworth is my handle. It keeps it simple for me. I remember it that way. But coming to @philbert soon.

Dave: Good. Good. All right. Cool. Thank you all, again, so much for coming on and answering our questions about the state of the JAMstack. Appreciate that.

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, and sign up for the [techno voice] Discord. That's patreon.com/shoptalk. It's a fun time. You should join. Okay. Thank you.

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

Chris: No. [Laughter] ShopTalkShow.com.