skip to content

Run Next.js without Vercel

What does it take to support Next.js on a platform other than Vercel? Rob Stanford will share how he and his team reverse engineered Next.js to add support for its complex feature set on Netlify.

Full Transcript

Click to toggle the visibility of the transcript

Captions provided by White Coat Captioning ( Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.

JASON LENGSTORF: Hello, everyone. Today, we've got a whole lot of fun stuff coming up. This is a superinteresting episode because it's going to dive into a little bit of the workings of open source and how you can use one of the most popular frameworks in the industry, right now, on any platform you want without any vendor lockin. And here to teach us about it is Rob Stanford. Rob, how are you doing today?

ROB STANFORD: Hey, Jason. I'm doing good, thanks.

JASON LENGSTORF: For those who aren't familiar with you and your work, do you want to give us a background on who you are and what you do?

ROB STANFORD: My name's Rob. I'm a senior engineer at Netlify. Netlify is a web platform for composable websites. Our core proposition is to remove the friction from building and deploying and running modern websites, so we make it easier� and faster� to build websites, basically, plus helping developers to unify their data and content and helping content editors to publish content visually.
In the framework team, our role is to make sure that whatever framework you choose, whether that's Next.js or Astro, the features work seamlessly when you deploy to Netlify.

JASON LENGSTORF: Yeah. So, I mean, I've always had a soft spot for Netlify. I worked there for a while. You know, left in 2022 and the frameworks team, especially, is something near and dear to my heart because that was a team that started with my old team, Sarah kicked that off as a team instead of Experience org. It's in engineering. You're reporting to Claire, right?

ROB STANFORD: That's right, yeah.

JASON LENGSTORF: Claire is one of my favorite people. One of the best engineering managers I've ever met in my entire life. You know, lot of love for the Netlify team. But let's talk a little bit about, like, what it means to run a framework on a different platform because I think one of the most interesting things, to me, is when I was first getting started as a dev, that didn't� it didn't really make sense to� to have a framework be platformspecific. Well, it ran in PHP or it ran in Node. If you had a Node server, you could run it. That's less and less true these day and I don't know that I understand why.
Why is it hard to deploy Next.js somewhere other than Vercel?

ROB STANFORD: Sure. Sure. So, yeah, it's probably worth mentioning, we're talking about frameworks. We're talking about meta frameworks, really, because we're talking about frames that don't just have a UI, they have backend routing and rendering to consider and that all needs to be connected to the infrastructure components you want to deploy to.
Most modern frameworks have the concepts of different deploy targets, so if you want to deploy your website to Netlify or any other platform, for your chosen framework, you tend to find there are a number of adapters which you can use and they'll do is they provide firstclass interface for transforming the buildup that your platform of choice can deploy and set up the web architecture to support it.
And, Next.js is a little bit of an outlier, you can deploy to Vercel or subhost it. So, that's really the key difference. If you selfhost it, then you're basically running Next.js and building Next.js in standalone mode, which bundles up all your code and you're expected to upload that and that comes with a whole host of disadvantages.
I mean, you get the flexibility, but you've got to set the box up, you've got to maintain it. You've got security, scalability. This box you're running on Next.js could be geographically located miles away from some of your customers so there's a whole host of things to think about.
Most developers will be wanting to consider hosting in a serverless environment for mitigating those issues.

JASON LENGSTORF: Yeah. And so people are saying, here, you know, like, Ryan's deployed to Firebase. Brendan runs it on Render. In that case� I mean, I'm not going to say exactly how they're deploying it, but my hunch that's running in standalone mode.
And so, I guess, to clarify a little bit, when you� you talked about adapters and what� what I understand that to mean is, you know, I talk a lot about Astro, I like Astro, so when I deploy Astro, I say, you know� I use the Astro CLI. It goes out and it gets this adapter file that goes into the config that basically tells Astro which platform it's being deployed to and the platform owners are able to write code that tells the platform, like, how best� tells Astro how to bestprepare itself as part of the build, to take advantage of all the features of Astro on a given platform. Is that� is that the right� am I understanding that correctly, how that works?

ROB STANFORD: Yep. Nailed it. [Laughter].

JASON LENGSTORF: So, the difference then, is that, you know, if you look at Astro, if you look at Remix, if you look at Nuxt or Solid or most meta frameworks out there, these days, they all have this adapter API, with the notable exception of Next. So, I guess then, you talked about standalone mode in Next and so is standalone mode featurecomplete Next? I hear them talking about how the API routes works, the caching, there's a lot of threeletter acronyms that come out of Vercel and Next. There's ISR and things like SSR. You know, so do those all work in standalone mode?

ROB STANFORD: Absolutely. It's featurecomplete, but� but, um, there are considerations. Mainly performance considerations. So, ISR works, for example, it's a caching layer. It's hybrid between static rendering and dynamic rendering. And essentially what it means is you're prerendering and gets served statically at a cache and you can rerender that content at request time, either on a timebased interval or ondemand. So, ISR is a kind of caching mechanism. If you selfhost, you're running the cache at the origin server that you're running it on. If you host on a serverless platform, like Netlify, then you can run that cache on the edge, close to your users so you're going to much, much less latency.
The same's true for middleware, when you're running in standalone modes, you're running your middleware at the origin. You perform things close to the users. There's a lot about performance in there.

JASON LENGSTORF: In standalone mode, you can't, like� so, for example, if you tried to run standalone mode on Netlify, it would, what, put all of Next.js into a serverless function and you're kind of hooked on� you don't get to use any of the extra features of the CDN edge because it has no way of knowing about them. When you ship one bundle for everywhere that's not Vercel, you have to ship to the lowest common denominator that has no extra� it is� it's like a server box, sitting on a rack somewhere in US East 2. If it can't be supported there, then you can't add the extra features and so this is where the adapter� why the adapter API's so important and why it's, like, why it's part of so many frameworks is you want your framework to work well on other platforms.
So, without getting into the "whys" of why would the Next.js not want to ship it. How do you work around that. At Netlify, to ship Next, you have found a way to give that same, like, edge functions geographically distributed, compute, CDN, that does work on Netlify now?

ROB STANFORD: Exactly. Featurecomplete and the goal of the Next runtime v5 is we wanted feature parity with Vercel, but we also wanted performance parity. We wanted this to feel like, experience that Next.js developers would expect.

JASON LENGSTORF: Okay. Cool. So, that, then, kind of gets into the meat of what I want to talk to you about today, which is they don't provide an adapter API. So� like, how did you do this?

ROB STANFORD: Well, um, they don't provide an adapter API. But, Next.js is an open source project. So, it's possible to examine the code and understand it deeply, which is the work of myself and the amazing team at Netlify. And, what we can do is we can take the buildup of Next.js and we can make some small transformations to that in order to move content to the right places, essentially.
What we've built� that we call the Next Runtime, we isolate the static assets in your site, so that's things like CSS, images, things that aren't going to change within a single deployment. And we move them to a location so they can be deployed directly to the CDN on the edge. Secondly, we isolate the prerendered HTML, like React component data, and we put that into storage which is a new primitive that Netlify offer.
And then, thirdly, we create the code for a serverless function that will handle requests at runtime, so that's a dynamic rendering part. And fourth, we create the code for an edge function, which will run your middleware on the edge. So all of this is essentially what we do and it's a build time transformation, essentially.

JASON LENGSTORF: And then is this� so if Next provided an adapter API, it would ask you. You've effectively just sort of, in user land, built an adapter API for Netlify?

ROB STANFORD: Yeah. Exactly.

JASON LENGSTORF: Okay. Do you suspect that, like� this has got to be about the same thing that's happening behind the seen scenes at Vercel. They have their own adapter API, optimized for Vercel's servers.

ROB STANFORD: Vercel has the buildout API. It roughly conforms to your the�.next file. It is already in the format to go to Vercel and create the [Away from mic] architecture.


ROB STANFORD: We rearranged slightly.

JASON LENGSTORF: Okay. So, then we're not talking about, like, building custom stuff on Netlify. We're just talking about rearranging the build output so it ends up in the right places to function properly.

ROB STANFORD: Yeah, exactly. Plus, most of the work is in the runtime cache handling. There is build time component, where we're moving things so that the right things get into the right parts of the Netlify infrastructure but then at runtime, because app router is so different, all of the roots go straight through to the dynamic function, but there's four levels of�


ROB STANFORD: I know, I know. It's interesting. Next.js trying to configure this naturally. But as we've seen in a lot of the feedback that Next has gotten and some of the changes they're getting, the caching is complicating, people shouldn't have to worry about it but they do inevitably. I think we'll touch on that later on, some of the complexities around caching.

JASON LENGSTORF: I do know that whenever I use Next.js, after they add the app router, I struggle with the automatic caching. It doesn't work the way I expect it to and then I'm confused as to why I'm not seeing my changing is because something is cached. And there's a reason that caching is joked about as the hardest problem in computer science. It is� it's because it is absolutely, like, brainmeltingly hard when you start thinking about caches beyond one layer. If you think about it as a CDN, easy, simple. If it relies on the CDN and the cache and the serverless function and a edge network but the cache of the edge network, you've got this exploding complexity problem. I don't even think our brains can handle the number of variations that can happen when caching gets beyond three or four levels. Of course, we're going to cause problems if we're trying to manage it manually.
This is one of the features brilliant about Netlify and the early days of Vercel and Cloudflare, put your stuff here and it's cached. You don't have to manage it anymore. Your caching idea is upload and we'll make sure everybody gets the new file and that's it. That's all you have to think about it. Really kind of caught me off guard when I started seeing the arguments being made in JavaScript land. I was like, no, no, wait. Did you forget what this used to be like?

ROB STANFORD: 100% agree. And it is really interesting because I think, like, the one sort of web frameworks have evolved a little bit and whilst there are more complicated caching requirements now coming from the developer community, people want to have more control, we just need to find that where we don't have to use [Indiscernible] and that's what we've tried to do with some of these new caching primitives that we've got at Netlify and these are the same� when I say "primitives," I'm talking about platform features. These are the features we've leveraged in the Next.js runtime.

JASON LENGSTORF: I don't want to go too off the rails. I got to talk to Bill, the CEO of Netlify. Where it feels like there are sort of two directions you can take when you are building and one is to optimize a platform for that platform's thing. And, a good example, this is, like, WordPress hosting. There is a huge amount of hosting that is highlyoptimized to run WordPress specifically because of its popularity and Vercel, I don't think quite as heavily focused, there's still that general sense of, this is tuned for Next.js because that's the framework they build.
And then there's the opposite way to look at it, let's build these lowlevel primitives that work everywhere and I think that's the approach that we've seen from Cloudflare, for example. They don't build frameworks. They build primitives that often, those are lowlevel and you have to build a framework on top of them to make them usable by normal mortals like me.
Netlify has taken a really interesting approach where it's these primitives are for every framework and the primitives you just talked about, that are being used to make this Next adapter, these are the exact pieces powering, even Vanilla HTML. But they're made in such a way that they don't have to be tuned� specifically, they're tuned for the web. The web use case. And I think that's, to me, that is a really fascinating way of taking it and it's also� it's like a� it's a long game. Like, it's a challenging game to play when you bet on the web because you can't own it. Right. Like, it's a thing you can't� you can't, like, jack up the price on the internet, as a company that builds for the internet. You got to own the ISP for that and that's never going to be us. [Laughter]. So then it kind of� it's this "bet on the open web" that I think is really interesting. Longterm, I think it is a safer bet. I've been around for a little over 20 years and over that time, I've seen the frameworks turn over multiple times and I've never seen the internet turn over. To me, it's kind of like that old saying, you never get fired for betting on IBM. You never get fired for betting on the web. Right. [Laughter].

ROB STANFORD: Absolutely. 100%. This has always been our driving goal, at Netlify, to kind of promote the open web and that's why when we were thinking about these new platform primitives, we weren't thinking about how do we make the runtime for Next.js work, how can we kind of do that? It was more, what can we build on our platform that can serve the Next.js runtime and the other frameworks? For obvious reasons, the more frameworks out there for developers, the more choice, the more innovation, it's just something that we are keen to promote.

JASON LENGSTORF: Yeah. And I promise I'm going to move on here after this, I just wanted to call out one more thing, which is there was this recent, I think, huge leap forward in frameworks and it was that, you know, the sort of rebirth of signals and how we manage state and really moving past what I think was a� like, a local maximum or for how we did state, where we'd kind of settled on some things but we really weren't happy with any of them and we get Quick And Solid and the Angular team. What about signals? What if we didn't have the drawbacks of what the React hooks are doing, which they've now solved in the React compiler. The Angular team was looking at the way they were implementing state and they brought in signals and we're seeing this big leap forward where the API of all of these frameworks improved because we had the diversity of lots of different people borrowing ideas and trying to something new and, you know, there's lower risk in something like Quick or Solid because they don't have the giant production userbases that will really be hurt. They can be pretty agile. Once we've proven it out, the bigger frameworks can say, wait, that's actually really do. We should do that. It's validated so they can actually prove the point. I think, yeah, the broadness of this space can feel exhausting when you're a developer because there are so many things that you� you feel like you need to keep up on and you need to care about. But it's also such a strength. Right. And I think there's a discourse going on right now about how Rails and Laravel are featurecomplete. You don't have to choose ecosystem tools because they just do it and that is amazing. Like, the velocity you can move at, with one of those, is truly impressive. And in the same breath, the absolute diversity of the ecosystem in JavaScript is a strength. Like, it's got tradeoffs, like anything else, but the fact we are out here, trying things, innovating, seeing if we can challenge, has led to some incredible innovation. If you look at JavaScript today, versus JavaScript 10 years ago, it's like a completely different landscape and I think� yeah, a little� little word of calm and happiness to go to anybody who's feeling stressed out about the state of things today. It can feel chaotic but it is, in fact� it is making things better.
So, Rob, my� my little diatribe aside, I am very� hold on, first I have to be very upset at Phil. First of all, how dare you. [Laughter]. Um, okay. So, I� I� I could probably talk about this quite literally for the rest of today without taking a breath, but I want to actually try this out. So, if I want to get started� do you mind if I bring us into Computer Mode and we start doing things?

ROB STANFORD: Let's do it.

JASON LENGSTORF: I'm going to first, and foremost, give a quick shoutout to Rob. Let me do the LinkedIn link again and we'll get that into the chat, so make sure you go and get Rob� it's not a follow, it's a connection now. Make a connection, make a friend. This episode is being live captioned. We've got Vanessa here from White Coat Captioning. Thank you so much. You can find the link to it down there, on the bottom. And, with that...I'm ready. I want to� I want to do some stuff. So, what's the first thing that I should do here, if I want to� if I want to make some Next stuff happen?

ROB STANFORD: Sure. Well, let's fire up a...a Vanilla Next.js and get it deployed to Netlify.

JASON LENGSTORF: All right. I'm going to NPMcreate. We're going to call this "next without Vercel." We will use TypeScript, sure. We'll use ESLint. Should we use the pages or the apter?

ROB STANFORD: Let's use apter.

JASON LENGSTORF: Okay. I don't like those import aliases. They always confuse me. Give me a relative file path any day. I don't care if it's 99 dots long. Okay. So, then I'm going to get into my folder, here, "Next.js without Vercel. "Do I need to install now?

ROB STANFORD: You're all done. You can go� if you're in there, you can bring up the code.

JASON LENGSTORF: All right. So, let's open this up. And I'm going to close this one. And� let me...initialize that so we can actually see what's going on and then let's take a look in here. All right. We're running Next 14, React 18 and all the� the config stuff to make that work. So, how do I deploy this to Netlify.

ROB STANFORD: Sure. You've got a couple options. You can go down the CLI route or go through the UI. What's your flavor?

JASON LENGSTORF: Let's do the CLI. That sounds fun. What I'm going to do, in fact, is I'm going to dump all the home page stuff. We'll just get rid of that and we'll a nice, simple one. Let me deploy this� let's run it and make sure that I just didn't break that site when I did that.


JASON LENGSTORF: We're running Localhost 3000. Okay. So, nice and simple. But, it works. So�

ROB STANFORD: Cool. Before you deploy, because we're doing this via CLI, we need to install the Next.js Runtime. You're going to need to add a little netlify.toml file.

JASON LENGSTORF: Oh, wait, hold on. Do I� what are my options again?

ROB STANFORD: Sure. We can go to the Netlify UI and create it that way.

JASON LENGSTORF: Why don't we do that because I think that's kind of nice to see. I did the "get init." Let me make sure there's nothing. I'm going to "get add everything." "Get commit." And we'll say "initial commit." So then I'm going to create a repo.


JASON LENGSTORF: And we want to push the existing one, we're going to do this one, there. We're going to send it to Learn With Jason. Yes, I should probably make an alias that all the right flags to do this for me. Then, I can� did I already push that? Yes. Okay. So, now we've got this repo here. So I'm going to copypaste this. Head out here and there's our repo. I'll do a quick one of those...okay. And, I'm going to go to the Netlify site. All right. And, add a new site?

ROB STANFORD: You got it.

JASON LENGSTORF: Okay. GitHub...and...I have, like, 900 repos on here. [Laughter]. There it is.

ROB STANFORD: And this will detect that that's the Next.js site. Should be able to use most of the defaults, apart from the name.

JASON LENGSTORF: Yeah, I didn't change any defaults so it should just kind of run, right? I didn't add any environment variables. This wasn't here when I left Netlify, so I'm happy to see this, this is nice. [Laughter].

ROB STANFORD: That's the difference if we did that via the CLI method, we would have to tell the build process we will use the runtime.

JASON LENGSTORF: Oh, okay. Cool. The reason I wanted to come in here is I actually� I love not having to use a netlify.toml. It's so nice to just be able to say, like, it just worked. Okay. What failed? Should we use your� should we use this thing? Is.

ROB STANFORD: Yeah. Go for it.

JASON LENGSTORF: I'm not going to do it now. Does it just work if I use this button? Oh, oh, I see. Due to a dependency conflict related to ESLint versions, what does that mean? Could not resolve� all right. Whatever. We're going to run one more "NPMinstall here." Nothing changed so that's not ideal. Um... ESLint 57856. Coollll.

ROB STANFORD: Interesting. So what� what version of Next are you using? You're using 14.2.3, weren't you?

JASON LENGSTORF: IIIII think so, 14.23. It's saying "use ESLint," the TypeScript ESLint and the other one. They're all saying 857. So, why don't I do this...I'm just going to fix it.

ROB STANFORD: This is a newer dependency. It's interesting because when I put the Next.js together earlier, that wasn't there. It must be something quite new.

JASON LENGSTORF: What are you doing? Why did I install ESLint? It was a mistake. Can I just turn it off?

ROB STANFORD: I'll tell you what we could do, we could create another one with it.

JASON LENGSTORF: Let's do that. That seems better than whatever the heck is going on here. How is this broken out of the "create Next app" thing?
Let me remove here and then we're going to NPMcreate Next app. Let's see if I had something out of date here. Okay to proceed. I do want TypeScript. I do not want ESLint. Installing dependencies. Then we're going to get into this folder. I'm going to "get init" and this time, I want to� actually, how are we going to do this? "Get remote add origin" and we're going to do "get" to Learn With Jason, next.get. I'm going to "get add everything." I'm going to "get commit." And then we're going to get push force.

Rob Stanford: Love it.

JASON LENGSTORF: Oh, wait... oh, get out of here. [Laughter]. There we go. All right. So, almost� almost remembered that, first try. Then, this should be deploying without ESLint.


JASON LENGSTORF: And now our dependencies should match, I hope.

ROB STANFORD: Yeah. Exactly. And what we should get is just that static page because that is what it is. We're not fetching any data or anything like this, so this should be statically rendered at build time, which is what is going to happen at the Next.js build process and then we're going to make sure that goes up to the blob storage and that is cached on the way out. But let's� let's get rolling first and then we can talk a bit more.

JASON LENGSTORF: Yeah. Looks like it's doing the thing now. There was a really good suggestion, in YouTube, to use Legacy [Indiscernible] so thank you for that. Would have saved us some heartache. Hopefully this also works. [Laughter]. Um, I mean, I do like [Indiscernible] code. It's not bad.
[Laughter]. Let's see...all right. Complete. Complete. Complete. All right. Is our site up and running here? Let's go "site overview." We're going to pop this one open. I didn't change anything so this is a straightup default thing, but, hey, it all works. Once we get our dependencies cooperating, it just works. All right. Everybody's happy. All the stuff did what we wanted it to do. Oh, these are all external links? These are all pages.
Okay. So, then...what should we do next?

ROB STANFORD: So what we've got there, yeah. It might be worth quickly explaining what's going on in the runtime, like I was saying earlier. It's funny, an app router, you don't have a clear delineation between a statically rendered page and a dynamicallyrendered page. We're not fetching any data or anything like that. But the interesting thing in app router is you can ondemand revalidate any page, even a static page. In theory, you could ondemand validate this page. Should we stick a timestamp on it? If we put it in some text somewhere.

JASON LENGSTORF: Yeah, let's do it. I'm just going to do the same thing I did before and let me knock out this stuff here and we'll say...then we can do "new date." Let's do "new date to locale string "would give us both. Let's run this locally, for a second, before we deploy it. I'll head back over here and check my local site...okay. And now we get, every time I reload, we can see that the seconds are increasing.

ROB STANFORD: And this is a point to note because when you run things in Dev Mode, which is what you're doing there, there is no caching applied so everything is dynamically rendered. We've got a timestamp on our static page. When we deploy this to Netlify, you'll see that that timestamp should remain fixed because the page is cached.

JASON LENGSTORF: Yes. The reason I just did what I just did is I was seeing that 3000 must be the same port that Quick uses and we were getting this 404 so I cleared all the storage on my Localhost 3000.

ROB STANFORD: Yeah. We had some feedback from the folks, back at Netlify, wondering if there might have been global legacy [Indiscernible].

JASON LENGSTORF: Okay. Cool. Now we're in good shape here because we've got the site running. We're getting our dates. Because we're in the Dev server, it's updating. Why did I stop that? I should have kept it going. We'll say "get commit." And "update home page."


JASON LENGSTORF: And we'll push.


JASON LENGSTORF: And then out here, little build. It took about 49 seconds last time, theoretically it should be quicker this time because we don't have to install the dependencies.

ROB STANFORD: Exactly. Whilst it's building, I can talk because what we're going to see here is because we've got no content on that page, Next.js serves up� it knows that there's nothing changing on that page. It doesn't understand that the timestamp is something you might want to see refreshed so it will� it will respond with a response that has a stale validate header in it. And it has a stale max age of a year, which is essentially an infinite, you know, for an infinite period of time, as far as a deploy's concerned. And so our next runtime intercepts that response and adds a Netlify CDN cache control header, which makes sure that caching only applies on our CDN and doesn't go through to the browser.

JASON LENGSTORF: Yep. And now we're cached.

ROB STANFORD: That's cached on the edge and it will be cached for a year.

JASON LENGSTORF: Great. So, for something that is static, which if we're being honest, the vast majority of web pages are static, then this is exactly what we want. But let's say that we did, in fact, want this to update every time you refresh the page. How would I support that? Because is that� which acronym is it when we want that, is that ISR?

ROB STANFORD: It's a funny one. It's SSR. In theory, everything is SSRrendered because even the stuff you're statically building is rendered with the server. Anyway, we'll skip over that. They call it SSR.

JASON LENGSTORF: Okay. Okay. If I� so what do� I want to mark this as dynamic so how do I make this page dynamic?

ROB STANFORD: Sure. So, in this instance, Next.js hasn't been able to work out, so you can force this. You need to export a const, which is called "dynamic." And that value� well, yeah, you'd think so, wouldn't you? It's actually a string value of force dynamic.

JASON LENGSTORF: Ooohkay. What are the other values?

ROB STANFORD: Um...that's a very good question. Um... whilst you deploy, I'll look it up.

JASON LENGSTORF: Make home page dynamic. Did I commit that? Oh, nope, I didn't. "Get add all." And then we'll run that. Push. Okay. So now that's going to build...

ROB STANFORD: Yep. So, yeah, the other ones are� oh, of course, for static, which is something probably best not to get into yet because it's also not quite what it appears to be...but, yeah, essentially, this is where� you know� the Next.js caching is clever but sometimes you need to know how to [Away from mic] and directions.

JASON LENGSTORF: And I mean, and, you know, I can see, like� I think this is one of the things that is both, like, very powerful and also, very, I think, to me, like, troubling about Next.js is that you can quite literally do anything with it and it's not always superclear, like, what the thing� like, why it should be used or when it should be used and so it� it� it becomes, like� one of the problems that I had, when I was at IBM, for example, is we would spend a lot of time building things that were...very flexible. And, then, the only way that we could enforce things was through, like, really cumbersome QA processes because you needed a human to go in and look to see if it was done the way the team decided. That's fine, but I want most of those conventions to disappear into the framework. Like, one of the things� like, this is actually one of the reasons why I started pushing for the staticallyrendered frontends was because it allowed me to, through convention, enforce good behavior so as a dev, if you wanted to do something in a different way, you had to sort of optin very intentionally into a different process because you had a use case that supported it.
And I think the part that's hard about a lot of these frameworks that don't have that, like, default� this is why I'm such a big fan of Astro, right. It's static until you very explicitly tell it not to be. When you explicitly tell it not to be, usually you have a reason. What I like about that is it� it sort of, like, builds this automatic enforcement as opposed to a topdown cultural enforcement that has to go through strict ESLint rules or ESLint failing tests. [Laughter]. So, yeah, just a little quibble of mine and one of the reasons I don't reach for Next.js is honestly exactly like that.

ROB STANFORD: I think particularly around caching� and I think that's potentially why they made some amendments in Next 15. I think for a lot of folks, caching feels like a performance optimization you add on and that's where� because I think the problem with caching by default is you can introduce bugs that way. Think of any Ecommerce app. For a lot of folks, it's worse to introduce a bug than it is to have, like, performance slightly less because you can work on that and iterate with that and I think in Next.js 15, they've� they've clearly realized that and there's a few of those four caches, which are not on by default. The data and the clientside cache is not on by default. I think there's lessons there, for sure.

JASON LENGSTORF: Great. Great. Great. So, checking here now, whenever we reload, this is updating. Now, the downside of that is, of course, we're fully rerendering this in its entirety on every reload.

ROB STANFORD: Exactly that. There's no caching in between the server and the browser. So, we're getting a full round trip every time.

JASON LENGSTORF: Which, um...sometimes is good. Like, again, if you have a dashboard and that dashboard is full of data that needs to be up to the second, you don't� like, you never want to cache that. But in a lot of cases, like, especially for something like this, that we're looking at, if I just want to update the time on the� on the screen, and everything else is static, there are probably better ways to do that, that don't require the entire page to be dynamic. We've introduced bugs where it is localized to the server and not to me, the user, so we'd have to now figure out, how do we figure out the requester's time zone. In this case, the real solution would be, let's just do this in JavaScript. Let me put this in a browser, like, a clientside call.
But I digress. So, let's go a little bit further. We've got static pages, we can force them to be dynamic. What about, like, let's see, there's a few other things that happened here. The one I know, off the top of my head, is images, because there's that image component for Next. There's all the stuff, it's kind of fancy stuff, on Vercel, that will do the resizing and it supposedly caches them. Does that just work?

ROB STANFORD: Absolutely. Yeah. So, we leverage another one of our platform primitives, which is the Netlify Image CDN so all of that image transformation is offloaded from the origin server so that would be interesting to have a look at. Actually, coming back to what you said about the timestamp not being a really representative example, we should get some data in here, data from an API. We've got two levels of cache, the data cache. We can look at images if you want.

JASON LENGSTORF: What do you want to do first?

ROB STANFORD: Since we're in the mode of caching, do you want to have a playaround with data first?

JASON LENGSTORF: Sure. I can do, what is it? and then we can I just get to put in a login and go? Yeah. Okay. So, this will� this will be an easy one for us to do because we can play with some of the, like, fetching part of it.
So, remind me how� should we do, like, a dynamic route so we can change it and see different data?

ROB STANFORD: I think� what would be really useful to show, because I think� a use case that a lot of people have is they might have content coming from a content management system, or something like that, and they would want to update that content and then have that specific route with the content on change. That's going to require� I mean, either you've got a handy CMS that you know how to call an API for�

JASON LENGSTORF: I do. This is� this is my� [Laughter]. This is the Learn With Jason API so it's got all the episode data so we can build that out if we want.

ROB STANFORD: Great. And we can make a change to it, can we?


ROB STANFORD: Let's do that.

JASON LENGSTORF: Let's go...uhhhh, actually...why don't we just go straight to Sanity because I think� if we're going to, like, get the changes right out of the gate, we should probably use the Sanity APIs and for me to do that, I need...more than I've got. I set all this up so long ago that I forgot how I actually use it. How many of my details are going to immediately become visible when I do this?

ROB STANFORD: Everyone, look away. [Laughter].

JASON LENGSTORF: Um... I'm going to take us offscreen, in case this shows an API key.


JASON LENGSTORF: So I've got my� those are webhooks, but I don't need those. "Add API token." What's the actual API? Oh, boy. Somewhere in here is a button that will let me get at the data. I know how to do this. Project ID. In the studio. Do something like this...okay. I think I got this. Yeah, all right. All right. All right. I got this. So, we have� I'm going to bring this back up so that everybody can see. And, so it makes a call to the, um, project ID and then you hit this general thing, here, and then we have to send in a token...which I will be able to get, and that will let us do the thing. So...why don't I...get's the� here's the request. Right. And then if I come out into here... what is it, here? It's not Loader?

ROB STANFORD: No. So, the Next.js data fetching is literally with a fetch so you want to define an async function called something like, "get content." Or "get data."

JASON LENGSTORF: We'll call it "get episode." Response equals fetch�

ROB STANFORD: Await fetch.

JASON LENGSTORF: Await fetch. And I need to put in one of these. Let's just get "type equals episode" and dump everything else and then that should give us 405� wow! That's a lot of episodes. Okay. Um, and then I think I can even, like� let's simplify this a little bit. I think I can do 0 to 10. Is it...that's far simpler and we'll give us, I think, an easier time with...that request. So then if we come in here and� so that in here...get rid of...this part. Okay. So that almost works. It's going to be missing the header and that header is going to be an environment variable that I'll need to set. So that's headers� nope, not whatever that was. Oh, my god. Come on. Wait, why did it just import something? VS Code, you're betraying me right now. Chill. Just chill. So then it's "authorization." And that's going to be a bearer token and that bearer token� is it processed on [Indiscernible]. Do you remember?

ROB STANFORD: It is. Yeah. But this is going to� let me just think about this. It's going to� we're going to need add that environment variable�

JASON LENGSTORF: In Netlify. I'm making a lot of assumptions of how this all works. Why are you yelling at me? Oh, because we don't have this doublequoted. Or, doublebracketed. And then, once we've got that done, we can do an "ifresponse.okay," we'll throw an error. And then down here, we'll get, "await.response.json" and then we can do something with it. We'll do data...we'll just return data. Which I need to get that Sanity API token, which I'm going to go offscreen for and, let's see, that was in this page here... got an API token. Okay. We'll go into the Netlify dashboard, into site configuration and then environment variables. Going to add a variable and this variable will be the same for all deploy context and I'm calling it..."sanity API token." We're going to hide it so I can bring the screen back up and show everybody what I'm working on right now.
So, this is the environment variable. I'm going to create that variable and now that I've done that, we theoretically can just run this.

ROB STANFORD: We could try doing it in Dev just to check that that� that works. And I suppose we'll need to put that response somewhere in the� in the� in the output, in the Markup.

JASON LENGSTORF: What just happened? No package JSON.

ROB STANFORD: I think you can just "ntl dev" without the "npx." We haven't set this up in the CLI yet and haven't installed the TOML file. Sorry. My bad.

JASON LENGSTORF: I have a lot of issues with the way that� let's� yeah. Okay. I'm starting to regret my choice of trying to do Sanity. [Laughter].

ROB STANFORD: I've got a Plan B.

JASON LENGSTORF: Maybe let's go to your Plan B. I'm working this isn't going to start on the first try.

ROB STANFORD: Sure. I have a� a public API, which doesn't need an environment variable, plus it's� I mean, basically, it delivers a random quote from Stranger Things every time you hit it. And that's good because it kind of mimics someone changing something in the Content Management System. Can I drop something in the chat?

JASON LENGSTORF: Yeah. We've got a private chat you can drop things into and I can copy from there.
Okay. This is� nope. I am copying the link address...I'm going to drop it right here...


JASON LENGSTORF: Okay. And, if we just hit this in the browser, we get an array of quotes, so, good. We will then� we'll get our response. We'll call this, um, what don't we just do, like, "at zero." And then down here...we can do, like, a pretag and we'll JSON stringify. We'll have to figure out how to get that quote. And null two and that'll be� wow! Jeebus. Okay. So, how do we get this data out? We just� we just call, like, "quote equals..."

ROB STANFORD: Yeah. You'll need to await it, I believe. Yep.

JASON LENGSTORF: Okay. And I can just make this async and it's not a problem?

ROB STANFORD: Yeah. Exactly.

JASON LENGSTORF: Okay. So we'll run that and let me doublecheck that this works. Um..."NPM run dev." Okay. And we'll out in 3000. There we go. Okay. And every time I is currently giving me the same� oh, here we go. There.



ROB STANFORD: Which is what you expect in Dev Mode because every route is dynamically rendered, but if we deploy that, we can start talking about the data cache because as I mentioned, there are four levels of caching in Next.js. Two aren't really relevant to this discussion because they're more implement� well, they're� you've got the clientside React cache, which is� happens on browser navigation, that's being� that's changing in Next 15 and won't be enabled in default now. You've got the request minimalization, Next never calls a fetch like this more than once. We can ignore these. The big things are the route cache and in this instance, the data cache.
So now that we have a made a fetch call here, Next.js understands that we're pulling data into that page and in Next.js 14, by default, that response will be cached. So�

JASON LENGSTORF: So, without this�

ROB STANFORD: Yes. Oh, sorry. I forgot we had that in there.

JASON LENGSTORF: If we take this out, then it will cache this response?

ROB STANFORD: Exactly. And you've kind of got caching at two levels going on there because that cache will be cached.

JASON LENGSTORF: It monkeypatches? That is supposed to come out in 15 because they decided that was a mistake?

ROB STANFORD: When you're getting fresh results each time, you're going to upload that to a platform somewhere and it's not going to change. That doesn't make any sense to me so I think that was an important, necessary change. But, since it is like that in Next 14, should we also set up a route handler, which we can call to ondemand revalidate this page?

JASON LENGSTORF: Sure. How do I do that?

ROB STANFORD: Cool. So, if you just create a folder and we'll call it "revalidate," or something like that, within your app folder.


ROB STANFORD: And then a file within that called "route.ts."

JASON LENGSTORF: Ts? Like, "route"? British route or American route. [Laughter].

ROB STANFORD: Cool. So, in this one, we just need to export an async function called "get."

JASON LENGSTORF: And capital "get."

ROB STANFORD: Which takes the request as a parameter.


ROB STANFORD: And then� oh, yeah�

JASON LENGSTORF: Is that the browser request?

ROB STANFORD: Yes. Yeah. I believe so. It might be a Next request actually saying that. Let me, um�

JASON LENGSTORF: So I need to import Next request?

ROB STANFORD: That might be the case. I'm just, it is just a standard web API request.

JASON LENGSTORF: Okay. Nice. Okay. Cool. Okay. And then in here, what� what am I doing?

ROB STANFORD: So you've got a couple options. You can revalidate your path or you can tag your data with cache tags and revalidate data. For this simple example, let's revalidate path, which you need to do from Next cache.

JASON LENGSTORF: Revalidate path from Next cache.

ROB STANFORD: We want to� I suppose it's just the route, so, yeah, just that exactly.

JASON LENGSTORF: The root route. [Laughter].

ROB STANFORD: Exactly. We'll get there. We'll get there. I think we can send that without any other parameters but you might want to return just a response, I don't know, maybe, like, "return Next.js response." I'm not sure whether it needs to be a Next response that needs to be returned.

JASON LENGSTORF: Let's see if it yells at me. Just something like that so it doesn't get sad?

ROB STANFORD: Yeah. Sounds good.

JASON LENGSTORF: Okay. When I run this, it says "compile." It's not yelling at me. And I just"revalidate"? Like that?

ROB STANFORD: Yeah. Although this isn't going to show you much in Dev unfortunately because the route page is being dynamicallyrendered on every request so we might have to deploy this to Netlify to see the magic.

JASON LENGSTORF: Sorry. I'm doing this wrong. I got a 404 when I went to revalidate "route."

ROB STANFORD: Sorry, I may have told you incorrectly. The path will be "revalidate" without "route."

JASON LENGSTORF: We're getting our response. It's not yelling at me for not using a Next response. I think we're in good shape in terms of functionality. I'm going to have to add everything. "Get commit m." And add revalidation. Endpoint. Push that up. Okay. And so, while� while we're talking about that, can we� I'm just going to do a build, real quick.


JASON LENGSTORF: And I just want to� because somebody was saying, why aren't we calling this "use Next.js on Netlify." We're using Netlify as an example but the part that is interesting to me is what is happening� why did we have to do extra work anyways, instead of being able to deploy this anywhere. You mentioned, earlier, we have to split things up to move them into the right places. Can we walk through a little bit of what's happening here and how it gets moved around once it's built?

ROB STANFORD: Yeah. Absolutely. Do we have a public folder outside of the�.next?

JASON LENGSTORF: Yeah, there's a public folder here.

ROB STANFORD: These have got some static assets in them. Those are not going to change throughout the lifetime of the deployment. We can move them straight up to the Netlify CDN. What would be interesting is if we should run a build locally. We could see� no, we can't. Forget that. So, essentially, we got four steps. The Next runtime will take the things in the public directory and also the things in the�.next static directory, I believe.

JASON LENGSTORF: Things like CSS. Yeah.

ROB STANFORD: All of that. And we make sure that that, at the time of deploy, is the only thing in your publish directory and that means Netlify will push that up to the CDN as part of the deploy process, never going to change the part of that deploy. We've got atomic deploys. The second thing we do is take the prerendered HTML, so, in this instance, for this site, we've only got one page. It's a static page because we haven't got the force dynamic on it and we're not telling Next, at the moment, that's data fetch that we're doing shouldn't be cache. Next.js will say, fine, that's static. You should find in the server folder, there, under "app," yeah. Index.html.

JASON LENGSTORF: And here's our cached.

ROB STANFORD: Yeah, prerendered HTML. And that's important, especially when you've got a larger site or you're calling kind of expensive APIs, it make take a while and you want to make sure that you're prerendering as much as you can at runtime. You'll notice there's a bunch of associated files, index.meta. This is the React server component data that goes along with that and some� some various metadata that Next uses and we package that all together and put that into blob storage. The reason for that is that HTML that you can see there might change during the lifetime of a deploy because as we're going to see, hopefully, if someone does a revalidation or it's got timebased revalidation, a request might make it revalidate and it's got to be an immutable place. We have to put it into some kind persistent, mutable storage, which is why we use the Netlify Blob Store.
The third thing we do is create a server handler to run the JS code and we do that by� if you close up the app folder...actually, sorry...hmmm. Yeah, maybe keep it open. [Laughter]. You can see, as well as the HTML and meta and RSC, there's a page.js file. So, this is all the� the server code that Next.js will use to render that page; which is important because as I mentioned, anything can be rerendered at any point. Even though we've got the HTML at build time, Next.js needs to know how to render this route ondemand when necessary. So this is all the code required to do that.
And we make sure that all of the server code gets bundled up with all the dependencies, plus your user code, into a Netlify function, which will run when that route needs rerendering at request time.

JASON LENGSTORF: Okay. And then, we've also got the, like, the route.js. Is that getting bundled as well?

ROB STANFORD: Yeah. That's a specific type of route, called a route handler. And, that works in the same way. So, it is also prerendered and this is a really interesting point that might be useful for your watchers and listeners because in Next.js 14, route handlers, our route handlers, like the one we've just created, the revalidate one, are also cached by default. So, that can be quite confusing to folks because you might be creating a handler, which, you know, is like an API endpoint, essentially, but the response from it is going to be cached by default. That's a Next.js thing they've changed in 15.

JASON LENGSTORF: Okay. And so, and the reason that this is all important to look at is that by default, if I go to deploy my site on a Node server or something, the splitting of these files isn't happening and so everything here� and we're not using middleware, but if there was, you'd be pulling that off to the edge so because Next doesn't supply that adapter API, there's no way for platforms to tell Next how to move these files around so as a platform author, or as a user wanting to deploy Next to another platform, that's not Vercel, we have to do this work and so in the case of Netlify, these get moved into Netlify functions, into the Netlify edge functions. In the case of something like Cloudflare, it might be, instead of blob storage, you're using� what is theirs? D1? I can't remember what they call it. If you were doing it on AWS, you would need to deploy parts to lambda and parts to S3 and CloudFront to replicate the functionality of what Vercel is doing so that you actually get the same performance and behavior.
And so, that's� that's why we're talking about this is that, it's not just a matter of deploy it and it's done. If you want to be able to get the actual performance that Next is capable of, you have to do more and in the absence of an adapter API, there are a lot of manual steps and these are what Rob has gone through with his team at Netlify to get this thing runs. That's why we're looking at this today. It shows just how complex it can be to run modern software well.
And I think that is� that is worth calling out and kind of talking about. So, with that being said, we now quote and when I reload the page...I get the same quote.

ROB STANFORD: Yeah. We're going to need to deploy this to Netlify. Perfect. We're here.

JASON LENGSTORF: So now if I revalidate, it should, theoretically� this is my revalidation. And now I'm going to go back to the home page...and reload. Oh, it didn't do it.

ROB STANFORD: What have we done wrong?

JASON LENGSTORF: That is a great question. Do I have to "await" that revalidate path?

ROB STANFORD: Let me So, revalidate path.

JASON LENGSTORF: Do you skip the leading thing?

ROB STANFORD: Nope. Nope. That's definitely right. I've got a similar build doing something exactly the same and I'm using a forward slash. Let's look at the� the page again, the route page. So, we're getting a quote. Um...we're fetching that.

JASON LENGSTORF: We returned the data. And then we display that, straight on the page.

ROB STANFORD: Straight on the page.

JASON LENGSTORF: And we're also� I'm noticing, not seeing� when I reload, I'm not seeing, my revalidation is working� or at least, it's returning my thing and then when I come back� oh, here it goes. It did it that time.

ROB STANFORD: Ah! I tell you what, we might have fallen [Indiscernible] of the fact that route handlers are cached actually, because I said that. We need to add the force dynamic to the route handler.

JASON LENGSTORF: Oooohhh. Oh. Okay. So, then "export const dynamic equals force dynamic." And that will prevent this from caching. "Get commit." And we'll say "fix force route revalidation to be dynamic." "Get push." Right. And so, yeah, because it looked like if I� I was in there and I, like, refreshed it a few times and then went to the home page and refreshed, then it works.
Um, so, the� the� the cache is maybe, like, [Indiscernible] while revalidate or something?

ROB STANFORD: Yeah, yeah. Quite. The expected behavior is the first time, after you revalidate, I believe, the first response will be served stale and while the regeneration happens in the background and then the second response, you'll get the revalidated data.

JASON LENGSTORF: Uhhuh. Um, and then while we're waiting for that deploy, there's a question from Michael about, why wouldn't you want to host Next.js on Vercel? I mean, there are a lot of reasons and I think, like, the most common ones, for me, are all of my sites are on different infrastructure so, for example, when I was at IBM, we already had whole deployment setups for, like, everything. We had the way we ran Node servers and CDNs. The idea of introducing a new vendor was a nonstarter. For other startups, you put all your stuff in one place. Maybe we're running everything on To have to put one site, one framework on a different vendor introduces new processes, new API costs, new people who have to know how everything works and it introduces complexity that can be challenging on teams. I like having choices. I want to know if I'm using Next.js and Vercel pivots and decides they're only going to ship Java, you know what I mean, I don't want to be stuck, like, crap, I can't use Next.js anymore because Vercel doesn't want to host it.
Or the alternative� and potentially more likely thing, Vercel just took a giant round of funding, at some point, they'll have to get returns. Prices will go up and things will change on the platform. As a user, I want to be sure that if they do changes on the Vercel platform that I don't like, I don't have to then migrate all of my sites off of Next.js in order to keep running my business. I want to be able to move those to another platform confidently. I'm not saying any of that will happen, but these are the types of things I worry about when it becomes clear that a framework is built for a platform. It starts to remove optionality. I might get very short notice windows to have to make major company decisions based on the behavior of a single vendor and that freaks me out.

ROB STANFORD: Sure, sure. We're building these platform primitives with the open web in mind, so we're� so, for example, things like� we're looking at PPR, which is something that, you know, Next.js is looking at introducing in the near future and ways to develop that. But specifically� and this is always our goal� to do it in a way that we can leverage all frameworks. So, Netlify is a platform that is trying to keep options open for  for developers, so, that's good in a widen sense but also as a developer, you have those choices when you have a platform.

JASON LENGSTORF: Yeah. I mean, ultimately, like, choice is never a bad thing and a lack of choice is almost always� not necessarily a bad thing, but a risk. So, to me, that's sort of my major concern.
But, that being said, um, is Netlify the first platform to achieve such compatibility? I actually don't know the answer to that question. I feel like people have managed to get it managed� SST is another platform that's figured it out pretty well. Do you know of any others?

ROB STANFORD: There's a server platforms that have Next.js support. Fly just launched something. There's support and there's support, there's a spectrum of support for Next.js and I think some of the platforms, for example, will run middleware, some don't have the same performance benefits. Some of them, they're similar to this� they're sort of selfhosting option, except just in a serverless box without all that extra stuff we've done to ensure we're getting parity with Vercel, like performance.

JASON LENGSTORF: I burned, like, 10 minutes trying to figure out that Sanity thing and we're just about out of time so we don't have time to fullyimplement other features but let's talk through it. The way this is working right now is when we're deploying, we� because Netlify has access to the repo and everything, it can say, we know this is a Next site based on its dependencies and we're going to handle out build output and take advantage of the capabilities of Netlify's platform. If we were using Astro or Nuxt or any of the others, Quick, et cetera, Remix, that have adapter APIs, the adopter would tell the platform, put these files here so we take advantage of the CDN, the serverless functions, the static assets, et cetera. So, here, we're just kind of� we're building a third� like, an external adapter API for Next.js is what we're dealing with here.
But what's interesting about that to me, all the things we're using� you mentioned we're caching, but that's a caching layer, you mentioned cache tags and that's something that we can use with any framework. And then when we get to the image layer, one of the things I really love about the image layer, on Netlify� I've always used Cloudinary. They've been my goto for a long time because it's, like, here's an image. You can do whatever you need to. You can resize it, change the quality, et cetera, and it has zero idea or interest in knowing what even, like, programming language you're using. It's just URL. And I think that's a pretty� so that's how you're� is that how you're managing the Next.js imaging stuff?

ROB STANFORD: Exactly that. It's a very similar service.

JASON LENGSTORF: Any other lowlevel things that are worth calling out about how you're managing the feature parity and anything people should be aware of if they decide they're going to go roll this on their own. You would need Cloudinary if you don't have an image service built into your platform.

ROB STANFORD: The image CDN and the blob storage and advanced cache, they're primitives you can use on Netlify. I wouldn't suggest rolling your own Next.js runtime, but essentially what� what we're doing is we're utilizing those primitives in order to provide the functionality that Next.js� the framework leverages, I supposed. But what's really interesting is if you're using Astro, they don't have ISR or ondemand revalidation but there's nothing stopping you from building that. We have a guide for people interested in that. It's really interesting because you can have the same setup where you've got a page fetching data but you might not want that dynamicallyrendered on every request.
With Astro, you can do "astroresponse.headers" and add a header and it is netlifycdncachecontrol and instruct our cache to cache the response for maybe a week or over� or even for a year and you can do the same thing, you can create a route handler, a little bit like what we've done here in Next and use a Netlify purge cache API to purge that cache ondemand so you can set up a route where it accepts a webhook. When that request comes in, you can call Netlify's purge API and that request will make it through to the server and be rerendered. Just using the platform primitives that Netlify provides, which I think is really powerful because you can use that with other frameworks or even without a framework. You can use it with Netlify functions. We're trying to open up, essentially.

JASON LENGSTORF: I think that is very exciting to me and the� you know, again, betting on the web is� is great. It gives a framework authors to get really good performance on any platform through their adapter APIs and, you know, making Netlify the one that has, like, the easiesttouse primitives, if I was building a company� one of the reasons I joined Netlify, back in 2018, for the years I was there, because it seemed like instead of saying, "we want to control things." It was "we want to provide the best tools so people want to be here." Right. And I think� somebody asked� what was the question? Would the lack of support for Next make me think about choosing a different stack? One of the reasons I don't use Next� I don't advise to use Next for their projects and I wouldn't personally� I would argue strongly against it because the implication of the actions of the team is that they� they aren't interested in supporting other platforms. There's no action supports that will help you. To me, that is a sign that� it doesn't� you know, the early warnings, I usually trust my gut. If things get hard, it's going to get hard to use Next so that, to me, makes me not want to use it.
The reason I lean towards platforms like Netlify and why I like the concept of betting on the open web, why I'm such a big fan of, you know, get the defaults right and then let people succeed, is because it's� it's a fundamentally open. You can't control that. If you give somebody a primitive, you don't� you can't control that primitive. Anybody can implement it. That's the whole point of using web standards so by building things that are stacked on top of web standards in a very compliant way so anybody using any feature of the web can take advantage of them, the thing you're competing on is being good at it, not controlling. I want to work with the companies that are fighting to be good at things, not to control things. And with that, we're out of time. So, Rob, any parting words for everybody before we shut it down?

ROB STANFORD: Just the options are good. [Laughter].

JASON LENGSTORF: Options are very good. All right. So, I'm going to give one more shoutout to Rob's LinkedIn here, so make sure you go and make a new connection. I'll give a shoutout of Netlify. They are also the sponsors of the closed captions on the show and thank you to Vanessa, who has been doing the captioning today. Let me get the link there.
While you're checking out things on the internet, make sure you go and take a look at the schedule we've got coming up because it is going to be a whole lot of fun. Next week, I'm back on my Tuesday schedule. And then on Thursday, we've got Brandon to teach us about Analog.js, which is a really exciting thing about Angular. Make sure you mark your calendar.
Rob, thank you so much for spending some time with us today.

ROB STANFORD: Cool. Thanks for having me.

JASON LENGSTORF: Chat, thank you, all, for hanging out. We will see you next time. Take care.

Closed captioning and more are made possible by our sponsors: