Next.js Full Course for Beginners | Nextjs 13 Tutorial | 7 Hours

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello and welcome to over seven hours of next js13 tutorials and instruction this video is made up of 12 tutorials that build upon each other much like the chapters of a book throughout the lessons in the video I will mention links being available in the description below I've compiled all of these links into one GitHub resource that you will find in the description hi I'm Dave gray and I'm the creator of these next js13 tutorials you can subscribe to my YouTube channel for more tutorials like this one you can also follow me on Twitter and if you're feeling generous you can even buy me a cup of coffee hey guys as I publish this video nextjs is on version 13.4 and the app router is now stable I don't expect the fundamentals of this course to be outdated until next JS reaches version 14 which would mean breaking changes that said as I built this 12 chapter course over 12 weeks next JS went from version 13.1 1 to 13.4 and I discussed the changes as they are applied to the chapters don't worry if next JS is on version 13.8 or Point whatever if you're considering learning from this course because the fundamentals and Concepts learned here will still apply even if next JS changes how they are applied in a new release therefore I'm going to show you which version of next.js to install at the beginning of each chapter so your file tree matches mine Lesson by lesson also note that anytime I refer to the next JS beta documentation in these lessons it's now been replaced by the stable documentation for next JS with the now stable app router so just use the current documentation as provided on the next JS website let's get started learning next js13 with chapter 1. before we go any further in this tutorial I need to clarify what beginners means in the title of this next JS tutorial series it means you're a beginner with next Js but it does not mean you're an absolute beginner in web development these tutorials require that you already know HTML CSS JavaScript and react we'll also be using typescript and Tailwind CSS along the way I have full courses for all of these topics on my YouTube channel and I'll link to each one in the course resources if you don't have this prerequisite knowledge please work through those courses first and then come back to this one when you're ready that will help ensure your success with the prerequisite discussion out of the way the main question is why nextjs why do people use it well I asked chat GPT what are the benefits of using next JS and it said nexjs is a popular open source framework for building server-side rendered react applications now we'll get into what all of that means but let's quickly go down these bullet points server side rendering and that means next JS enables the server-side rendering of web pages which can improve move website performance by pre-rendering and that's a term that we will get into pre-rendering by pre-rendering pages and sending fully formed HTML to the browser number two is automatic code splitting so it splits the code into smaller chunks which makes it easier to load and more performant SEO optimization SEO stands for search engine optimization and next.js supports that server-side rendering and pre-rendering that we talked about and we're also going to talk about static site Generation all of those things really help it perform in search engines better than a traditional react app would faster development next.js includes many features that can speed up development it really has a great developer experience overall and that was the next bullet point and then built-in support for typescript which is definitely something that is required more and more often in the industry and then scalability next.js is built to handle large-scale application and that's because of features like automatic code splitting caching and support for serverless functions and of course it says overall next JS can help improve website performance streamline development and offer a better experience for both developers and end users so if we go down on the page for nextjs.org we can scroll down and we can see many companies are actually using next JS already and you can see all of these different brands scroll through that you may be familiar with many of them and if we go down a little bit further they even have a showcase here where it shows some of the many sites and applications built with nexjs so now let's revisit those terms pre-rendering static site generation server side rendering those are things we need to talk about as the benefits of next JS as we get into next JS and so it says by default next JS pre-renders every page and that means that next JS generates HTML for each page in advance instead of having it all done by client-side JavaScript and that's what react does react sends down this huge bundle of JavaScript while sometimes not so huge but a big bundle of JavaScript and then everything is rendered in the client which the client is the browser that's client side but pre-rendering does this on the server and it can result in not only better performance but better search engine optimization and then each generated HTML is associated with minimal JavaScript code instead of a large bundle only the code that is necessary for the page and then when the page is loaded by the browser the JavaScript code runs and makes the page interactive and that process is called hydration so let's quickly look at the two forms of pre-rendering and you'll hear more and more about these as we go but there's static generation which you'll also see referred to as SSG which stands for static site generation and then the HTML is generated at build time and will be reused on each request this is what's recommended it's the most efficient it's built on the server and then it can be sent out and we're going to talk about cdns as well which is a Content delivery Network and that's where the static generation becomes very useful the server side rendering is also very useful but it's not as recommended as the static site generation here the HTML is generated on each request it's still generated from the server not on the client side however both of these can be combined with client-side data fetching as well which lets us create a Hybrid next JS app and we can kind of have the best of both worlds when that happens so why is this static generation so important let's look at what is a CDN I'm on cloudflare now and I'll put this link in the course resources as well but they have a good definition here of how how does a CDN work again a Content delivery network is a network of servers linked together with the goal of delivering content as quickly cheaply reliably and securably at securably securely as possible and in order to improve speed and connectivity a CDN will place servers at exchange points between different networks so if we have generated our site statically our site can be cached at these different servers and ready to serve faster I'll scroll here where we can see this map which really tells us what's Happening Here we have this origin server right here but there's all of these CDN servers that are blue that we see here and the user just has to go to this CDN server so if we've cached our site out at these other servers they don't have to go all the way here and they get more performance essentially faster load times okay now that we've completed a quick discussion of the benefits of next JS and really what separates it from a traditional react application this react framework has many benefits for us let's go ahead and look at the documentation which they have great docs but let's see it has a link here that says see the new beta docs now this is an important note because next js13 was recently released and there's some major changes and so any previous next JS tutorials before next js13 they've changed things quite a bit so we want to look at the new beta docs and we can do that right here and one thing I like about the beta docs is dark mode it's identifying that I already have dark mode as a preference on my Windows computer and of course then it just provides dark mode already and I really do like that so the first thing that we need to have is node.js and it's not that you have to know node.js already but you do need it installed on your your system and it says node.js 16.8 or later well let's go ahead and check the node.js website currently they're on 18.14.0 for long-term support so you could download and install that if you don't have it already because you're going to need at least node.js version 16.8 or later you can see there is support for Mac OS windows and Linux as well so you should be fine there make sure you have no JS up to date your installation instructions for this chapter I am going to open a terminal window in vs code which I have open here and I can do that with control and the back tick and now I have a terminal window you could also do that from the terminal menu and then choose new terminal from here I'm going to type npx create Dash next Dash app and then it's going to be at and now I'm going to give a specific version of next JS and for the this lesson we're using version 13.1.6 and now press enter and this will go ahead and install next JS and it's going to ask us a few questions now I'm going to name mine after the chapters so for this version we're going to use it in next01 or also O2 so chapters 1 and 2 use this version so I'll just call it next01 and press enter we're going to use typescript we'll say yes to eslint we're not going to use the source directory for the first six chapters and then later on we will but the source directory is just a parent directory for the app directory that's the only difference it could make your code look a little bit neater but we want to see that full file tree for a while until until we're used to it so I'll press no here and then would we like to use the experimental app directory was it was experimental in version 13.1.6 of course it is now stable in version 13.4 and later and we'll get there later in this course but for now we're going to say yes we do want to use the experimental app directory and then we do want to use the import Alias so yes we want that configured just press enter this will go ahead and create the next app in a folder called whatever you named it as I did my next01 and now we've created our application and we have the directory here so what I really want to do we could CD into this here but I'm just going to close this and I'm going to go to the file menu and I'm going to open folder which would be Ctrl K control o as well and from there I'm going to open up this next series and there's our next01 open that and now we can see everything that was installed over here in the file tree let's quickly discuss what we see here of course there is a readme file and you could look to see what is provided in here that's just some directions like we have npm run Dev to go ahead and start our application if we want to do that it's going to be on localhost 3000 you could look at the other things here as well after that we have a package Json file now notice we have some scripts here we're interested in the dev script so we would type npm run Dev when we want to start our development environment the build and the start those are things that would be done on the server there's something for lint as well so we're only going to be using this one right here and you can see the dependencies that were automatically added for us here such as typescript and next and eslint all of those things okay after that package Dash lock Json that's something you have probably seen before in react as well then there is a next config file and we'll get into that in the future there is also an eslint Json file and you can see it's already got something in that and we can close out of that too there's the tsconfig.json you should have seen this before if you've used typescript before so nothing really new there but there the file is so we've got a lot of config files now let's talk about the public directory oh and I did skip over the get ignore file and that's of course with Git any file that you want to ignore and some are already listed in here and then there is a grayed out file and that's a file that you should not change and it says note this file should not be edited so do not edit the next Dash env.d.ts file we'll just leave that one alone the public directory though this is where some images are some svgs and an icon file this is where we would put any static resources that we would want and images are a good example of that after that there is a Pages directory and inside of pages is an API folder and inside the API folder is a hello TS file now this would be when we want to request some data and we'll definitely get into this in the future we're not going to right away though but this is the area that we would be using those requests in right there okay then we have our node modules folder which you should be familiar with and then the new app directory and this is where we see our basic Pages now I know this can be confusing because we have a Pages directory but I said it's more for the API here here is where we have the basic page not an index dot TSX and that's what we're using here for typescript TSX files but this is the basic page that we'll see once we start our application and then there is some CSS here in a module page.module.css there's also some Global CSS that we have right here and then there is a head.tsx notice it has some meta content in it and we'll discuss how those work with Pages as well and there is a layout.tsx now this is important to note that next JS supports routing which we'll be covering very soon so with the react app maybe you've used react router before you won't have to do that with next JS it's already built in so let's go ahead and open a terminal window once again and I'm going to type npm run Dev and we'll start our basic application you can see it starting up and I'm just going to say allow for now and let that go by and then after we've started it up we see all of this information here in the terminal but here is the URL we want so you can press control and then just click to follow that click and it's going to launch that in Chrome and here we have our basic page over here so I could drag this to the left or we could look at this in full screen if we wanted to and I think I will so here we have the full page that has started and this was that page.tsx that we saw inside of the app directory now as cool as this looks let's go ahead and make some changes so I'll drag this back to the right and let's take this back to full screen I'll close the terminal window it will continue to run but let's just get rid of everything that we have here so I'll select everything between the main elements in the jsx returned and we'll delete that and after that I'm just going to put in an H1 and say hello world put that right there and then after that I want to go ahead and drag this once again over here to the left and then for next JS here let me see if I can open the console window so we can see well that doesn't look too great maybe I could dock it somewhere else like at the bottom and then bring this down okay so we we're definitely going to change the page here we can't see a whole lot of it but what I want you to see and I'm going to hide the file tree too I haven't saved this file yet when I save this file you should see that our Dev environment reloads the page quickly I'll save and then we see fast refresh rebuilding and there we have it so when we change our files and our Dev servers running everything updates immediately and now we have our hello world page instead of what we previously had and it happens that fast but you will get this message in here from the hot reloader client as it says okay so you've learned more about what next JS is and why companies are using it and you've learned how to start the basic next JS Dev environment and get your first app going in the next tutorial we'll be looking at pages and layout in the previous lesson we learned how to start a next JS project and we reviewed all of the files you get when you do today we'll dig deeper and look at how we can construct pages and layouts in the new Next js13 app directory and we'll also look at some basic routing links and more so you can see I've got Visual Studio code here on the left and our starter code is the completed code from lesson one which is essentially the starter project that you get after you install next JS but we change the contents of the page of course the default page and if you remember that's in the new app directory for next js13 and here's that page so I'm going to take this and just bring this back to the full page so we can see the code for now and we'll come back to the browser in just a little bit so now in this app directory let's create a directory inside of it and let's call this about and we'll do that with lowercase and now inside of the about directory let's create another page dot TSX file and now I'm going to type RFC for react functional component and you see that choice right here now I'm going to select that that's not part of next JS that is an es7 react Snippets extension that I use and I can provide a link to that in the course resources but you can go to your extensions over here and I'm just going to search for es7 so I can pull this up and let me find the correct one it is right here it says es7 plus react slash Redux slash react native and this is the one I have installed you can see over 7 million downloads and it's very good with those Snippets so you can type those abbreviations and complete those functional components easily again I'll link to this in the course resources as well but you can find it with your extension search okay back to the project I'll close this out we have got our basic functional component for page but I'm going to go ahead and make this a capital P for page and actually we could name it about with a capital A because if we look back at the page file we have here notice they didn't name this page either it's named home so you really want to name the component or the functional component what it is like about however the page itself is named page.tsx I'll go ahead and save the page now this is how basic routing and basic pages are created in next JS so when you want to have a different page that you could link to or navigate to you want to create a directory for that page now let's pull this back over as we look at our page here and you can see I'm just returning a div that says page inside we would go to localhost 3000 and then navigate to slash about and I'll press enter and now it's very small but we have the word page up here at the top so we're going to want to change what we have in here maybe make it a little bit bigger maybe even apply just a little bit of CSS but we know we do have a second page now and we can navigate to it with Slash about I'm just going to click the back button and we go back to the home page also okay bringing this back over just to view the code I'm going to make one simple change here and that is to turn this div into an H1 so it's a little bit bigger and easier to see and then I'm going to turn the word page into about so we know we're on the about page just a couple of simple things before I save that page again now let's look at the layout file that's back here in the parent app directory and for this layout this applies to the entire site or the entire application so anything we would put here would be on every other page as well so for example we could put in a nav bar and I'm going to do that right now not by creating a separate component but just inside the body here and realize the body is returning all of the children here and that would be all of the child components inside of the application but then we could have a component above that that we defined so if I created a nav bar in a separate component I could import that and that would work as well but for now I'm just going to use the nav element and then inside of the nav element I'll put an H1 and I'll just say my nav bar and save now I'll pull this back over once again so we can look at the application and see we have a nav bar here at the top in hello world but if I go ahead and click forward and go to the about page we also have that nav bar on the about page so this parent layout applies to all the pages on the website once again dragging Visual Studio code over for a full page view I want to create a layout now that will only apply to anything in the about tree so this means it would only plot apply to any pages that started with the slash about and of course you could have sub directories and other pages that fall follow that path so you could have a sub page or directory in the about directory here so we're going to create a layout file inside of the about directory so I'll click the new file icon and I'll type layout.tsx from there I can type RFC but it's not going to have the name layout so let's look back at what we were given from our starter files and we can see this was named root layout or root layout you've got my accent in there when I say the word root and then we have a return I'm going to copy this much and we'll return something different but we need the same types and we'll need to change the name so I'm copying from the beginning of root layout and going down to the return with the parentheses so Ctrl C there let's go back to our about layout and right here I'll start with the name layout and I'll go to whoa I did not mean to do that control Z to undo okay copy here and just to the beginning of the return paste that in now I'm going to change this to about layout we're going to use the same types so that's why I just copied that now here our return is going to be different notice in the return of the parent directory for app that layout it has the HTML tag you only want one of those per page and really per site because this applies to everything remember so anything now anything we have below is considered a child and it's right here in our HTML structure so back in this layout then I could just start with a fraction let me remove what we have I don't have a fragment I said fraction I mean a fragment there now I'll put a nav element and I'll call this the about nav bar and after this nav element let's go ahead and put a main element inside the main element is where we'll put the children for this about layout and we'll go ahead and save that file and now when I drag this back to the left we're still looking at the hello world page here our very beginning page so let's go to slash about and now we have the nav bar that applies to the entire site then we have the about nav bar under that and then we have the word about right there now I can use the forward and back buttons to navigate but let's go ahead and add some links to our pages to navigate between the two as well so I'll come back to full screen for visual studio code let's go to the page inside of the about directory and we'll add a link there first and so at the top of the page I need to in import link and if you're familiar with react router this is a lot like using react router when we import a link there from that Library oops this is not what I wanted there either so I want to just start with import link and it comes from next slash link and then after I do that I'm going to add a fragment here and put my H1 inside of that fragment so add the extra line there and then I'm going to put the link here so it's going to say link with a capital l and then we're going to have an href and I'm just going to link this back to the home page so that's just the slash for the root directory and then we'll have link to home page just for the text and I'll get rid of this extra line here when I save I should get a little bit better formatting and there are Pages complete let's see if that link has been added so we need to go forward to our about and there it says link to home page and yes we get a pointer with our cursor when I click that we go back to the home page so now let's do the same for the home page and we'll come back to the page in the app directory not the about directory and here we can import link as well so I'll import link from next slash link and then inside of this page just underneath the hello world I'll put link and press tab that's fine I closed it out but I need the href set this equal to slash about then inside of this I am going to type go to about page and save we'll drag back over and see what we've got now we have go to about page now just because of the default CSS that we didn't change from the starter project our link that says go to about Pages way down here at the bottom but we can go ahead and click that then it takes us to the about page that has the site nav bar it has the about nav bar it has the H1 that says about and link to home page so we can go back and forth now with links rather than using our back and forward buttons from the browser so I just mentioned CSS is the reason this about link is down here let's change that and briefly look at how some CSS is currently applied in this starter project right now this styles.main that we see here is applying that beginning CSS so we can go ahead and remove that and let's see if we actually want anything else there for Styles I don't think we do so we can just remove that class name all together and if we save that's definitely going to change what is applied guide in the home page but we can see what that starter project did and that is import styles from page.module.css so it made some Styles inside of this module some CSS Styles specifically for this page and then there are globals that'll apply to the entire site we could also create some styles that applied just to the layout for a specific level or path in the directory tree like our about path here so now in the about directory let's create a new file and we'll call this styles.module.css we're creating a CSS module and I'm just going to create a class here called Main and then inside of this main class we'll have a Min height of 100 viewport units and display let's go with grid so we can just Center everything easily with a place content Center and after that what did I miss here oh I've got a comma instead of a semicolon there and after that we need a background color that will not be too bright so let's go with a different dark color like this one right here okay just a simple class here inside of our module and let's apply this to the layout so any page any component in the about path so the about page but also any children would receive these Styles and to do this we need to import Styles at the top so we'll say import styles from dot slash styles.module.css and then after we've imported those we just need to apply those and I'll do that here with this main element I'll say class name equals and then Styles dot main now the nice thing about these modules is you could have a main class with the same name inside of the page dot module and then you could have essentially the same name at two levels but they're not applied the same because they're just applied to the component in that class however you would have to be careful if you were using globals and applied those but just to show what I mean and I believe I removed the main class just previously from this module there is a class named Main in here so let's put it back and we had it on the main element here so I'll say class name equals and we'll go back and use the Styles dot main here that are imported from page.module.css here at this parent level and we will still not have a problem using a class name of main here at the about level now I need to save this file so I'll do that now let's go ahead and see what was applied so if we look at our home page and I'll just refresh to make sure but we've got the link down here again because I applied that main class in the app directory parent but if we go then and I'll go to this link and go to the next page we have applied our main class here that is entirely different it has a color it's centered our H1 and our link together unlike the other main class that applied to the parent so you can see how the module CSS works and applies only to that level or that page so this is at the page level when we have page.module.css us we import that and applied it just to that page now we did this differently for the about we applied it to the layout so this would apply essentially to all children that we have right here as well because the children are nested inside of this main element that got the class so just so you understand the different levels we're talking about page level or we're talking about layout path level or of course you go to the very top and you have Global level that applies to all I'll go back to the home page and now I'll remove that main class and we can see the difference here as well so I'm going to quickly Ctrl B to hide that file tree let's just remove this style right here from the main page and now everything shifts to the top because those styles are no longer applied to our parent page we are back in the beta.nextjs.org docs and we're of course learning next js13 and this this is a rapidly moving environment and there are changes we've got a note here as we moved on to the Head section of pages and we're looking at SEO and metadata now the head JS file that I'm going to cover because it currently works with the code we have but it is already deprecated as they move forward and so this is why you have to constantly refer back to docs and check everything so let's look at what we would do for metadata in the near future so they're saying in the near future with 13.2 and I believe I'm on 13.1.6 right now but in the very near future you will import the type metadata that you could use in your page.tsx file and then you can create your metadata here and they go over a lot of information about what you can provide as metadata and so it would be right within the same file but currently what I'm going to show you to work with the current code that you've downloaded I'm going to show you the head JS file now if you're watching this several months in the future from when I've created this this would probably be the way to do this and this is why I'm showing it first because the head file is going to be deprecated so just know this is the future for the metadata instead of the head.js or in our case head.tsx File that we're about to create let's bring Visual Studio code back over to the full screen and we will go to the file tree now I just said that the head file is deprecated so moving forward remember what is covered in the docs and always reference back to that however it's currently still in use up until 13.2 and you can see what we're on if you look at package.json and we'll see what next we have we have 13.1.6 as I make this video you might have a newer version if your version is 13.2 or later you should refer to the docs that I already pointed you towards okay so for what we currently have if we look at this layout let's first look at the note here that's included and I'm going to press alt Z so this wraps down there's a note about this head component here and you can see this right here within the layout and essentially if we create a head file like we create one inside of the about directory well then it will apply it it's whatever is the nearest so if I wanted to put metadata in there for the about page I'd create a head.tsx file in here and that's what I'm going to do you can see there's one here for the home page and we just want to essentially mirror what this content is and so what I'm going to do is come up here to the about directory create a new file name it head.tsx then inside of this file I'll do RFC first and press Tab and I've got my head component I'm going to make this a capital H there for head though after that I'm just going to change what's inside I'm not going to spend much time on this because is again it's already changing but it currently works for what we have so you can see what I put and I just based this off of the one that they gave us already in the Parent Directory so you could put in your title you're not going to change this line at all this is for your responsive design that you need the meta content and then the description of course you could change and we're referencing an icon here for it and that Icon by the way is in that public directory here so notice there's no dot before the slash we're just referencing that public directory so that's it for the head file let's drag this over quickly and if we look at our about page now we should be able to see a new title at the top and I refreshed it and now we have about page here at the top and if we were to inspect we could see that meta information that's inside of the head that doesn't appear on the page okay now let's move on to something that is not currently deprecated but we can add more files here that some you don't even see that weren't provided with the starter project but they can really help the project out and one of those is a loading state so once again in the about directory let's create a new file and we just name this loading all lowercase dot TSX now inside of this I'll type RFC and we'll get our loading functional component I'll once again make that a capital l for the name of the component there and then we are returning a loading state so instead of what is currently being returned I'm going to put a H1 and inside of this I'll just say loading now I do have a tutorial on how to create skeleton components in react applications and that would apply here as well so you could easily create some skeleton components and use those for loading the pages that next JS loads by default when you create this file and the great part is is next JS applies react suspense under the hood really so we will probably be able to briefly see this loading message when we navigate between those two pages so let me drag this over and let's see if we can see our loading State I'll go to the home page first and remember it doesn't have a loading state but now let's go to the about page see if you quickly see the loading message we did just briefly I'll do that one more time so we go back go to the about page loading and then of course there's the about page now I also have a tutorial on my YouTube channel about react suspense and react suspense requires the use of error boundaries and so that's also really recommended those are also supported in next.js and they're very easy to apply so let's go ahead and look at the page in the docs first that show how to do this and you don't need to create anything that's really new here you just need to go ahead and apply what they show so here we have error.tsx then you can see how this is applied now you see this used client here which means this will be some client-side logic so what we're going to do is copy this and you can see basically the component that we want to show when we catch an error inside of that error boundary and we'll just say something went wrong and then we'll have a function that can be called when this button is clicked and it would be an attempt to recover say possibly some state made an error happen something so we might be able to recover if we click that reset button but the other nice thing about the error boundary is it doesn't crash the rest of the application so even if I create an error on purpose in the about area of the page our home page would still be working as well as other paths for our application if we created other paths so I'm going to scroll to the top of this and I'm just going to start copying everything I'll scroll down to the bottom hold down the shift key and click and it looks like I've got a little more than I want so I'll just delete that in a minute but just Ctrl C to copy everything go back to our about page here drag this over to the right and now Go full screen with the code and I need to create that error dot TSX and notice I'm doing this inside of the about directory I'm just going to paste all of that code in here now I'll delete the word how but now we have our error boundary component and by creating this error.tsx next JS applies it automatically so all I need to do is save after getting that code out of the docs I could alt Z just so we could see anything that wraps or that was extended off the screen but now that I've done that we won't see this error at all unless I throw an error on purpose right now because we have a very simple page so I'm going to go into our page.tsx that's inside of the about directory and just throw an error on purpose and I'll do it before the return so I'll say Throw new here I'll just say not today save that now let's go back to our page and we've already got the error page here and of course here in Dev mode even we're getting this one error notification down here but this is what a user would see something went wrong and they'll get the try again button now try again won't help us in this case there's no state to reset or anything like that but at least it gives the option to try however we can go back to the home page and everything should be fine of course we're still seeing the error down here from our Dev mode if I reload we don't have an error now until we go to the about page and our error boundary catches the issue so that's great we can apply react suspense and loading States and we can apply error boundaries easily just by creating a couple of files inside of the directory where we need those before we wrap up I just want to comment out this throw new error but I'll leave it in the code just in case you want to experiment with that yourself elf and we have much more about next JS coming up in future lessons next.js just released 13.2 and as I discussed in the previous lesson the metadata was changing and we see this now with built-in SEO support so we'll quickly cover those changes and then we'll get started with data fetching fundamentals I've got new installation instructions for chapters three and four we want to type npx create Dash next Dash app and then at version 13.2.3 and we're going to use this version for both chapters 3 and 4. we say yes okay to proceed we want to name this I'm going to name this next03 of course it also applies for chapter four when you create that one after that we do want to use typescript yes to eslint no right now to the source directory that will become later once again we will use the app directory so choose yes there and press enter to go ahead and use those import aliases all right I'm in my next O3 folder and if we look over here to the left in the file tree the individual files that we see there's eight of those and those are the same as before when we started a project however you'll notice there are fewer folders there's no longer a Pages directory at all everything is now in the app directory including that API folder that was in the Pages directory and I've had several people ask questions about the API folder right now it has a hello folder and the new route TS file we may eventually get to that but of course that's about an API and right now we're building pages in a website with next.js and that falls under the app directory but it follows the page and layout model that we covered in the previous lesson what I really want to highlight is what I said was changing in lesson two and that is the metadata and I showed how they were going to do it and now you see it is already added to the layout file in the top app directory here we have metadata right here now this is static metadata and we'll learn how to add Dynamic metadata later as well right now the so we're using typescript and if we Mouse over this I can see well I should be able to see what type we have there we go and you can see it's an object with the title and description string and that's all it is you could let typescript infer that or now you can go ahead and import the metadata type so I'm going to show you how to do that with import type and then we can say metadata and this is going to come from next and after that you can actually use the metadata type right here if you want to so there's metadata and now if I Mouse over this we should be able to see just a little bit more information it's the interface metadata type you could actually click and look at the definition of that as well but it's going to give all of the different possibilities that you could put in your metadata object so again just to note this replaces the head components that we were adding like head.tsx that no longer exists over here and there's no reason to create it it's no longer supported that is deprecated and we're now using an export of metadata to create the metadata for a full layout this would add this to the full branch and all child branches or you can add this statically to any page that you want to statically create that with and once again I will go over how to generate the dynamic metadata if we're generating Pages dynamically now before we start with data fetching there's just a little bit of setup I want to do so one of the things do I want to do is pull the font that the page actually has here I'm going to just copy these three lines I guess four lines two through five right here I'm going to just Ctrl C go back to the layout and now here at the top I'm going to paste those in I'm going to remove the Styles one I just really needed the font ones because this is pulling a Google font in and I haven't really covered how to do that yet but this is exactly what it's doing it's pulling in this enter font from Google and then we need this next line with the subset as well and then back here in the page TS we can see how they apply that also I may need to quickly control F just to search for the word enter and here you can see it applied to the H2 it has class name and then it's enter.class name and I'm going to pull that over Ctrl C that line as well or just that piece of it and go back to the layout and I'm going to apply that to the body just because I want to use that font on everything from and now I want to go back to the root page and as nice as their default rip page looks I want to go ahead and remove just about everything for now and make it very simple for us to work with today so selecting everything between the main elements and I'm just going to put in a couple of extra things here so an H1 that says home page so we know when we're back at the home page for sure and then a paragraph and inside the paragraph I'm going to use a link so we need to import link and we're not using image anymore so up here we can import link and we did this in a previous lesson as well and this link is going to come from next slash link and then here we can use that link put link put the href equal to and we're going to create a user's Branch so we'll go ahead and indicate that and I'll just put users here of course it's not going to work right now we'll need to create that branch and finally while we're not focused on CSS today I'm just going to go into the global CSS us and scroll down here where they have the body area and I'm just going to add some padding to the body overall so it will move everything away from the edge just by one rim and that's good now our initial setup is complete and we're ready to move on to data fetching fundamentals we're now back in the next JS docs and we're at data fetching fundamentals and there are four recommendations that I want to go over because we're going to come back and refer to these as we write our code so the first recommendation is to fetch the data on the server using server components that's a big part of the power of next JS we're going to create these things in advance rather than on the client so we're going to use server components the second thing is to fetch data in parallel that minimizes waterfalls and waterfalls would be fetching one type of data waiting for that and then fetching the next type of data waiting for that and then doing something else so step by step where in parallel you can fetch the data that you need at the same time so one isn't waiting on the other of course course this reduces loading times recommendation 3 for layouts and Pages fetch data where it's used so you may see the same fetch request more than once and that's okay because next JS will automatically dedupe that means deduplicate those requests in a tree so it's going to just request it once even though you might see that request in there more than once so if it's already requested it's going to use that information that it has it's not going to send duplicate requests and recommendation 4 is to use the loading UI which remember we went over the loading.tsx pages you could create to indicate loading for a specific Branch or even a leaf which would be an individual page if you put a loading page in that area however there's also streaming and suspense and if you know what react suspense is that means we can break apart a page load part of the page and then add suspense while the rest of the page loads so that also improves the experience and it progressively renders a page to show the result to the user while the rest of the content loads so these four things we want to keep in mind as we create our code with data fetching okay we're back in Visual Studio code and we're ready to create our users Branch so I'm just going to create a new folder here in the app directory and I'm going to call this users now inside of the users directory I need to create a page.tsx now the first thing I'm going to do here is import the type that we saw before and that is metadata because I'm going to use it as we add the metadata for this page it will just be static metadata like we've already covered so we'll start with our export const then I'll say metadata and the type is metadata then let's set this equal to an object and I'm just going to set the title here and it's going to be users now below this I'm going to use my es7 Snippets extension and just type RFC to quickly create a functional component let's rename this component even though it is page.tsx we don't have to name the function that I should say that the file is named page.tsx but the functional component inside the file does not have to have that name so I'm going to call this user's page and now the first thing I'm going to want to do inside this component is actually request the users and so to do that I'm going to need to create a library function I don't want to keep that just in here like I've seen others of course just Define a function inside of the same file you can do that however I want to organize my code and possibly be able to reuse that same function again and again without typing it again and again so I'm going to create a library outside of the app directory so just in the top Parent Directory I'll create a new folder and I'll call it lib and then inside of this we can create our function that we export so a new file here and I'm going to call this get all users.tsx I'll once again start with RFC and just press tab now we have export default function but this is also going to be an async function so I want to add that word at the top as well and now we're going to fetch some data from a website called Json placeholder I've used that in several other tutorials and so some of you may be familiar with that but let's go ahead and create the fetch here so I'll start off with const I'll just say response equals await and fetch and now really it would be handy if I could just paste this URL in so I think we should go to the website and I will just get the URL from the browser we're here at the Json placeholder website and you can see in the URL bar it's jsonplaceholder.typeecode.com and from there it offers resources I'm just going to click on this slash user's link and it provides 10 users and here we'll see the data that comes up this is just Json data I'm just going to copy this URL out of here to use back in our code now we're also going to come back here and grab one of these objects to create a type for this data as well but first let's just go back to our function and create that all right I'm going to paste in that URL into our Fetch and I'm going to press alt Z so it wraps any code that would extend down to the next line now after that we just need to check to see if we got a good response or not if we received a good response so I'll say if and then res is not okay so res dot ok but it's got the exclamation in front of it which means not and we're going to throw a new error and I'll just say failed to fetch data that works and then after that we're not returning a div with get all users we're actually going to return the response dot Json right there let's bring this down line it up well see if it lines up after I save there we go so that's our basic function for get all users worth noting that I did not put a try catch in here because we're going to use error boundaries if we were creating a project and of course that would catch the error and we would get that response from the error boundary which gives a component allowing the user to try again and we covered that in the previous lesson as well let's go back to our page in the users branch and now we're going to import that function so we will import get all users from our library and you can see how it uses that now has the at symbol slash lib slash get all users and now once we've imported that we can actually get that request going this is our server component so it's going to request this as it builds the website so it will not be requesting it as a request this will be a static page it requests this during the build and so we're going to say const users data and now this would be a promise and we need to put the type in there and we don't have the type yet so we'll need to create that then it will be git all users so we should grab that type I'm back at our data here on the Json placeholder website and I'm just going to grab one of the users objects here in the Json data and we're going to create our type from that so I'm just copying all of that and then we're going to come back to visual studio code okay we're back in vs code and notice this next Dash enb.d.ts well this is a type definition file right here so we can create a file like this so I'll just highlight this for a moment and we're not going to create anything like you see inside this file but we're going to name it with this same pattern because if we look at our typescript config file it wants to include this file that I just highlighted but also any other file that starts out with this pattern and so we're going to use that same type of pattern so typescript picks up on the file so I'll create a new file here I'll just call it types dot d dot TS and you can see I'm using vs code icons it gets the TS icon over here we can put in definitions so to Define our type user I'm going to say type user then set this equal to an object but I've got this object to paste in now of course I'm not going to use these literal values here I'm going to change these based on the data type but I won't have you wait around and watch me do that okay I've converted everything over now so you can see most everything's a string here and we start with an ID that's a number so I'm just going to save this type now typescript will pick up on this we don't need the word export here or anything else but we'll be able to pull this into our file so This Promise is going to return a user type and then it's going to be an array of users actually and so now we've added our type there but we're not quite finished because what happens is we start requesting that data right away but notice I'm not using the await keyword and then we'll have cost users equals a weight users data and of course for a weight to work we need to add the keyword async above here for our component as well now let's finish out our page but one thing we need to do is import link once again so I'm going to say import link and that comes from next slash link now that we have that I'll go ahead and finish out the page I'm going to Define some content right here and map over what we expect to receive so I have const content set this equal to I'll use parentheses I'm going to start with a section element so we have a parent element for the entire thing now let's put an H2 here and inside the H2 I'm going to use that link and the link is going to link back to home essentially back to our home page and inside of that I'll just put back to home so that's at the top and now we need to map over our data let me put one line break in there as well so our headers separated just a little bit because I'm not really using any extra CSS here today now inside of this we're going to map over the users and with that map I'll say for each user and inside of this we're going to return because we're down to the next line and I've got I've started a new block scope so we need to use the return statement there and then inside of that I'll once again use parentheses I'll create a fragment here and inside the fragment I'll say paragraph This paragraph is going to need our key though as we map over and let's give that the user.id and then inside of the paragraph we'll once again create a link and inside the link we need to link this to our users so these will be dynamic Pages this href is going to receive some value here let's see what we get we'll have a template literal and it will go to users slash and now I'm going to provide user dot ID and then inside of the link itself what we're linking to Let's link to the user.name which would make more sense than somebody looking at the ID I'm going to press alt Z again so that wraps down then after the paragraph I'm going to go ahead and add one more line break just to separate those so I'm not getting back into any CSS for now and then at the very end here instead of returning this div with the page we're just going to return the content we defined above and so now our users page component should be complete and I almost forgot one other thing I want to add just to demonstrate how this is working with a server component is I'm going to add a console.log statement here and just say hello so we can see where this appears as well with this much complete let's go ahead and open a terminal window we can type npm run Dev just to begin running the program in Dev mode and you can see that we are now at localhost 3000 and I can just control click on this link and it should launch the web page in the browse might take a second to get going yep we see the home page and the link to the users is way down here because we still have some of those Styles applied but if I pull this over to the right maybe I can close the terminal or a few things here in vs code and I could see both at the same time I think if we go to the layout I believe no maybe it's the page here itself and I'll go ahead and hide the file tree I could just remove this main class name styles.main part here of the main element and save and now it should remove that and so now our home page title and our users link is right here at the top let me go ahead and bring this over to the full screen but then I want to go ahead and open up Dev tools and notice we're at the network tab in Dev tools I'll clear this out let me reload everything and we're in Dev mode so it's going to load several things I wonder if I could make this any taller but it doesn't look like it but it loads quite a few things here in Dev mode because that will be different than you would see with a build let's clear this out and now when I Mouse over the user's link you see requests happen immediately so it goes ahead and starts pre-fetching that before we've even clicked on it I haven't clicked on it yet okay once I do we should get our data and yes we see all the users names and notice as I moused over I did the first three it tried to request those pages now we haven't actually built the pages yet so we're getting errors for now but if I Mouse over another one for example there we see it for number six as well so it tries to get that data in advance of course we can go ahead and handle these errors and anything that would occur that way but what we should do is just go ahead and create those Dynamic Pages we're back in vs code and now we're going to create a dynamic route that's something we did not previously do when we learned about pages and layouts so let's do that now it's going to be inside of the user's Branch now let's create a new directory and we'll put this in Brackets and now we need to name this whatever we're going to name the parameter the prop that we are passing to our component that is dynamically generated so I'm going to name this user ID because that is what we'll be getting from the param in the URL so now I'll press enter and we have that inside of this let's create a page dot TSX and inside of the page.tsx we're going to create a functional component here so RFC with my es7 Snippets and we'll go ahead and rename this as well and this is going to be for individual users so I'll name this user page so above our functional component I'm going to need to create a type for the params that we're going to receive so I'll just say type params I'm going to set this equal to an object that has params then inside of that it's going to have the user ID which your parameters from your url are always strings so that will be a string here now we can specify that inside of our functional component so we start off with params and then inside of that we're going to receive the user ID and now we need to provide the type so we come out here outside of both of those curly brackets and we'll provide params there so this component is going to fetch data in parallel like the recommendations that we previously went over let's quickly go back and look at those docs now we started our first users component by fetching data on the server and that's what we want to do and this next component is also a server component and we're going to need more data from two different API endpoints and so we're going to fetch data in parallel and not create a waterfall so now back in vs code we need to go ahead and create a couple more functions inside of our lib directory here our library so let's start I'll just highlight the first one and create a new file and we'll just call this get user instead of getting all users we're just going to fetch the data for one user and once again I'll start with RFC and press Tab and then I need to add the async keyword here for our function after that let's go ahead and put in our request so it's going to be const res once again set this equal to a weight fetch and we'll need to get the URL from Json placeholder again let's go ahead and finish out the rest first so I'll say once again if res is not okay then we're going to throw a new error and now we can just say something like failed to fetch user and then after that we need to return the Json once again so we'll say earn res dot Json and we'll add an extra line there and save that's our basic function so now let's just put in the URL to get the specific user we need okay back at the Json placeholder website we can see the resources here and the slash users gave us all 10 users but if we go down and look at routes you can see the example they give if you just put posts one which would be the ID afterwards you would just get the post with the ID of one so we could do the same with users and we could just put an ID after it for one for example and that should give us the user so let's try this out inside our browser and yes that gives us just the user so we can just replace that one with Dynamic data in the URL back in Visual Studio code we now know this needs to be a template literal so I'll remove those single quotes and put in back ticks instead paste in the URL that we just received alt Z to wrap that down and we can see the number one here that's what we want to replace with a template literal so here we're going to provide the user ID and that means our function needs to receive the user ID above we already determined that's going to be a string type now we also need to create git user posts so we need all the posts from an individual user I'm just going to copy everything in this file Ctrl a to highlight all control C to copy now I'm going to create this new file over here and call this one get user host.tsx inside of this file I'll paste in what I just copied but we'll change the name here to get user post it's once again going to receive the user ID alt Z to wrap everything down now it is going to have a different URL but without going back to look at Json placeholder again I can just tell you what the URL will be instead of users here it's going to be posts so we're looking at the posts and then we need to pass the param that says what the user ID is you can do that at with a question mark and then we're going to have user ID equals and then we'll of course have our user ID value and with that created you now know we need to get the post type as well once again I'll do it the same way that I did before for the user go to Json placeholder copy one of the posts and then of course turn that object into a type without having you watch that full process I'll just scroll down here to the types.d.ts and I can paste in the type that I have previously created but you know how I did it the same way as I did with the previous one so we just have a post here with the user ID that is a number which will come into play an ID that's a number and then a title and body that are strings let's go back to our page that we are creating here the individual user ID page that is being created and we need to fetch this data in parallel now that we have created those functions so at the top we should import both of those functions so we will need git user and we also need to import git user posts now that we have those let's request that data in parallel as recommended by nextjs we'll start by defining the user data and this will be a promise and we're just receiving an individual user back notice we're not going to use the await keyword here we'll just say get user so it starts the request right away and we'll have an ID however we do need to make this an async function as well because we will eventually await something after that we need to go ahead and create our users posts data as well so let's say user our user just individual user hosts plural data there we go and this will be a promise and it's going to receive back an array of posts so that is our type and we'll set this equal to git user posts and of course we need to pass in the user ID here as well and I noticed this extending off the screen so I'm going to press alt Z just to bring this down now our emphasis here is that we are requesting this data in parallel notice we're not using the await keyword on either one of these requests we just say start both of these requests but then after that one way to do this is to use promise.all so then we could say const and we would be receiving a user and we would be receiving posts or user posts we could name it that be clear and then we could await and we would say promise dot all and then inside of this we first have parentheses then we have our user data and our user hosts data and we could let this then resolve in parallel and we are waiting until we have the data from both but we start the requests at the same time we're not creating a waterfall where we wait on one after the other so then we can complete the component here with the return statement and I'll just change what we currently have there instead I'll use parentheses and then a fragment and inside the fragment I'm going to first have an H2 and inside the H2 we could use the user name and then after that we would say have a different component that we haven't created yet let me create a another line break here but then let's go ahead and put in a component called user posts again has not been created yet so we won't like what we see here with a red squiggly but we'll eventually create the component and we'll set the posts equal to the user posts that we got back then after that we would just go ahead and give the slash because this would retrieve all the posts for that specific user now this approach does work especially after we create the component we need and it is documented in the docs however the recommendation number four actually gives us something that will improve this approach if we look at recommendation number four back here in data fetching fundamentals it says we can use loading UI streaming and suspense to progressively render a page and we could incrementally show results to the user while the rest of the content loads so let's do that with our component so the approach we will take here is to load the user and will show the username but then we could use suspense we could wrap our user posts in suspense so we could actually show the username while we're still waiting on the posts and to do that I need to import suspense at the top so we'll import suspense from react and now we can use that in our component and we'll also be changing our promise all approach but first let's just apply suspense down here inside of the component and so inside of the component now after our break I'm just going to put in suspense and then we'll go ahead and of course take the closing suspense and put it after the user post component and then inside of suspense we need a fallback and I'll just provide a simple one here fallback equals and here I'm going to put another H2 and I'll just say loading so that's our simple fallback for the suspense but now inside of users posts we're going to change what we're sending here and we're going to change our approach above so instead of This Promise all which I'll just comment out to leave inside of the resources for the lesson in case you want to refer back to that because it is a valid approach that's documented but so is the one that I'm about to use that follows the recommendation number four and this will be getting our user here we'll just await user data but now we still have a promise for the user post data and that's what we're going to pass down so let's switch this to promise and here this would be the user post data that we're sending down into the user posts component so let's go ahead and create our user post component and to do that I'm going to create a components directory here inside of our route we'll put components and then inside of this components directory we'll go ahead and create a component as we would normally name it I'm just going to name it user post.tsx now this components route is not available to the public because it doesn't have a page.tsx inside of this directory and that's the way we want to leave this here I'm going to start by typing props again so I'll have type I want props I'm going to set this equal to promise that is being sent down and it is a promise it is a post well it's an array of posts there we go then after we have our type here let's go ahead and create our function so RFC and now this is going to be an async function as well because we need to await our promise that we're receiving and so then inside of our props here we'll see that we have a promise and the type is just going to be the props we created before okay now that we're receiving that promise let's go ahead and get our post first thing so we'll say cost posts this is going to equal await that promise that we receive then let's define some content so I'll say content set this equal to hosts.ap over each post and then inside of our map function we will return now I'm going to create an article and this article is going to have a key and that needs to be the post ID as we map over then after that inside of the article we can just use what we want from the post so I'll create another H2 here we'll make a post whoops I need this inside of curly braces post dot title after the H2 I'm going to create a paragraph for the post body and then let me put one more line break in because we're not really styling anything too nicely today this will just add a little separation and then finally at the bottom of the component here instead of the return uh div once again we're just going to return that content that I created so that is our full component not too complicated there but we are receiving that promise from above again it's still requested in parallel but now we're able to incrementally show the results back here in our user page because we can show the username right away and we can use suspense while we're waiting on the post data and this is also shown in the documentation and speaking of documentation you can see we still have an issue here even though we created our user post component we need to import it above let's go ahead and do that user posts and this is going to come from our components.user's post and after I save you'll see there is still an issue and we're going to need to go back to the docs to reference this current issue again we're using beta docs here for next 13.2 as of the making of this video if you're watching this months later this issue should already be resolved but right now it's noted in the docs and I want to highlight it if I Mouse over we've got a typescript problem here it says users post user posts cannot be used as a jsx component well actually there's nothing wrong with what we're doing but we have a typing issue okay we're back in the beta docs under data fetching and then fetching and you can see there's a warning here it says you can use async await in layouts and Pages now they're specifically talking about the file names layout and page or pages.tsx that we've created before but it says there are server components and they are however we're creating a server component that's named user posts as well using async await inside of other components like the one we just created named user post with typescript can cause errors from the response type from jsx it says we are working with the typescript team to resolve this upstream and as a temporary workaround although none of us are probably going to like it you can use this comment line right above your component so that's what we're going to do just copy this right here we'll put it above the component for now and realize this probably will not be an issue a few months after this video is created so if you're not receiving an error right now the way things are then you don't even have to do this but let's go back to visual studio code and apply this so back in vs code I'm just going to put that line right above what we had and now of course our typescript error is gone it tells it to basically ignore what it's experiencing but we have created a valid server component it just doesn't have the name page TSX or layout.tsx so now that we've created our Dynamic routes with the user ID and we're receiving that as a param that user ID comes in from the URL then we get that and pass it into these fetch functions that are created here in parallel and we get that data and then of course we use suspense to incrementally show the data we get so we have the user information and then instead of using that loading.tsx page that would apply to the entire page or the entire Branch inside of here we're just breaking this down to part of the page using suspense and then we're going to show that user post data so let's see how it all works back in the browser okay we're back in the browser I'm going to clear out the network tab we'll go back to home here and I'll even just hold down shift and refresh so we get everything new and of course we're still in Dev mode so we have a lot of information coming here with network requests I can clear out now I'll just Mouse over the users link and we can see it already requested it so when I click on it there it is and we've got all of the users now we should no longer see errors when I start to Mouse over these user IDs we're seeing those requests and we're seeing the data of course that comes with those requests so it's pre-fetching those before I've even clicked now let me go to one of the users and there we have the username and then we have all of the user posts the title and the body of each of those posts so everything's working as we expect it to but back at the beginning of the tutorial if you remember we covered metadata and we only covered the static metadata I said we would cover how to generate Dynamic metadata as well and notice for our user Leanne Graham the title of the page is still create next app just like we had in the layout there at the beginning for the overall app so let's go ahead and create individual information for each user when we go back to our users list remember we created some static metadata and of course that applied the user title up above and that works just fine line now let's go back to the code and create some Dynamic metadata we're back in Visual Studio code and we're back at our user page component that is inside of the dynamic route and we need to create some Dynamic metadata what we're going to do is create that above I can do it after the params because we're going to need that with this function as well we'll say export async function and the function we're going to create is called generate metadata and now it's going to receive the same params that our user page component receives so I could just copy all of that and paste it right inside of our generate metadata function as well because it also needs the user ID to get that specific metadata and after we do this it's going to have a promise and this is going to be metadata that we get here now we haven't imported that metadata at the top yet so let's go ahead and do that import as well so we'll say import type and that is metadata and that comes from next okay now that we have that let's continue creating the function here so afterwards we need curly braces and then inside of this function we're going to need that same user data that we got in the function below now remember one of those recommendations from next was to go ahead and request data where you need it because it will automatically de-duplicate these requests and that applies to this generate metadata function as well so because we have the request here and the request here does not mean that two requests will be issued they will be deduplicated okay after that let's go ahead and get our user and once again that is the user type we'll set that equal to a weight user data and now that we have our user data we can return our metadata so we're going to return and then I'll have a title and inside of this I'll say user.name then I'm going to have a description as well and here I'll use a template literal so I can say this is the page of and once again I'll just use the user.name here so that creates our metadata so we'll apply this and then let's go back to the browser and see if it applies to each one of our Dynamic Pages I'm back in the browser and we're still running our code in Dev mode I can clear out the network request so we can see them happen once again I'll go to users after that let's go to Leanne Graham and now if we look at the top tab here it says Leanne Graham and I think if we're to inspect the page we could also see that other metadata that we added so let's look inside the head element here as we inspect scroll down and we see the title is Leanne Graham and then there is a meta description and it says this is the page of Leanne Graham so our Dynamic metadata is being generated as we expect it to be all right we've come a long way and next time we're going to dive deeper into fetching with our server components remember these are all server components right now and we're going to look at the differences you can control including static site generation server side rendering and even the powerful incremental static regeneration strategy our starter code today is the ending code from lesson three so I'm just picking up where we left off and you can see I've created a folder now in the course resources called next04 so you could find this starter code in that directory in the course resources now what we did in the last lesson was create server components that use data fetching we did not discuss however are those static components are they server-side rendered components or do they apply any other strategy other than the data fetching strategies that we applied and right now they're not applying any other strategy however you don't know which type of component you have and in Dev mode you can't really tell if we look at package Json though you can see the different scripts and we were using Dev mode if we run build next is going to tell us what type of components we have and how they are being generated so let's go ahead and do that I'll just do control in the back tick to open up a terminal and instead of npm Rundown of I'm going to run npm run build and we'll go ahead and build our application and I'll expand this to take up the full screen and as it creates this build when it's finished it's going to tell us what type of components we have and now we can see the output I'm going to scroll up just a little bit but it gives us I should scroll down just so we can see these first it gives us these different indicators so this indicates server server side renders which would be SSR and this indicates static not necessarily SSG as we'll see a little bit later next is going to differentiate from just static and SSG based on props this uses no initial props SSG will actually receive props but still be statically generated so we'll see a different indicator for that so right now we're saying our users page is static just like the hello page they give as a default inside of the API directory for example it's just statically generated in advance ants built on the server and then sent out to those content delivery networks however the users page receives that user ID and there's no way next can know what parameter it's going to receive in advance so it can't build those and so those are server side rendered at request time it builds it on the server sends it back to the client and really the only way to see the response time is to go ahead and run this as well so if we look back at our package Json I'll need to bring this back down in the scripts we not only have the build but we have the start and if we do npm Run start it's going to use the build we just created so let's do that once I'll say npm Run start and we'll go ahead and start this code and we'll get a better idea of how it would actually respond and so now we're at localhost 3000 again I'll go ahead and control click that to open that up in Chrome and let's look at our next app here I'll close the one we previously had open and again it looks very basic let's open this to Dev tools we're at the network Tab and now our request will look a little bit different than they did in Dev mode so here I'm going to Mouse over we should still see the request for users oh we don't it's static it should already be there right we did that and then instantly after we went to that users page that has the links notice it didn't wait until we moused over like it did in Dev mode it instantly requested the data from all of these links in advance and so now we see the 10 requests for those and so now when we actually do click on one of those it should seem fairly instant because it wanted to get a jump start it pre-rendered those pages and so now when I click and go it's there pretty much instantly already but those are server-side rendered Pages they are not actually statically generated before because there's no way next can know that we're going to send in the param that is one or two for whatever the user IDs are however I say there's no way if we know in advance we can actually use a strategy with our code to tell next.js what they will be to make it even faster and we're going to do that today okay we're back in vs code I'm going to press Ctrl C to close that server and instead of the build we're going to go back to our Dev mode so npm run Dev and that's what we'll want to work with as we apply some changes so now I'll close the terminal and I'm going to close out a package Json as well let's go to our library where we had the get user posts function right here and now that we have that I'll press alt Z to wrap that down we can apply some things to fetch here and first let's look at what is default already as as I said next already caches data by default so that default would be a cache setting inside of fetch that we could show after the URL you can have an options object we could say cache and here we would say Force Dash cash we don't need to do this this is the default so the data that is server side rendered initially if we're getting a dynamic request in the URL that is cached and it doesn't need to go back and re-render that again it knows that data after the first time and it holds on to it the only bad part would be if there are changes if it's data that is changing constantly you may not want to always see the old data which would be referred to as stale data and you could make it always Dynamic so just the opposite of allowing it to be cached essentially saying never cache this data and that would be the value no store however there is incremental static region generation and that means we want to go ahead and create the page and then we want to just check every so often to see if there's an update and that might be the Best of Both Worlds and that's what we refer to as ISR again called incremental static regeneration and this uses something different we put a revalidate value in and instead of just saying cash here we start with next so we'll say next and then after that we have another object and we say revalidate and we put in the value in seconds that we want next to wait before it checks for new data again so let's put in 60 seconds so this can be applied to SSG static site generation or server-side rendering it can be applied to either type of component that uses the fetch request and what it's saying is show the data for 60 seconds before you revalidate to check to see if there's new data so if it's the static page and the data data happens to be stale that was already generated on the server you would only see that stale data for about 60 seconds and of course you'd have to navigate away from the page and come back to it and then you would see that new data however if it's a server-side render page you know it was just rendered at that time but if it changed before the 60 seconds were up you'd still see the stale data and of course you'd still have to navigate away and come back because the page isn't just going to revalidate and magically change in front of your eyes however this gives you kind of The Best of Both Worlds because you're getting the benefits of that server side generated page that's served very quickly and then if the page updates say it's some type of weather forecast or whatever and the user would navigate back to it then they would see the updated data and for us this is ideal for the git user post because let's say our users add a new post well we saw the post list before but the next time we go back to their page to check their posts again maybe a new post was added and course the revalidation would then show that new post now we're back in the next JS docs and while I'm not using this in the code that we're writing I did want to highlight it as I discussed the revalidation in the ISR strategy because you can also set this revalidation at different levels you can set it at the layout level or the page.tsx level and all you have to do is create an export const revalidate and set it equal to the seconds you want so this sets it for everything at that level instead of on that per request basis as I did in our code so we have applied incremental static regeneration ISR and it's very good and we now have the power of server side rendering and incremental static regeneration but what if we could take these SSR Pages the server-side rendered pages that we are creating in our app directory with our users branch that has this Dynamic folder here that receives the user ID right now next has no idea what value will will be passed as a parameter what if we could take those and actually tell next.js in advance what those possible parameters will be well we can do that and that will turn our SSR pages into the recommended SSG Pages the static site generation now to do this let's go to our page.tsx file for the individual user after our user ID Branch here so we need to actually open this up and go to the one inside of the dynamic route here we are and we have our generate metadata and then we have our user page component so underneath the user page component we can create this new function that will help us generate those static parameters it's export and then we'll say async function and it is called generate static params and now this function doesn't have any props that it receives there but inside the function we're going to once again request that same data and remember next jsd duplicates this data so this will not create an additional request by putting this in here even though we're using it inside of our user page component and inside of our generate metadata oh and I said no props we're giving this the wrong one actually what we're going to need is the get all users because we're going to send in all of the user IDs so let's go ahead and get that function and that comes from the parent component up above where we had this here and it's get all users and we get the user's data not just the individual user data so I'll go back here and put it in of course we'll need to import that because we weren't using this function previously in this component so above go ahead and import get all users as well from our library okay now that we have that our users data and you can see it's a promise and it uses that same user type and we get an array of users now we need to say cost users and here we will go ahead and await the user's data and once we get that we can simply return the map over this data so we would return and then we would have users.map and then for each user go ahead and return an object so I'm going to use parentheses here first as we come down to the next line and then after parentheses well I could have put the curly brace above but we can put our brackets here as well say user ID and then it's going to be user dot ID because this is for each user but here's something to remember now because our user type remember we have the type in our definition file down here where is that oh it's way at the bottom a user type has an ID of a number so what we need to consider here is params always need to be strings now when next gets a param from the URL we know it's going to be a string there but now we're providing these params in advance so we need to say two string here as well and I just don't like how that looks as well with the curly braces on the same line I'm used to seeing them up above so let me do that that's just a formatting preference of my own here bring that down without the curly brace underneath and I'll wrap this back up there we go so we're providing these params in advance as we map over them all and then next.js will know what the prams are going to be it like I said before it couldn't know when we were just saying hey this is dynamically created but now we're providing static params in advance and with those static params next JS will then know what the parameters are going to be and it can actually statically generate those pages in advance without the server side rendering so there'll be SSG and not SSR so now let's open the terminal once again I'll press Ctrl C to close out of our Dev mode and let's rebuild this project and let's see what next tells us about our server component so npm run build and if you remember in the past all of our Dynamic paths for the user ID were SSR Pages now let's look at this there's no longer that SSR indication we have SSG here and as we scroll up and look users slash user ID these are all SSG Pages now and that's what we wanted which is even better they're generated in advance but note these SSG pages will still follow our ISR strategy that incremental static regeneration strategy that we talked about and it will of course revalidate at the time interval that you set just to check it out let's once again run our build code with npm Run start and we should come back once again to our local host at 3000 control click to open that up we're here at the home page let's look at everything I'll click on users and instantly it requested all of these now I'll go to Leanne Graham and there she is with all of her different posts there was no extra request now we didn't need to request to the server to generate those pages it requested them once there was no longer a server-side render page these are all SSG pages and then of course we have that data ready for us instantly there is there's no weight it's just like visiting any static web page and that's the power of SSG and of course if there is an update if there is an update to one of the users posts it is going to revalidate that information still with that built-in ISR strategy you're really seeing the power of next JS when you understand how this strategy is applied we're back in the beta docs once again and we need to discuss Dynamic params now with this setting enabled and it is enabled by default so there's no code for us to add here we're just looking at the definition of it in the docs so we're not adding this it's already in there by default essentially unless we wanted to set it to false it's enabled by default but with this setting in enabled next will attempt to render pages with Dynamic parameters so if we were to request a page like a user page remember we only have 10 users so if we were to go ahead and request user number 15 next would try to go ahead and generate this page of course you could handle with an error page as we've previously discussed but there's a special way to do this as well so let's go over that in our code now okay in vs code let's go ahead and use Ctrl C to get out of the npm Run start that's running the build code we'll run npm run Dev once again and just have that going to localhost 3000 and there you can see it we'll close the terminal and we're still inside of the page.tsx file that has our user page component that's inside of the dynamic route here at the top the special way we can handle this when next tries to get a dynamic page that doesn't exist instead of just generating a typical error we want a 404 and of course course next does provide a 404 default page and we can just go ahead and use that if we want to or we can create our own and we're going to start all of this by importing not found from this comes from next slash navigation now once we have that in here we need to actually apply this to a couple of the functions that we have one of those functions is going to be right here inside of our generate metadata so we're not going to use the not found we imported but we're going to apply the strategy here so we don't receive an error and the first thing we'll need to do is just say if we do not have a user.name because we know that's part of our user object that we should receive we can say return we can Define the title this would be a custom title for our not found page so since we're in the user Branch I'm going to say user not found and this would be the metadata for the not found page now after that let me create an extra space here just to clean that up after that let's scroll down and apply not found inside of the user page component as well I'm going to press alt Z once again just to get that to wrap in so we can see all of the code okay once we're here after we receive our user we just basically need to say if we don't have our user.name again and you can't just check the user because the empty object wouldn't validate that way so we're just checking one of the properties on it so after this we'll say return and we're going to call this not found function just like that I'll save this file and let's go back to our application inside of the browser I'll open this up go back to home we're still on localhost 3000 so I'm just going to refresh reload everything should be running even though we're back in Dev mode now and if we go to users that's fine if we go to Leanne Graham to see her posts that's fine we wait a little longer in Dev mode but that's the thing we wanted to check out actually when we ran it after in build mode it was instant Dev mode takes just a little bit so that's the best way to check your code but right now we want to check what happens if we request a user that doesn't exist otherwise so let me just check something crazy like user 1000 this user doesn't exist what's going to happen we've got a failed to fetch user oh and we threw the new error and that's something our code didn't catch yet and this is something I forgot to change that's recommended in the docs when we're applying this strategy so let's come back and get rid of that error by returning undefined here instead of throwing an error when we get the user we're going to return undefined and let's also do that for the user posts that are inside of this Branch as well so we'll have undefined there and now save and after we've applied both of those let's come back and now we get the next JS 404 default page but we can make this look a lot better than this plain 404 that we have if we want to you can provide your custom one I won't provide one that looks better today but I'll at least show you how to create the page back in vs code we're going to scroll back up here in the file tree to our Dynamic directory for the individual users and now we want to create another page here so I'll create a new page and this is called not Dash found it's a special name just like page.tsx is or error.tsx so here we're going to say RFC to quickly create a function and we can't name it not Dash bound so we're going to name it not found with camel case they're actually Haskell case there and with that we can save the file and then we can go back and look at Chrome we may need to restart our server let's take a look at what we've got here no it looks like it applied it right away and it just says not found here now of course we can put in our own custom message so let's pull vs code back up and we'll just change this div to an H1 and inside the H1 let's just say the requested user does not exist we'll save that and let's take a look at the browser once again and that's the message we get for the 404 and there is the custom title as well remember what we put the metadata in back in the other component so our main takeaways today as I come back to the terminal and press Ctrl C to get out of Dev mode I want to run the build once again and as we run this build we learned about how to tell if you have a SSG or static page in itself or an SSR page because you can check the build but essentially you know if you're creating Dynamic data and you haven't provided those static props then you're going to have an SSR component and that is generated at request time on the server versus a static page and of course next JS recommends SSG when possible so if you know the params in advance then you can provide those by generating those static parameter times with that function and then have SSG Pages as we see here and you get the indicator down here and you'll see that next to your pages up above and we also learned how to apply incremental static regeneration and those work in both SSG and SSR pages that strategy works and so all of that will help improve the user experience I'm back with your installation instructions for chapters five and six we want to type npx create Dash next Dash app at version 13.2.4 go ahead and press enter now all of our decisions will be the same as before I'll name this one next05 and press enter yes to typescript yes to eslint no to the source directory through chapter 6 and then we'll go up to yes for the app directory and yes for the import aliases okay we've created the new project and I now have the next o5 directory open here in vs code and we can see the files in the file tree but what I want to bring your attention to now is the website for Tailwind because we're going to add Tailwind CSS to this project and the first thing you want to do on the tailwindcss.com website is go to docs and from docs you can see we're at the documentation over here on the left hand side and then it says get started with Tailwind CSS we can go to to framework guides and from there they have next JS right here at the top so let's click that and it's going to walk us through installing Tailwind CSS with next JS now the very first step we have already completed we did that when we created our application so we no longer need to do number one we can move right along to number two and you can see we need to execute these lines here at the terminal prompt so what I'm going to do is just copy you can click the copy icon here and then I'm going to bring vs code back up and in vs code I'll open a terminal with control in the back tick and I'm going to right click and it puts in the first line and it immediately starts executing that and after the first line I think we'll have the second line as well and yes here's the second line now and so I need to press enter for this one so we'll go ahead and do that too so now we've executed both lines so you just have to remember to press enter for the second one and now you can see we have a Tailwind dot config big.js over here to the left and we're ready to go to the next step on the Tailwind website so let's pull that up and it says configure your template path so inside of that tailwind.config.js we need to add the following lines here so I'm just going to copy all of this now we're not using the source directory so I'll remove those afterwards so Ctrl C to copy let's go back into vs code and in vs code I'll close the terminal for now let's go into our Tailwind config and that was in the content area if I remember correctly so I'm just going to highlight the brackets and Ctrl V to paste yeah I've got two contents now so I can back that up and after that I've also got two commas there so remove that error now I'm not using the source directory so I'm going to get rid of these lines but we'll keep these three lines here between the brackets you can see we're going to use the app directory and it's also got something in here for Pages or possibly components now let's go back to the Tailwind side again for the next step I'll scroll down it says add these directives to your globals.css so let's once again copy now let's go back to our globals CSS file in our next project let's find where that is I believe we would be looking in the app directory there's globals.css I'm just going to control a to select all of this because it goes with the starter project and we don't need it so I hit backspace I'm going to paste in the three directives here and Ctrl s to save this file and now back at the Tailwind site once again let's look at the next step it says start your build process with npm Rundown up well we definitely know how to do that then it says we can start using Tailwinds so we're really complete now and we can just go back and do npm run Dev if we want to but I'm going to make some other changes first let's start by going to the page.tsx file inside of the app directory and here we can clear out a lot of things we're not going to use including this first line that Imports image we're not going to use that today we can also get rid of these Styles here we're not going to use the page.module.css we'll actually remove that file here in just a minute but let's keep the enter font from Google as we see imported here and we need this other line that defines enter as well after that let's grab everything between the main element the opening and closing tag and just remove that here from the starter project so I will press shift and click and select everything in between and now we have really cleared out our home page here our main element inside out of this but instead of styles.main which Styles no longer exist let's just apply that enter font right here and we can do that with enter dot class name as we pass into the class name and save this file now I mentioned we will no longer need this page.module.css so let's just press delete here to remove that file and now let's create a components directory here inside of the app directory so I'll just highlight this and click the new folder and I'm going to type components and then inside of components I'm going to create a navbar file so we'll do this with a capital N dot TSX then inside of the nav bar we can just type RFC if you have es7 rack Snippets like I do and press Tab and it will start a function for us now we're going to need to import Link at the top so I'm going to press enter a couple of times and say import link this comes from next slash link oh I need a cat or a lowercase link there we go and now that I've imported the link we just need to change what we're returning here so let's go ahead and put some elements inside we'll start with a nav element which makes sense and inside of that an H1 element and inside of our H1 we will use the link and this link is going to point to with an href back to the home page because this nav bar will be available on all pages when we use it correctly and inside of this we're going to call our small project Wiki rocket and I'll put an exclamation mark after that now while I'm going to apply Tailwind classes today I'm not going to go over each one and have you learn Tailwind along the way that should have been one of the prerequisites as you started in lesson one so you can copy my classes from my available source code in the course resources if you want to I'm just going to quickly add them by pasting them in today so we'll see class name on the nav and I'm going to paste in several classes now you can see it's a long line so I'll press alt Z to wrap that line down after that I have a few more classes to go ahead and apply to the H1 as well so I'll put a class name here and I will paste in the following classes as well after that we're pretty much finished with the navbar for now we will come back and add something else so now let's look at the layout.tsx where we will want to use this navbar so it shows up on all of our pages so we need to import the nav bar first and we get that from components navbar notice we already have metadata here at the top and we can just leave this or you could change it to the wiki rocket information if you want to that is fine also so we have our root layout here and it receives the children that's all good so all we really need to do is put our nav bar inside of the body with the children here and a common mistake would be to put it outside of the body I think that would be easy to do but right now we want to make sure it's inside so here we'll just have our navbar and put a slash there to in the component let's also put a Tailwind class on the body so we have a darker page so I'll say class name equals and here I'm going to use background slate and a dark one so 800. now we won't have much to look at yet but let's go ahead and open a terminal with control back tick and type npm run Dev and we should see our Tailwind applied to our basic site as we start it up here I'll click allow for that message and control click on localhost 3000 as it shows here in the terminal and I can pull that up inside of chrome and yes we have our Wiki rocket navbar across the top that has a little bit lighter slate cover than the rest of the body where we applied the darker slate cover and that's all applied with tailwind and so now you know how to set that up in xjs and get a project started now we'll head back to vs code and I'll pull that up we'll go ahead and close out the terminal window so now our next step is the focus of what we are covering today and that is the client component and we want to build a search component that will be in our nav bar so in the same components directory as the navbar let's go ahead and create a new file let's name this file search.tsx we want to start our client components with use client at the top and you may have seen this before you should recognize this because we use this inside of the error.tsx when we covered creating error Pages it was provided by the documents and error Pages must always be client components as well so after we have gone ahead and typed use client let's use our es7 Snippets again with RFC and create that default search component as well now we have a couple of imports to go ahead and bring in at the top so I'm going to import use state from react and then I'm also going to import use router from next slash not next slash router that was the default actually this new version we want next slash navigation so we just want to make sure that that import is the correct one and notice that my default was wrong so now at the top of our component let's go ahead and use State and I'll just say const and we'll call this search and set search you should be familiar with this understanding react already is one of the prerequisites for this next JS series and let's just make the state an empty string to begin with this will hold our current search term then let's define our router and set this equal to use router and now we're going to have a search input and we're going to need to be able to handle that input as the form is submitted so let's go ahead and create a handle submit function all this handle submit and it will be async and now I guess I need to put an event here we don't know the type of the event yet so let's come back to find out what that type is and I'll show you how you can do that also but we'll start with event dot prevent default as we do not want the page to reload when it's submitted then we'll set the search back to an empty string after we have submitted the current search and then we'll also route to the location for the results and that's one thing that we'll do here in next.js that's a little different than how you might do it in a regular react app because we route to a new page that will have the address of the search term so I'll say router dot push and now this will take us to whatever the root URL is and then add on to that root URL our Search terms so I'll put in the search state right here and we can look more at how that works after we get everything working and you'll see what I mean and when we look at the URL and how that search term is added oh and I want to add another slash at the end of the URL as well now let's change what we return here so our return can still have the parentheses but we'll remove this div we're actually going to have a form now this form will not have an action on it but it will have an on submit and it will have more classes from Tailwinds so let me just grab the classes first and we'll put class name over here and we'll set that equal to the Tailwind classes that we are applying now anytime you just want to pause the video and copy my classes or copy them once again as I mentioned from the source code available at the link in the description for this lesson you can do that as well okay after that we also need the on submit Handler so we'll say on submit I'm going to press alt Z so this wraps down once again and we'll just pass in our handle submit that we created okay now we need the inside of the form the actual input itself so we'll put in an input element and after that yes it is type text I like to put these on separate lines so it's just a little more organized especially when you have several different attributes okay so after the type equals text the value will be equal to the search state as it's a controlled input after that we'll have an on change and here with the on change we're going to set the state so I need curly brackets and then we'll have an event here and this event is going to go ahead and go in here and we'll use the target value that we get so we'll have set search and you have probably completed this before as you learned react but event.target.value so anytime this changes this sets up our controlled input essentially after that we're going to have some Tailwind classes we apply here also so I'll set this in here and I'll just bring these classes over quickly and it should make the input look a little nicer after that let's go ahead and add a placeholder and the placeholder will just be the text that displays until we enter something we can just say search so that is our input now let's add a button to go ahead and submit the search so the button is going to have some classes as well but inside the button instead of saying go or something like that I'm going to press the Windows key and the period because I'm on Windows and it brings up an emoji menu you may have a different way of doing this on Mac or Linux if you're on one of those operating systems I'm just going to type rocket and it's going to show the rocket here remember we're making a Wiki rocket application so we've got our button with a rocket and I just want to apply some class names here as well so class names equal and I will bring these over and it's a short list but it should make it for a nicer looking button and now we've applied the Tailwind classes and our form is complete so we have the controlled input that sets the state as we type and that shouldn't be A New Concept for you if you've already understood react or taking the beginning react course back up here then we have our handle submit this would be a New Concept for next JS because we have this router now it's very similar to react router but the real the router pushes this onto the web address so we're going to go to a dynamic page now we've covered handling Dynamic routes already and that's what this will be so the only current issue we have is the type here we notice our little red squiggly under the event here we don't know what type this is if you come into the on submit and you type e and an arrow like this this is going to kind of tell us what the type is so I'll Mouse over it is a form event says html4 form element when we Mouse over and get some intellisense so we know we need the form event now we don't want this e here so let's go ahead and remove this we come back up here we're going to go ahead and need to import form event at the top so here we can say this is a form event and then it had the HTML inside of it so let's once again I'm back I shouldn't have deleted that I should have just copied from the intellisense right so we'll put the E back here Mouse over it's a form event and then I'll just copy the whole thing is a form event and then HTML form element inside I can't always remember what those are either so that's a handy little trick for getting that so let's just copy over all of this and paste and now we have the correct type in here for our event when the form is submitted so now with our client component complete let's go ahead and import it into our nav bar and of course notice then that this will not be a client component but you can use a client component inside of a component that is otherwise generated on the server and that's what we'll be doing here so let's import search this just comes from dot search because we're already in the same directory now that we have that it's going to go in the nav after the H1 so here we'll just say search and we have our component added now let's go ahead and look at our application in the browser there's our search box and the little rocket as well let me open Dev tools with Ctrl shift I and I've got the network tab open here notice how this shifted because I do have in some Tailwind that is changing the nav bar depending on the width of the page so that's good also we can get this down a little smaller even down to phone size so that should work well all right let's go back to vs code and in vs code we need to create our Dynamic route because although we're showing this in our app the search of course is routing to a dynamic route and we haven't even created that yet so that's next up and this will go inside of the app directory so let's create this Dynamic route here and if you remember we put those in Brackets so we'll start with a bracket and then I'll just type search term and close with a bracket that's what is going to be passed as a param as well so we have to remember that we used search term with camel case Here and Now inside of this Dynamic route let's go ahead and create our page TSX so page.tsx and inside of the page.tsx we want to create our component I'm going to call this component search results but we can use our es7 Snippets and since we're using typescript we can also start with TS and RFC I'll press Tab and now notice it added some props for us so we've got props right here this is an empty object right here for now so we can put the rest of the information in we are going to need those props so let's go ahead and Define props here it's going to be params and then inside the params we're going to have search term and prams are always a string and so then to start our function here as well we're going to need params and then inside of this we will be destructuring the search term and that gets our function started now from this search term we're going to request results from Wikipedia and that's how we're going to get our Wiki rocket results so what I need to do now is set up a request function we can't really do much more with this component at this time so for that request function now we're going to put this outside of the app directory just in the directory itself we can create a new directory and call it lib for library and then inside of this I'm going to create a new file I'm going to call it git Wiki results dot TSX now I'm going to type RFC press Tab and start this function but it is an async function so I need to add async up here at the top as well after that we know this is going to receive a search term and that search term is always going to be a string because that's what we will get from the URL now I am going to go ahead and highlight this and put the rest of the function in here and then go over it with you because it's really it got it has a lot of lengthy params here that we're going to create a URL search params this is a new URL search params you could look this up on mdn if you're not familiar with URL search params but when I Mouse over notice it says search params is URL search params type and here this is something like with a get request you could see all of these parameters added on to the URL with the different things that would take to put in the URL I should say like you know your Ampersand symbol of course it would start with a question mark and each one of these would have an equals but we're not doing that we're just creating the URL search params here and this is really easy to kind of map it out now notice they're all strings except the search term here and the search term of course is a string as well it's just being passed in so all of these different values are something that relates to the Wikipedia API so it's not a specific type you need to know so much as just the Wikipedia API we're using today needs these as well here I'm going to press alt Z once again to wrap but as we request down here's our fetch here is the root URL that Wikipedia requires and then we add on WE concatenate the Search terms and then we're just responding with the Json that comes from that so that is the entire function you can see this in the course resources you can pause the screen and copy this here but all of these parameters are required for the Wikipedia API okay after saving this file I'm going to add a types file as well so just here in the main directory again in the root directory I'm going to create a file and call this types.d.ts now you can create a file like this or you could create a types folder and create a file for each type if you want to organize it that way either way works when I only have a couple of types this is a very easy way to do it and then typescript does not require the Imports because in your TS config file it's already going to look for any file that has this type of naming convention just like it finds the next env.d.ts so you can see the other types of files that it does include okay closing out the TS config back in the types.d.ts file I've just got two types that we're going to use today and again these are types that relate to that Wikipedia API I'm just going to paste them in and we'll go over them you can copy them from the source code repository for this lesson if you want to or just pause the screen but we've got a page ID and every individual result will have a page ID that will have a title that will have an extract notice the thumbnail is optional as we see here in the type and if there is a thumbnail it should have a source width and height now the search result this is questionable because we aren't guaranteed to get a result from the Wikipedia API so the query is optional and the pages is also optional if we do get Pages it's going to be an array of results but we just have to keep in mind that these could be undefined as well now let's go back and complete our Dynamic search term page that is here inside of the dynamic search term results so we can show those results that we get back okay the first thing we should do is import that get Wiki results function that we created in side of the library folder so we will import get Wiki results and you can see it's imported from that Alias that we have right here and then the live or the lib and get Wiki results after that let's go ahead and start building out the inside of this function and the first thing we're going to do is get that Wiki data so let's define wikidata and this is going to be a promise and it's going to be the type search result that we defined in our types file if I could spell search result correctly there we go set this equal to get Wiki results and we'll pass in that search term okay after we have done that then we need to get the data itself so here we'll say const data and this is going to equal a weight Wiki data now of course we're flagged here for the await because we didn't make this an async function yet so let's do that so now that we have our async function page and we should just go ahead and rename this page while we're at it because this is our search results component of course it will always keep the file name page.tsx okay after that let's define our results so we'll say const results and this is going to be an array that has results in it but it could also be undefined as we noted so more of a union type there now that it is either an array of results or it's undefined let's set this equal to data and we're not sure if we'll get the query but if we do then we're not sure if we'll get Pages or not so we're just saying that yes this could be undefined these may not exist and we just need to code for that if they don't exist let's go ahead and scroll up just a little and then I'm going to Define some content here so I'll say const content equals and I'll use parentheses and now inside of this I'm going to create a main element that we could return and then inside of the main element we'll have some other content as well but let's first let's apply a class names to the main for Tailwind so I'll say class name equals put our quotes and I'll bring these classes over again so Ctrl C there on my other screen and paste that in with control V press alt Z to wrap that down so you can see all of these classes here from Tailwind now after that inside of this main element let's use a ternary so let's make sure that we actually have results that's what we defined up here but remember it could be undefined so let's make sure we have results and with this ternary we'll say if we do have results then we're going to use object dot values because the results come from Wikipedia as a large object so then we'll pass in the results and then we'll map over those and we'll say for each result we are going to eventually return an item component but for now let's just return some Json here so come down an extra line and I'll put in a paragraph and inside this pair graph let's say json.stringify and let's pass in the results we can stringify each result here and it's not necessarily liking that so let me go ahead and put curly braces for each let's write this the way I'm used to writing it and then I can adjust it later when we put in the item component if that's what we want to do oh and I think the reason it's not liking it yet is because we haven't closed out our ternary statement so we just also need to provide the false possibility here so what is going to happen if we don't have results well let's put in an H2 and then inside of the H2 we'll put in some more JavaScript here and what I'm going to do is use a template literal and I will use the search term and then we'll just say not found and inside this H2 we could put a couple of classes on it so let's say class name set this equal to padding Dash 2 and this would also be text Dash XL okay so there is our content and what we've got is a main element and inside the main element of course we hope to have results from our search we have those results we're going to map over those values and that's what will be displayed here it looks like we still have a problem actually and that's because I didn't close out the curly bracket here at the end so let me go ahead and put that right there and now everything looks like it should so hopefully we're going to be showing these stringified results and of course that's not going to be too pretty on the page but at least we'll let us see that we are seeing results but if there are no results at all we should be showing whatever the search term is not found on the page and finally with our return down here let's give an extra space and instead of this we'll just return the content that we defined above okay with that much in place let's go ahead and bring up the browser and let's try to search for something of course I could open up the dev tools with Ctrl shift and letter I here I'm on the console we can also go to the network and see what comes in remember we're in Dev mode so we'll see more things come through here so if I refresh we should see quite a few things load I'll just clear that out but let me just search for my name here and we'll see what shows up on the page well we've got a lot we've got all of this Json it doesn't look great it actually overflows this container even that it's in but we know we're getting the data and that's what's important from here we'll be able to format this and it will look good let's go back to vs code and improve this display and we'll start out by creating some metadata so let's just scroll up inside of our page file here and we can create that metadata at the top if we've covered this before if you remember we type export we'll have async function and then we're going to use generate metadata and this is going to receive the same props that we have down here for our search results so let's just copy that and we can paste that much in and after we do that let's go ahead and create the rest of the function so inside of the function the first thing we're going to do is request that same data and remember we can request data in xjs wherever we need it and xjs will dedupe the request so it doesn't hurt to put in the same request here now that we've got that data we want to define a display term so I'm going to say const display term we're going to set this equal to the search term that's received but then I'm going to use replace all and the reason I'm going to do this is because it's coming from a URL that's where the search term will be and if there's spaces those spaces are represented by percent 20 and we want to replace those and just put in an empty space so it's more readable by humans not So Much by a browser and so that makes sense to pass in the search term and I see I've got some red squigglies and that's because I missed a parenthesis here it seems like I am prone to some typos today but now everything looks good once again and definitely typescript helps me catch those okay after we have defined our display term we have to consider that what if there are no results and so we want to of course adjust the metadata for the page if the search term is not found so we can do that with an if statement we'll say if there is no data and remember the query might not exist so we need to use optional chaining there and then again optional chaining on the pages but essentially if we have no results that are eventually found at that Page's position in the object we're going to return some metadata here and I'll just do the title and we'll use a template literal and here we'll use the display term because again it's more readable than the search term might be if there are spaces and we'll just say not found so that will be the title for our page if no results are found otherwise we can return some more metadata so let's return another object here this will have the title and it will just be the display term for the title and now let's have a description and this description could be search results four and now let's pass in that display term once again and so this would make sense because we've got a different set of metadata if we have results versus if we don't now the next thing we could do to improve our display is actually create an item component so now let's create a new directory inside of this Dynamic search term directory call this components and inside of the components directory we'll have a new file and it will be item.tsx now let's type tsrfc using Snippets here and we should get a component that also already has some props so that's good now we'll start at the top we know we need to import link so that's the first thing I'm going to do or link from next slash link after I have that import let's go ahead and Define the props this is going to be a result and it will be the result type we have already defined so when it comes to our item component here then we will go ahead and say this is result it is all we really need to put there because we already have the props defined okay after that we're going to Define an item text column and I'm just going to highlight this delete this and paste this in and we can see what it does I'll also press alt Z so you can see all of the code but it's all held in this variable and essentially we've got a div here and I've turned it into a flex container and then we've got the H2 which is the title from the result we see and you can see we're actually going to link back to the page on Wikipedia for the result and the target equals underscore blank opens it in a new tab and then I've applied a few Tailwinds CSS classes but what is displayed is the result dot title and then we have the result dot extract here so we have a title and an extract and that is what our item text column is after that I'm going to scroll just a little and underneath this I'll paste the content and I will go over it with you as well so what we have now is a ternary statement once again because remember not all results will have a thumbnail so we just have to make sure that the thumbnail and the source exist if we're going to display this content because what this does is take that item text column that we defined up above and it puts it with the thumbnail if that thumbnail exists so here you can see we're creating a thumbnail image it's a very small image but it has the different information from the result if it exists and then I'm also just lazy loading it with the normal HTML attribute okay after that we have this is the true condition in the ternary but after that we also have the false condition which is much easier it's just an article that wraps around that item text column that we displayed above so we're going to either have a thumbnail with our text or we're not going to have a thumbnail with our text and that's what this ternary decides with the content and we eventually just return I'd spell return correctly the content now if this went too fast for you go ahead and pause the video if you need to or look at that source code from the course resources and you'll be able to put this item component together or just build one of your own of course experiment with that data you see come back from that Json stringify statement that we still have over in the page file for the search results component before we put this item component into place with the item component complete we need to go back to our page and use this item component so let's imp recorded here at the top you will import item and it should come from components dot item after that let's scroll down and put it into place instead of this ugly Json stringify statement here so instead we could return our item component and it's going to have a key which is going to equal result Dot Page ID and after that we want to pass the result so result is going to equal result as well then we can just close out the component here and save the file now let's go back and look at our page once again in the browser I'll pull that up and the search for Dave is already showing results like we'd expect to see them here's all the little thumbnails there's a lot of thumbnails for Dave's we could search for something else that might not have as many thumbnails but we've got some results let's try something else I like the bubble gum search and the reason I like the bubble gum search is not only are there not thumbnails for each one but this kind of weird result here for the movie They Live that comes up with all the bubble gum and trading cards results if you're not familiar with this movie there is a reason it comes up with bubble gum and I'll let you look that up on Wikipedia or on this app after you build it so let's see how our app handles something that is not found I'm just going to type in some gibberish here and press enter and yes it says whatever I just typed in that doesn't make any sense is not found so we did handle that data that is not found those results that may not exist we're handling that correctly okay let's go back to vs code and we can just add a couple of more things to our project inside of our search term directory the dynamic directory where page is let's go ahead and add another file and name it error.tsx as we've learned about in previous lessons I'm just going to paste it in because it pretty much comes from the documentation however I did add an extra statement here that says or go back home so I gave a link back to the home page and you could of course adjust the error page however you want to but we've got an error just in case it needs to handle an error then let's also go ahead and create a loading page so another new file here named loading.tsx and if you remember loading is using suspense kind of under the hood because this applies to the entire route now not just part of the page we could apply it partially to a component by bringing in suspense as we did in a previous tutorial as well this will just be a simple loading page in case it takes a while to load our data from the Wikipedia site so here we've got the loading page it's just got a few classes and it's just going to say loading so nothing very big right there now that we've got those in place let's make another search and let's go ahead and see if we can make a search that takes a while it looks like I need to back up here back to our original page or maybe refresh yeah now that we've got those changes in okay so let's search for something else maybe like uh Eddie Van Halen and let's see what we get do we get loading at first no it came up right away so let's try something else maybe we'll get a search that takes a little bit John John happened fast also it may get results so fast from this API that I do not see the loading but let me think of something else like Frank Zappa ah we briefly briefly saw the loading there for Frank Zappa so just in case there is a longer delay you will see that loading due to react suspense and now that we've built the project let's go ahead and bring vs code back up I've got it back up open the terminal once again with control in the back Tick Control C to stop the application from Dev mode and before we build the project think about the components we have and ask yourself are they server side rendered of course we covered client components today are they SSG just think in your mind if you can decipher what type of components you have before the build tells you I'll go ahead and type in PM run build we'll see what components we have and we can discuss that as soon as it's finished building the project and the build is complete I'll go ahead and extend the terminal up here to the top and let's look at our queue down here or our key I should say the circle indicates static not SSG but a complete static page and this icon here indicates server side renders SSR so that's what we should have when we come up here to the top we can see the home page even though it has the search component in it that's client side the rest of it is just static and then when we go to the dynamic route for the search term those are server side renders now if you remember from a previous lesson we were able to use git static params and make SSR Pages SSG pages but we could do that with something more like a blog post where we could get those numbers those IDs in advance with a search term that's something that only the user knows what they're going to type in and they're only going to do that right when they type it in that may be when they know we can't really predict what that's going to be so this is the best we can do there with server-side rendered Pages for the search term pages that are generated I'm on the nextjs.org website and here we can click learn and we go to some lessons about next JS but it's not with the beta docs it's not with next js13 it's an older version and if you go through this you end up building a sample website here that was created by shoe and I don't think I could pronounce the last name correctly so apologies shoe but overall we build a Blog here and this isn't updated on the website yet for next js13 so what I wanted to do in today's tutorial is just walk you through building this project but building it with next js13 my finished product and here I'm in dark mode but it's really the same blog approach using next js13 and it's also responsive we can go to each page here and it reads these articles out of markdown files and then like I said it's responsive so I can open up Dev tools and you can see I can resize the browser and everything resizes as well well as well as the Articles and it looks pretty good doing that and of course you don't have to use dark mode but I'm using Tailwind CSS also which is something that was not in the original tutorial so we'll put all of this together today I'm back with your installation instructions for chapters five and six we want to type npx create Dash next Dash app at version 13.2.4 go ahead and press enter now all of our decisions will be the same as before I'll name this one next o5 and press enter yes to typescript yes to eslint no to the source directory through chapter 6 and then we'll go up to yes for the app directory and yes for the import aliases now I've opened up that directory that we just created for this project next06 as you see over here in my file tree and let's go ahead and clear out some of the basic things we get we go to the app directory let's go to the page.tsx and we can clear out most everything we see here I'm going to select everything between the main elements and delete it here so just press shift and click backspace to remove all of that I'll go ahead and remove all of the Imports up above as well so we're left with this basic basic home component here inside of page.tsx of course we'll add more to this soon we can also highlight page.module.css and I'm just going to delete that let's go into the globals.css control a to select everything and press backspace we'll save that we're going to add Tailwind to our project so we'll come back to this file in just a second now I'm on the Tailwind website at tailwindcss.com we're going to click docs from there you can go to framework guides and right here at the top you see next JS so let's do that and it's showing us the steps we need to add Tailwind to our project and they have these nice little copy icons so we can just copy the code here so let's do that and you know what we've already got some things going so let me go ahead and just install here from the second one here we already created this project so don't do number one copy number two now let's go back to vs code and maybe we can pull both of these into the same window if I drag vs code to the right and maybe I can go ahead and move our browser over here to the left and still read everything there we go control B in vs code to hide that file tree and then control and the back tick to open the terminal and we're in business I'm going to right click which should paste that in and execute the First Command the second one that we see right here will be waiting for us here it is now I just need to press enter there and it's going to run that one as well then it says configure your template pass so that's back in our file tailwind.config.js that has now been added to our project so what we want to do we're not going to use the source directory here so let's just copy the these three lines and we're going to add it here between the brackets in our content so I'll just Ctrl C to copy those three lines I'll quickly close the terminal and let me drag this back to full screen just for this part and Ctrl B to show the file tree here's that Tailwind config and here's the brackets with content so I'll just add those three lines in there and save my Tailwind config now I'm going to drag this back over to the left and see what the next step is for Tailwind so as we scroll down now it says add these three lines to the globals.css so I'm going to copy that I'm going to go to that globals that we had here inside of the app directory and I'm going to press Ctrl B to hide the file tree just so we can see everything paste these three lines in and save that's in the globals.css file that's inside of the app directory okay now it just says go ahead and start the build process with npm run Dev we're not quite ready to to do that yet but we will very soon now there's one more thing we're going to need from Tailwind today and we can just search for it here at the top they've got a great search feature just type in the word pros and once you do that you should see this Tailwind slash typography click that and we will be using this today because look what this says it says if you need a class name well not if you need a class name other than Pros let me find it here at the top I thought it brought it up to the top of the page there we go so this is essentially for any vanilla HTML that you don't control this is what I was looking for so we're going to create HTML from markdown and it will be generated and we won't have control over each tag to add those Tailwind classes to and that's why we need this because we can add this prose class and then we could also customize it and I'll put this link in the description of the video and in the course resources but we can customize this Pros class and it can just apply some kind of blanket styles to our blog and it will look good typography can actually be easy for our articles that we write in markdown so if we scroll down we actually need to install this plugin here so this is what we need we need npm install and then the Tailwind typography right here so I'm going to control C we don't have a nice little copy thing here for this open up our terminal once again and I'm going to right click to paste that in because we need to install that it's notice it's a Dev dependency that's what the Dash D the capital d means there in this line over here it's a Dev dependency after that though back in our tailwind.config.js under plugins we need to require the Tailwind CSS typography plugin so let's go ahead and close the terminal again let's bring this back to full screen because it's just easier to find control B to show that and then we come down here to tailwind and there we go inside of plugins we're going to paste that line in and that is what we're going to use as we generate those articles from our markdown files and now that prose class is going to help us to apply styles that look good without having to apply classes to every element that is generated because we won't have access to those okay before we start our project let's go up and add something to our page.tsx that's inside of the app directory so instead of just this opening main element here I'll paste in something simple and yeah very simple overall notice I just added some Tailwind classes to the main element then I added a paragraph with some more Tailwind classes a little bit of content just a hello and welcome notice my little space here with an HTML entity that helps me out with some spacing right after that emoji and then I've got a span element and it also has a class here from Tailwind that tells it not to wrap this text I want this to always stay together and then I made my name bold as well so just a quick overview of what we're looking at and let's quickly go to the layout.tsx as well and here I just want to add something to the body I'm going ahead and bring the children down here on a separate line but let's add a Tailwind class to the body and I'm using dark mode and that's really the only thing we need to change here so if we're in dark mode I'm going to use background round slate Dash 800 so we can see the text in dark mode as well because this will make the background darker and after that we can control in the back tick go ahead and start our project with npm run Dev it should pull up localhost 3000 here and then we can control click who launched this program application there we go starting it up and there we've got the Slate background and we've got our hello and welcome message here that says I'm Dave I'm going to drag this over to the right and hopefully we can continue to use that and here on the left I'll close the terminal I may sometimes hide the file tree but we'll be able to see our project on the right this way and our code on the left okay let's make eight components directory inside of the app directory so I'll create a new directory here and I'll name this components and then inside of components I want to create a new component named navbar navbar.tsx and then I'm going to go ahead and hide the file tree for a moment with control B now we can go ahead and create this component I'll type RFC using my es7 react Snippets and press Tab and it quickly creates this functional component now we're going to add quite a bit to this but this is a good start and so from here instead of a div I want to use a nav element so I'll just type in nav and press tab but then I'm going to add some class names from Tailwind to this so class name equals and I'll put in the quotes here I want to add a background slate Dash 600 adding of four make it sticky because it's our nav bar that will stick to the top I'll put the top at zero then and then a drop Dash Shadow Dash XL and then a z index Dash 10. I'm going to press alt Z also so this wraps down to the next line but those are the classes for this nav element after that I'm going to use a div element on the inside and the reason I'm going to do that is because I want the nav to extend all the way across the page but the div wrapper is essentially going to keep those icons and my name at the top within the same width that the article will be in the page and it won't necessarily be all the width of the page so that's why I'm going to do that so the first thing we're going to do here is apply that same class that we're going to apply to those articles and that is pros and I'm also going to use pros-xl just to tell it what size to use and then we'll go ahead and Center this with margins at on the x-axis of Auto make it a flex and then say justify between here it is and after justify between I want it to be a column and then I'm going to put in one media query here for small and for small it's going to be row okay so now we've got all of our Tailwind classes on both of those let's import Link at the top foreign at the very bottom here from next link we're going to use that link to create a link back to the home page so we'll say link this is href equals and then our slash here for the home page let's put in some classes on this as well so class name equals and here I'm going to say text Dash white but then I'm also going to put a slash and make it 90 percent opacity and then no dash underline for this link and then for hover I'll make it text Dash white so it gets just a little brighter so it would be at a hundred percent there instead of ninety percent then I'm going to put my name in here and so this should be at the left side of the nav bar when that nav bar is visible after that I'm also going to have another div inside of here where I can put in some icons later but I don't need to do that right now so we can just save this for now now let's show the file tree and we'll go to the layout and inside the layout is where we want to import and use this nav bar so at the top we'll say import navbar and there it comes from components nav bar and then we'll use this here in this layout and we're going to of course put it inside the body so we'll just say nav bar it will go right above the children there now we see it here at the top so we have got the nav bar that goes all the way across and my name here as well but if we make this wider let me take this to the full page you'll see that my name doesn't go all the way over here to the left and that's because of that prose class that we put on there so this will be the furthest left that any content really goes and we'll do the same thing with icons and they will go to the right eventually now let's show that file tree again with control B and we'll scroll down to the public directory inside of this directory I want to create another directory named images and then I'm going to drag over my profile picture that I'm going to use and of course you could put in your profile picture or whatever image you want to that's a very big picture here 600 by 600 that's what I'll be using here on the page and of course you should put in yours you don't want to use mine so now back in the components directory let's create another component here and let's just click that and we'll call this my profile pic dot PSX I'll once again use RFC from es7 react Snippets I'm going to press Ctrl B to hide the file tree so we can see the component better and now at the top here I want to import image from next slash image and next JS will actually help our images out and they can do that in several ways usually it would be by lazy loading the image when it's not part of the page but our image is going to be right at the top so you're going to see an attribute that we must add to the image file as we use the next JS image instead of your typical HTML image tag so now I'm just going to remove this div all together and I'm going to start with a section element here the section element will have a class or two so I'll say class name we'll set this equal to a couple of classes W Dash full for 100 width and then we'll use mx-auto so it once again centers this section then inside of here is where we're going to use the next JS image element and I'll put the closing slash for this element on a separate line in between here it requires several things that are missing and that's why we see the red squiggly line so for the source which is one thing we definitely need we need to say at images and slash profile Dash photo Dash 600 by 600 dot PNG of course you need to put your file name in that spot after the source I'm going to set the width equal to 200 and then I'm going to copy this down so shift alt and the down arrow and I'm going to change this to length so they're both 200 now for the alt attribute I am going to say my name because it's a picture of me you should probably put your name there now the other one that needs to be here because this is going to load at the top of the page so it's above the fold it will be loaded immediately next JS needs to know that this is a priority so we put Priority equal to true now we didn't add any class names yet and I've got a typo here I said width and length I should have said height there we go so I got rid of that and that's great here that vs code is helping us and I could see my mistake quickly instead of finding it later on okay I'm going to add the class names here at the top and I'll just say class name equals and I'm going to grab my class names because I've got several for this image and I'll just add them here and of course this will be available in the course resources I'm going to alt Z to wrap this down and you'll be able to see them all as well and we've got of course another arrow because I've got two quotes there but now everything looks good so essentially I put a border around the image and that border is rounded it's black when it's not in dark mode and it's a slate color when it is in dark mode and then we added some margins here as well okay let's show the file tree over here so there we go and now inside of the layout is where we want to put this as well so now I'll hide the file tree again and I'll say import my profile pic and now we will use my profile pic and let's put it right underneath that nav bar so here is my profile pic being in the layout now we know this will appear on every page as well and there it is so I am in dark mode so it's got that slate border around here and it's rounded but that worked out well for the page and when we create other pages with our Blog the image will be on those pages too okay we've added the picture let's finish off our nav bar I'm going to go ahead and show that file tree again we go back to the nav bar and then I'll hide it so we can see the code better and we put the link right inside the div and I'd like to add an H1 there and I've got a few Tailwind classes on that H1 so I'll just return here and enter that H1 and you see the different classes that are added again you can grab those from the resources if you want to or add your own then I'm just going to close the H1 out here and save and now we can see we've centered my name here and it's a little bit larger than it was before but if we make this larger it should go back to the left as well yes it's to the left over here but it's more of the mobile view now when we're in this small of a width here and so the name is centered and now we need to add one more dependency so I will open the terminal again Ctrl C to temporarily stop the server and let's install react icons so this is npm I and react Dash icons and press enter this should add this dependency force that will let us bring in some font awesome icons into our project so we've added that now back here in the nav bar at the top I'm going to use that and we'll start with the import of we're going to use four icons actually so I'll say import and we'll have f a YouTube and then we'll also have f a Twitter and f a GitHub and of course bring in the icons that are relevant to you and what you want to link to and then I'm going to use a laptop icon as well and after that it's going to come from react Dash icons slash fa because I'm using font awesome icons here and now I need to scroll down and after the H1 that we have right here but not after the div or the closing div we're going to insert another div with these icons so it's a parent element then inside that parent element we have links and each link has an icon and let me bring this to full screen it'd be much easier to see this part of it I'm going to alt Z so it wraps down or it is wrapping down there we go so here's what we've got is the parent div right here it's got several Tailwind classes then I create a link for each icon and you can see how I use the icon as well and so we've got one for each link and that finishes out out that nav bar save this and pull this back over and now of course we need to start the project back up to see the changes so npm run Dev once again it should start back up and we may need to refresh so it's going and we'll refresh the page here and let's see what we get after we get those new icons at the top and there they are all four right underneath the name in mobile view when we pull this to a full page they go over to the right here and that's why we have the parent div so we can put the space between these two elements here in a flex box but when we're back in Mobile and we have it right here we stack them on top of each other in a column okay let's close the terminal window once again let's show the file tree and go back to the layout and now I will hide that file tree and above notice the metadata that we have here this is just generic metadata so you might want to change this to be a little more custom for your blog I'm going to say Dave's blog and notice here we've got single quotes but then I can't put an apostrophe after my name if I do that so I'm going to change that to double quotes now I can have Dave's fog inside of here and then generated by or I might say created by and then just put your name here so Dave gray for the description and we save that and of course it should change what's at the top and now it says Dave's blog when we Mouse over our tab there at the very top and we have the basics complete let's do a little bit now with those markdown files so I'll bring this back to full screen show the file tree and now we want to create a blog posts directory now this does not need to necessarily be in the app directory or the public directory so let's just put it somewhere in the root directory here like RTS config.json is so here I can say logged posts and have that empty directory now inside of blog posts I'm going to create a file and we're going to call this pre-dash rendering but it importantly it ends with a DOT MD and that stands for markdown and now I'm just going to paste in the contents here but we've got a couple of important things here we've got an article or a blog post that is formatted with markdown if you're not familiar with markdown you should look that up there's several resources on the web it's what we make our readme files with notice the markdown icon here beside this readme file that we get with our basic next JS project as well so mark down something that you see all over the web and it's definitely good to learn and it's easy to write blog posts with and that's important at the top here we're putting some information about the blog post and we're going to use a dependency called gray matter to read the things that we put here at the top about the post so that's important as well that wouldn't be good just to have one blog post let's create one more file here and we'll call this ssg-ssr.md important to note that both of these markdown files are exactly what Purcell and the next JS tutorial provided in their previous tutorial that I mentioned at the beginning of this lesson that I am just updating for next js13 but both of these files have good information so I'm just continuing to use this content for the tutorial and it looks like I did didn't save this markdown file yet so I'll save that now after we have created the markdown files let's create another new file in the root directory and I'm going to call this file types.d.ts now our typescript config our TS config file is set up to read this pattern already that we see right here in the include part of our TS config file so we can put a type in here and it will be available to us this is a simple type it's going to be a blog post I'm going to set this equal to a type that has an ID that's a string we're also going to have a title like we saw in our blog post that's going to be a string as well and we're going to have a date that we saw in there and that's a string the ID itself is going to come from the file name so let's just save that type and that's really all we need in this file and now we need to create a lib directory in the root also so here we go with one more new directory and we'll name this lib lib and now inside of lib let's create another file here we'll call this posts.tsx this will have some functions for our post we need some imports at the top first we're going to write some node.js in here so import FS from FS after that let's import path from path and then we will import well we're not ready for that yet because we haven't installed it as a matter of fact let's add that dependency now so oh and I said parth you need to make sure that says import path from path okay so now we need to go ahead and install one more dependency so Ctrl C to stop the server and we'll say npm I I'm going to add gray Dash matter and after we add that we'll be able to use it and we need it in this file as we create a function so here we're going to import Adder from Ray Dash matter there we go and now we'll say const posts directory say path.join and now we say process dot CWD which stands for current working directory and then we're looking in our blog posts folder that we created over here that we see on the left so now we've got our post directory we're going to create a function export function and we'll call this git sorted hosts data there we go inside of this function and paste this in now I'm just going to review what we're going to go over here so what we've got is file names so first we get the file names under posts and again I should give credit here this comes or this function comes from that versel tutorial created by shoe and now I've just updated some of it to work with next js13 and typescript so here we've got the file names that we're using the fs and we're reading that directory and that directory is host directory here that we got the value when we get the current working directory here so we Define post directory pass that in we end up reading that and we get the file names there now all post data well we map over those file names we replace the dot MD which is the markdown extension for those files and that gives us the ID for each file and that's where that is generated now we have the full path which is the post directory once again and then we refer to the file name and then finally we have the file contents by reading the file this again is something you see with node.js and after we read the file we have those file contents that we can pass to matter that comes from that gray matter dependency and then we have the matter result and I'm noticing a typescript problem here blog post let me see if I typed blog post correctly in this types no I used a lowercase p this needs to be a uppercase B and then an uppercase P so I'll save that again and now let's go back here and everything should be good because that's the way we want to use it here at capital b capital P for blog post so we're defining our blog post here and it's type blog post here we have the ID title and date and we get those from the matter result that is read here from that matter function that we imported eventually we'll return learning the blog post that we read from the markdown file and that's what we really want and then we sort those posts too and notice this is allpost data.sort and then we have a greater than less than with the dates and it returns one this is a ternary statement by the way returns one if true turns negative one if false so this just Returns the sorted posts and again if I have gone too fast all of this code will be available in the course resources where you can review it as well and with our get sorted post data function complete we are ready to move back up here to our app directory and then inside the components directory where we have navbar and my profile pic and let's create a new file here and call it posts dot TSX but with a capital P for posts and now I'll use RFC once again and my es7 Snippets and quickly create that functional component at the top of the file let's go ahead and do our Imports here so we will import get sorted post data from our lib directory and then I guess that's all we're going to use for now we'll eventually have another one there then let's go ahead and get that information so I'll say const posts and I'll set this equal to get sorted post data and call that function notice I'm not awaiting get sorted post data we've already got that information it's right here on the server with our project so we will get that right away no need to use a sync a weight with that and then for our page I'm going to remove the div right here and I'm going to put in a few elements with classes you can see we have a section we have an H2 and then we start an unordered list right here and of course we'll have some information inside that unordered list and then I just need to close out the section here as well and with that I'm going to press alt Z to wrap the code down so you can see the H2 does close out there what we're going to do here is just map through that post data so let's say post dot map and then we'll have a post here Arrow over I'll use a parentheses and now here inside of the function we can say Json I guess I don't need curly braces there we can just say Json Dot stringify and then we can pass in the post and we can just stringify each post here we need lowercase here we go and of course it won't look completely formatted but we'll see what we get back from each one of these posts by doing that okay that said let's drag this over to the left and we need to add our posts then back into our page here right so back on the page that we have here inside of the app directory that is outside of the components directory we need to add that here so I will hide the file tree and at the very top we need to import posts and that comes from our components.post there we go and then let's just put the posts inside of the main element after our introduction paragraph here so this should be a list of posts but it's stringify Json data and now let's refresh our application over here and I don't think we started it back up no we didn't that's why it can't be reached so once again npm run Dev get the application started back up after we installed gray matter I don't think I had restarted that and with it running then we should be able to refresh here reload and there we go so it's not formatted but we see each blog post right here as a Json string now of course we don't want to keep this so let's close the terminal I'll drag this back to full screen for now show the file tree and inside components here we want to create a list item component that could be inside of our posts component here where we have the Json stringify with the post and that way we can format the post so here just inside that same directory let's create list item dot TSX now we can start out this file by typing tsrfc and that will go ahead and add props to our functional component right away and so with props we're going to go ahead and add our post and it's going to be a type of blog post after that let's put a space between and let's go ahead and add the Imports we need at the top as well or at least the first one and we'll import link from and that comes from next slash link there you go so we know we're going to get post from our props so we can add that in as well now inside the function we want to retrieve the ID the title and the date all from the post that is received now I want to format the date that we have here but I'm going to need to do that elsewhere as well so I want to create a library function instead of having to type out formatting twice so in order to do that I'm going to go back to the library here and then I'll create a new file inside and I'll call this git formatted date dot TSX now inside of here I'll paste the code in I'm going to press alt Z to wrap it down so you can see what we have here we're going to get a date string received into the function and that's just the date that we pass in it's a type string it's going to return a string but we're going to use this International API so we're returning New International Date time format I'm using the en-us because I'm in the United States you may want to use something else here then I can say the date style long and then dot format and you can see it wraps down here and I'm creating a new date and passing in the date string right here because it needs a date to format and it's a string so that's the full function and if you want to look up this international.datetime format on mdn if you're not familiar with it it's a great way to format dates so we create that git format a date we'll come back to the list item and now we need to import that as well so imp Port get formatted date and we can use this function now with our date so I'll say const formatted date and I'll set this equal to get formatted date and I'm going to pass in the date that we just received so now I have a formatted date that will look much better on the page now I'm going to remove this div in the return and I'll put in our list item and save so we get the correct formatting and let's break this down here so this list item because remember we're in an unordered list that starts in the posts component up here and we're going to pull the list item in so our list item here has several classes and we don't need this key here I had previously had that but we can remove that because we put the key in the post when we Loop through okay so here's the link and then after the link we're putting in a line break and then a paragraph where we have the formatted date notice I set it to the class text small so that date will appear smaller than the actual title of the post and notice it's going to link to a dynamic directory here this is a really important important part for next JS because we have the post directory I want it to link inside of a post directory but then it's going to link to a dynamic ID here so with that saved we'll go ahead and come back to our post and let's import that component that we can now use so we'll say import list item and we're in the same directory so now instead of the Json stringify we can just delete that and we can start our list item here and inside the list item we'll set the key and that's going to be the post dot ID here and after that we're going to say post equals post so we're just passing it down into the list item component and save and now things should look a lot better when we look back at our application and here we have it so here's our blog title here's the title of the article and here's the title of the second article with the small date formatted underneath now notice that we haven't created the pages these links would not currently work but we can see where they are linking to they link to posts slash and then they have the name of the file which was also the ID and that's what we're using as the URL is the ID and you see that as I Mouse over it's in the very bottom left of the browser corner here I'm going to bring this back to the full screen once again and we're ready to create our dynamic directory over here and we're going to keep that directory inside of the app directory so let's create this new directory first the directory posts and then inside the post directory is where we'll put the dynamic directory so here this needs to be inside of brackets I'm going to call this post ID and that should do it so we've got posts and post ID so now inside of post ID we want a new page.tsx now let's create our component with RFC and there will be many things we change about it along the way but it's going to be export default we're going to make this function async we will eventually need to use async await here and the name of the component let's go ahead and make this post now our component is going to receive params because this is a dynamic component so that parameter will come from the URL and then over here let's say the params type so we'll have params and then after that it's another object over here and that is post ID and the type is string okay let's go ahead and press alt Z to wrap everything down and keep it on the same page let's also create a little space in our function and we're going to need the posts again so let's define posts and we'll set that equal to our get sorted post data function and that should import automatically at the top and we can see that happen now I'll put a note here this is deduped we don't have to worry about sending that same request twice remember part of next js13 is request data where you need it we have requested this before when we went ahead and created that post list back on our page and we imported posts so this has already been requested so it will dedupe the request we've already got the data now after that we're going to need the post ID from params as well so here we'll say host ID and we will get that from the params that's de-structured now at the top I also want to import not found and if you remember not found that's when something doesn't exist essentially that's requested at a dynamic route so I'm importing not found and that's going to come from next slash navigation there we go and I should have put brackets around that also or curly braces not brackets but here we go so not found it's de-structured there from next navigation okay now we can use that in our functions so we're essentially going to see if we expect to receive that post ID we're going to check the existing post so let's say if hosts dot find and of course this is the opposite so we're saying if we don't find the post have post and for each post here we'll see if the post ID equals the post ID that we destructured from params and if it doesn't we're going to return not found that function so that could be our custom 404 so we're going to need to create that page as well so now in this same Dynamic directory we want to create that special not found page so here it is not and then Dash found.tsx and I'll just put in the simple code for it you can see it is a functional component and I'm just returning an H1 saying the requested post does not exist now let's go back to the page TSX with this much in place I'm going to copy the top part of this function right down to the posts dot find control C to copy and above this function I'm going to paste that as well and then of course I'll close out the function I'm going to just rename this function and this function could be renamed to generate metadata there we go and after that we're going to remove the async from it and the function starts out the same way so we'll have the post ID and the posts as well and then instead of using this if statement we're actually going to define a post so if we find the post we want to use that post and I'll just delete this part of the statement that came after it and now we can return our metadata so let's go ahead and put a return down here and we'll just return the title and it would be the post dot title but what if we do not have metadata oh and I should put a comma behind this as well I'm just used to doing that but if we don't have metadata we need to handle that as well so let's say if no post let's go ahead and return a different title and here we could say title and just say post not found and of course this would be the title for our custom 404 we would generate that metadata for it as well now I should mention you can go into the next JS docs and you could look up many more things that you could put in for SEO and for metadata as well so we're just generating some simple metadata here I did notice that we've still got a red line here and that's because I've got the default up here I don't need that either we can only have one default export per file with our generate metadata function complete we never really completed our post component here we've just started but before we can complete it we need to create one more Library function now we have get sorted post data but let's go back to our library and back to the post.tx we're going to put in one more function and it's a function just to get one post I'll paste this in it's very similar to the other and I'm going to need to go ahead and add a couple more dependencies remark here we see that line so we could do that first and then I'll go over the functions so let's open up the terminal Ctrl C to stop everything npm I and we're going to add remark and we're also going to add remark Dash HTML both of these will help us generate that HTML from our markdown files so we'll go ahead and press enter quickly let these dependencies install and then we'll have to go back and import those into that file as well so let's close the terminal and go to the top now here at the top of the file just two more Imports we're going to import remark that's going to come from Arc and then we're also going to import HTML from Arc Dash to find the dash there it is HTML so our Imports are complete now let's go back and go over this function a lot like our previous function up here that get sorted post data function so you'll see some of the same things happening here so we get the full path with path join and we use that post directory notice this post directory value was defined above the function it's up here at the top before this function starts so we use it in both functions after that we still Define the file contents we still pass the file contents to the matter function and that comes from Gray matter and then we have our matter result now when we use the matter result this is why we need an async function here so we have to await remark and then we chain dot use and we say HTML that's what we want and that's what we imported at the top so that's what we're using there and then we have dot process and we process this matter result for Content then we Define our content HTML and this processed content that we defined up here we passed that or we chain to string onto that so it's a string and that's what our content HTML is now notice we have a blog post but now we're defining blog posts with HTML so we just take that blog post type then we use the Ampersand and we add on the content HTML as a string for that type and this is the only place we'll need that so that's a good reason to do that not Define a complete other type as well and then here you can see the blog post with HTML just has everything the blog post had and then it also has the content HTML and then as we scroll we've just combined all of that and we return the blog post with HTML also notice that the get post data expects to receive an ID that is a string so it knows what post to actually get so now let's save this function and head back to our actual component here that is going to show it it's inside the dynamic directory so posts the post ID Dynamic directory and back to page.tsx and let's finish out this post component I'm going to scroll for just a little room and then underneath this if state statement we're going to get the title the date and now we'll get the content HTML and that's all going to come from awaiting get host data that we just defined we're going to pass in the post ID that we receive up here from the params now let's see if that imported at the top I'll copy that just in case it didn't it looks like it did not and it comes from the same file actually so we could just put it right here now we import both of those and yes no more error line there after we await that data and we get the date title and content HTML we want to Define the pub date this is our formatted date again so we could call it formatted date but I just called it Pub date here so we're going to use get formatted date and we're going to pass in the date once again now let's make sure that imported at the top I think it did and let's see yes it added it right at the very top so that's all good now we're ready to return some jsx here and I'm going to just replace the div with that now let's look at this quickly we have a main element with several Tailwind classes we have an H1 that actually gets the title of the article then we have a paragraph that gets the publication date then we have an article element this article element uses a section element where we use dangerously set inner HTML you may not have seen this before it is part of react and this is where we set the content HTML that we generate with remark and remark Dash HTML then we're using a link that goes back to home and that's the one thing we haven't imported yet and that's why we have a red error line there so let's go to the top let's also import link and that comes from next slash link if we scroll back down we should no longer have an error here as well okay with this much complete let's go ahead and open the terminal window again because we need to restart the project with npm run Dev and we'll get the project started here and we've got localhost 3000 I'll close this let me drag Visual Studio code over and we've got our project right here I'll refresh it just in case if we're waiting on anything and it looks like it's going to load all good let's see if we can see an individual article now so we'll click on one here's the article so everything is working like we expect it to but we haven't really built the project yet or looked at what type of server components we're currently generating remember we have that Dynamic directory that leads the post ID to our page.tsx here when we generate these articles from our markdown so maybe you can guess what type of components those are so let's go ahead and Ctrl C once again to stop the server let's run npm run build and of course once it finishes building our project it will display what type of components we currently have oh and I have an error in my build and that's because I put in that single quote as an apostrophe I should use the HTML entity here for an apostrophe so I'm just going to copy that that's a nice note here from the build error that we got so let's go back to the actual page.tsx and that's possibly where it is because there's one here when it says I'm and then we also had one inside of the layout TSX right here for Dave's blog so let's try it again I think it said that was in page.tsx so let's see if we can get by now without changing the other one in the layout let's give it another shot yes and the page build or the project built no problem now so it was that one inside the page.tsx we've got static Pages here indicated with the circle and we have server side render Pages indicated with this icon right here so let's look up here and see what we have it looks like our home page is static but then the posts slash post ID the dynamic are all server side rendered but this is a good example of a project where the SSR Pages can actually be SSG Pages because we know what blog posts we're going to have in advance so let's go back and make our site even more efficient by creating SSG pages from what our currently SSR Pages I'm going to close out of the terminal window and we should be back inside of this page.tsx so we have our post component and we also have our generate metadata function just above generate metadata let's create another function I'll say export function and this will be generate static params now inside this function we'll once again need the posts and remember we can request this wherever needed it is deduplicated so we're not adding any overhead by doing so and after we get the posts let's return post.map and we'll map over each post and then I'll use a parentheses and a curly brace here because we need a post ID and it will be equal to the post dot ID that we get from Post so we're returning this object right here and that gives us our static params so now let's go ahead and build this project one more time to npm run build and let's see what the results are and what type of server components that we now have and you can see already we no longer have the SSR icon down here we just have SSG and static so when I scroll up we can see our home page is static and our Dynamic directory in the pages within are SSG as indicated by this solid dot that we see here so let's look at our package Json and there it is I'll close the terminal window if we look in package Json we can scroll down here and look at our dependencies first we see we're using next 13.2 point four if you're watching this later on you may have a newer version but besides that let's look at our scripts and if we want to start our build we're just going to need npm Run start instead of Dev so control in the back tick once again and we'll just npm run start this should go ahead and start the build that we just created and it's now at localhost 3000. I'll drag vs code over let's look at this in full screen mode now that we've built it and here of course all the icons the name that links back to our home page let's so let's go to an individual article there's the article we could go back to home here or we can click up here and everything's working as expected and now anytime you wanted to add another blog article all you need to do is create another MD file a markdown file with that same format and it would be added to your website so you would just load it up to that blog post directory so wrapping up this project what could you possibly do to make it better well imagine if you had a lot of different blog articles in here you could actually create a search filter for those articles on your website that would be good you could also look at the extra SEO settings for that metadata and that is in the current beta docs for next js13 so you can check all of that out as well any other features you think of to make this project your own too it might help out but this is a great example of where next.js shines we just made SSG Pages they're already generated on the server in advance sent out to that content delivery Network and they're going to load fast back with installation instructions for lessons 7 8 9 and 11. so we'll type npx create Dash next Dash app at 13 .2.4 now here it's going to ask us some questions I'll name this next 07 and of course like I said these instructions also apply to lessons 8 9 and 11. and the only thing we're changing here is we're going to use typescript and eslint but now we are going to use the source directory as well so you can learn about that and we will continue to use the experimental app directory and we will use the import Alias and so now this is installing I'm in the next JS beta docs and as we see here under API routes it says API routes have been replaced by Route handlers in next JS 13.2 so the old API routes are still supported in the Pages directory and of course that no longer exists when you install a next JS 13.2 project however it says they recommend using route handlers with the app directory instead so that's what we're going to look at let's go ahead and click on Route handlers and as we bring this up I think this example can be just a little confusing so I want to talk about it here it talks about route handlers and we create route.ts or JS if you prefer but we create those files inside of the app directory but what it doesn't show is an API directory here but typically we're still going to create an API directory to put those in you don't have to though so I'm not saying you have to it's just that normally we would do that to organize but we're going to have that API directory inside the app directory and that's what you get when you start an example next.js project anyway and there is a note here about the route handlers as well they have these good to know notes throughout the beta docs and they are good to know so it says route handlers are only available inside the app directory so you're not going to try to create one of these new route handlers outside of the app directory at all again when we look at the example project there is already an API directory inside the app directory so now I'm back inside the new example project in Visual Studio code and notice we have this Source directory since I said yes s to the source directory this time and when we open it up inside we have an app directory right away so everything that you see here now is inside the app directory which is inside the source directory and that's the difference and one of the things we have is an API directory that's already provided and notice it has a new directory named hello so this is the slash API slash hello route so let's look at this route Note in this example get request we notice it's a get request right here they give the request object here and the type however you don't really need that so we can just remove it and this route will be statically evaluated and not dynamically and we'll talk about what dynamic routes are here in just a moment as well but this means there's essentially no variation in the request or the information that we depend on from those incoming requests it's always going to respond in the same way and without that information it can be statically evaluated now to try this this out we're going to need to go ahead and start our project so I will go ahead and open the terminal and then I'm going to say npm run Dev but we're not going to need to bring up the front end example page or anything like that I'm just going to keep it running here and this is a back end API endpoint just like if you were to create a rest API essentially so we can test this out with something like Postman or if you have the extension installed thunderclient and I have that right here as you see in my activity bar if you don't go to extensions and then search for under client I think is it one word or two it's two words so if you search for that you could find this thunderclient extension and install it you can see I already have it installed here and so I'm going to close out of that but if you use that that's what I'm using today so now that we've started our project let's go ahead and create a new request and here it has the thunderclient.com welcome we don't want that we're going to just have HTTP on our Local Host instead of https and then two slashes localhost Port 3000 and then we're at API slash hello and that should be sent to that hello endpoint that we have right here if we look back in the file tree we're at API hello and then the route dot TS essentially fills the same role for an API that the page.tsx does when we're looking at different page routes but you cannot have a route.ts in the same directory as a page.tsx you don't want to have a route and a page in the same directory so now let's go ahead and run this with ThunderClan I'm going to send the request here and we'll see the response we get back I'll drag this up we're not sending any parameters in the URL either so we send this and we get hello comma next JS exclamation mark right there and that's what we were expecting to receive because you can see how this endpoint sends that response now we're back in the beta docs and I'm going to scroll down just a little bit here on the same page where we were looking at Route handlers and we see static route handlers and that's exactly what we were just working with there they are statically evaluated when using a git method and we don't really need that request object in there so that's why we removed that just as we see with the example it's not in here so that's what we want but what if we want to send Json back notice they're using a next response and the reason we're going to use that we'll scroll down just a little bit further a typescript warning here in the betadocs although response.json is valid we're going to have an issue with it with typescript so for now we need to use nextresponse dot Json and they've extended the response type they've also done that with request but we don't need that at this point so let's go ahead and now put a Json response in our hello endpoint and we'll need to use this next response as we do it back in vs code let's go ahead and import our next response at the top so I'll say import curly braces and next response and that comes from next slash server after that we can go ahead and use that response instead of the response we have here so we'll just copy that and paste it in but then we're going to say dot Json and now let's send a Json object so what we want is curly brace and then I'm going to send message in quotes and then our response message here would be hello nextjs and then another curly brace and you can see I've still got a red squiggly because I need to remove the new keyword at that point so let's save this everything looks good let's go back to our thunderclient request tab here and we'll send another request to that endpoint and now we get our Json response here okay I think we've learned enough about our example hello route that we can create our own new route now so let's select the API directory here and then inside the API directory we're going to create another new directory so instead of hello let's call this one Echo and let's create an endpoint that Echoes whatever it receives or it echoes the parameters that it receives at that endpoint and we weren't sending any parameters with this request so that will be something new as well so now let's create a new file inside of this Echo directory and we'll call this route.ts as well so you can see it follows the pattern just like we did with our pages and always creating page.tsx files so I'm going to start by importing that next response once again and after that we'll go ahead and type RFC to get a export default function here and I'm going to make this an async function as well so I need to put that in and then I'm going to rename this and it's going to be get once again for this route and actually it doesn't even need the default for a route so we can just go with export async function and get now we want to go ahead and put in the request objects so we're going to say request in lowercase and that's going to be a type it is the request type the request object here and now we want to Echo any of the parameters that might be sent in the URL for a get request so to do that we want to get the search params we're going to destructure those so we'll say search params and that's going to equal a new URL and inside of this we'll pass in the request dot URL so now we've defined the search params that we are receiving and when we look at what type the search params are you can see they are URL search params and you could look that up on mdn as well to learn more about that but what we can do is use a git method so if I say const name equals search params.get and then pass in name it's going to return the value for name if that search param exists now I'm going to copy this down and do one more and here I'll call this instrument so we're going to get the name param and the instrument param if they exist after that we want to return those so let's go ahead and create this response I'll get rid of the div that we have here and instead we'll have next response dot Json and then we'll pass this object here that is name and instrument so let's test this out now and go back to our new request instead of the hello route we're going to go to the echo route now we can add parameters here in thunderclient below but you'll see them get added to the URL to see how that's created as well so let's go ahead and add the parameter here and the first one was name so I'll put Dave and notice it's being added up here so the first one you would have the question mark the name equals Dave now let's add another one I'll need to drag this down I'll have instrument equals guitar so then there's the Ampersand and then you put the next param and have that equal the value so now we're sending both of these params in the URL and that's how they would be received with a get request so let's go ahead and send this and see if it works yes they were echoed back to us name and instrument now the downside here is this isn't flexible it has to be name and instrument it's not going to Echo any other params it's only expecting those two when we look at the route we created so now let's modify this so it will Echo any param we send so I'm going to leave these individual lines that we're no longer going to use and just comment them out so you could see them inside of the source code for this lesson and I'll copy that down so I can comment one out as well and now let's go ahead and get the search param values in a different way so I'm just going to Define I I need cons there we go obj for object I'm just going to define a basic object here and I'm going to use object dot entries and then inside of object oh I said entries it needs to be ROM entries pardon me and then inside of that I'm going to have my search params and I'm going to call the entries method to get those values so now we've got an object that has those entries okay so now our response needs to be different as well instead of this object here with name and instrument it's just going to be whatever the object is now this will Echo any params that are received and just to verify that works let's go back to our request and let's change these this could be nickname and this could be Hobby and now let's go ahead and send these and yes it's echoed instantly nickname and hobby so any params we send we could change this once again to last name and let's change the value also so here I'll put gray and over here we could do something else like code equals often there we go and and it still works so it's going to Echo any params that are sent and we're back in the beta docs once again and now we're looking at Dynamic route handlers it says route handlers are evaluated dynamically when you're using the request object with the git method so that's part of why we removed it before remember when we saw this request in the request type with our get request just for that hello example and we didn't need that so we removed it so it would become statically evaluated however with the request object get methods are dynamically evaluated any of the other HTTP methods so post put delete options Etc any of the other methods are going to be dynamically evaluated and then also when you're using Dynamic functions that use cookies and headers and they give some examples so I thought about what could be just a good example of something you would frequently use one of these other methods for like like post and I think it would be to evaluate some form data so let's go back to vs code where I have a form ready to go okay we're back in vs code and you can see I am not in the API directory that's underneath app which once again I should remind you you don't have to create an API directory it just seems like that's the best way to organize it and that's the example the next JS gives us of course when they create the hello route that your example project usually comes with when you do the install however here we're in the app directory and now we're back to pages so I have a feedback route that has a page and then a thank you route that has a page and on the feedback route is where we have a feedback form now this is a react form I've got other tutorials on my channel that go about creating forms in react if you're interested in that and the change event handlers all of those things I assume you've already done some of that if you're at this next JS level of the series so I'm just providing this form you can look at it in the course resources but once they fill out the form then they would be routed to the thank you page of course but it is going to submit here in the handle submit it's going to send this to our feedback route that is at API slash feedback so that's the route we now need to create so let's go ahead and go into the API directory create a new directory named feedback and inside of this feedback directory will create a new file and it will be a route.ts file let's once again start by importing the next response that we're going to use and after that import let's create a type so our type will be feedback we'll set this equal to a type that has an optional name which would be a string and now I'm going to use shift alt in the down arrow twice because we'll also have an email that is optionally there and we'll have a message as well so this is our feedback type it will have a name email and message all coming from our form and they might be undefined now we're going to require them in the form so I'm actually being just a little safe here in saying that they might be undefined but we'll go with that and now we'll say export async function and this will be a post request that we're going to receive it will still have the request object though and we can just use the standard request instead of the next request but that is also available to us from next.js now let's define the data that we're going to receive and it's going to be of the type feedback we'll set this equal to a weight request.json now this is different if you're used to working with say a framework like Express and it took me just a little bit to get used to it as well because I'm used to getting things from the request.body so this all you need to do is call Json here on the request itself so just a little different now let's go ahead and log to the console now remember this is on the server side here this is our back end so when we log to the console this will show up in the terminal window that would be the console for the server so we'll log this data after that we can get the name email and message we're destructuring now from that data and once we have that let's go ahead and well we don't really need to log anything else here I guess we've got it all above so we you could log any one of these just to confirm you're getting a value if you want to then let's go ahead and return our next response dot Json and this will have the name email and message that is being sent back now of course at this point you could process the form data you could save it in a database you could do anything you want with it we're just going to respond again kind of echoing that same information just to show how this post request is received and how it works and how you can get the data out of it okay I need to open a terminal window and restart the server here after I added Tailwind to the project with that form I added so I'm going to go ahead and type npm run Dev if you don't have yours running go ahead and start it as well once we do that we're going to now go to our localhost 3000 in the browser with control on a click and then we want to go to our feedback page so we need to go to that feedback route that we created and here is our form I'm going to open up the console here too because I put a couple of console log statements in that as well so now we could just put Dave I could have Dave at davegray dot codes and then I can just say hey there and now it's ready to submit I submit and yes we got our thank you for your feedback page but we also have the object here in the page.tsx so this was logged in the front end and then we have what is received this is also in the page.tsx but it's received it's the result from the request after we get the request back so that's that Json that's sent now let's go back to vs code and we'll look at the terminal and see what we got there as well and you can see here we had the data logged as well so this is the console log message that is inside of our route here for our feedback as well so now we close this out you can see where we logged that data so that's how the post request works with the form and of course you can look in the course resources and look over that form on the front end part for react as well that is a client side page by the way because it's interactive so at the very top you need use client as any page needs to be that has that user interaction so pointing that out as well but back here in the API we created this post route now and this is also how put and delete and the other methods would work besides git so I wanted to make sure to show you both get and post in the last lesson we learned about the new route handlers in next js13 they help us build API routes and today we'll build a rest API with next JS but before we do we should discuss some use cases for an xjs API and we should also discuss what we don't need to use an API for there is no need to use an API route if you're fetching from a server component if you're using a secret API key or a secret URL it will already be hidden on the server it won't be viewable in the client-side code and second if you're not hiding an API key or a secret URL you can also fetch directly from client components without using API routes in your app so likewise a couple of common uses for API routes in an xjs app are to hide secret values like API keys or secret resource URLs and we also previously covered when introducing route handlers that we might also process form data with an API route so as an example of when not to use an API route out I am in the previous docs here not the beta docs and we're on the when should I use get static props page well we're not using get static props in next js13 with the beta docs and the new features we're going over instead we're using generate static params and when we've used those that data must be available at build time just as they note here it used to be needed to be available at build time when using get static props and you know if you're building your app well that data won't be available from an API route because it's being built at the same time so that's going to result in a build error so that's one example of course I already recommended not using API routes for Server components but if somewhere along the way you get confused and attempt to do that and then you're requesting data from an API route that's being built well the server components need that data available at build time to generate those static params I am back with more in installation instructions and I know in the last chapter I said I was providing the instructions for chapter 7 8 9 and 11 but there is one thing I did differently in chapter eight that I forgot so let's go ahead and do that and you'll see why we need to make the change so we're going to start off with npx create Dash next Dash app and now this is going to be at 13.3.0 and now with this install it's going to automatically add tailwind and that was something new with 13.3 and then you'll see what we do with it afterwards so let's go ahead okay to proceed we'll call this next08 we're going to use typescript we'll use eslint and now we can say yes to Tailwind so it's automatically going to install Tailwind for us if we do this and we'll say yes to the source directory we will say yes to the app directory that once again is no longer experimental once you get to version 13.4 but currently with this install it was and now with import Alias we'll say yes as well and now it will begin to install okay now in vs code I've got my next08 folder open and notice in the package Json we have next 13.3 now we're going to make an adjustment here because there's a small problem they have a bug currently with the delete route Handler and I filed an issue for that already on GitHub and hopefully they will fix that soon but currently if we await the request.json it throws an error and it works in 13.2.4 which was the previous version so I'm just going to go back to that now if you're watching this in the future hopefully you're on a newer version than even 13.3 and you won't have that problem so you might try that out before you roll back to a different version I'm going to press Ctrl and backtick to once again open that terminal window I'm just going to type npm I and then next at 13.2 point 4 and this will roll us back to that previous version where the delete route Handler is still working as expected with that request.json so now I'll close the terminal and we can see that I'm once again for this tutorial using 13.2.4 now just a side note on that install we did of 13.3 where it added Tailwind notice we didn't have to manually do any of that we already have a Tailwind config file and then if we go into the source directory and look at our Global CSS it already adds the three lines we were manually adding before so that's just a nice addition that they added in 13.3 where we can choose to add Tailwind basically effortlessly to our project right at the beginning when we created now we're going to create five rest API endpoints today in next JS and we're going to pretend we're using these routes to hide a secret URL resource and even send an API key with any request that's not a get request but first let's discuss environment variables okay now I'm back in the stable next JS docs not the beta docs and it says they get the environment variable values from dot env.local that's where it will load them and we will format them like this so environment variable name equals and then value notice there's no quotes here so that's how we will put them in our DOT env.local file also note that after we create this file we will want to add it to our DOT get ignore file if it's not already in there but we'll take a look because I think we already have a DOT get ignore file and of course that keeps this file from being loaded into GitHub with your repository because you don't want to share this information with the rest of the world not even in your GitHub repository and now I'm back in the beta docs under static route handlers and I just want to show an example here of where they're providing an API key in the headers of their request so this is how we will access that data from that dot env.local file will say process.env dot and then the name of the variable we gave it not the value but the variable and then it will put the value in our code where it's needed now we're back in vs code we do have a git ignore file so I'll click that and as we look at this file this lists out any pattern or extension or exact file for that matter that we do not want included in our GitHub repository and here it has local EnV files and we can see dot EnV then an asterisk dot local so you could even have something after this or more than one EnV file but we can just create a DOT env.local and put our value in there for today so let's do that by creating a new file here at this top level of the application all this Dot env.local and then we're just going to say data underscore API underscore key which I believe was the same variable that we saw in the doc there and we're just making one up and you can put anything you want here it's usually a long random kind of looking value but what I'm going to put is Dave Gray teaches code and I'll just have that be the value because we're just going to log this to the console we just want to make sure we know how to do it and send it in those requests now let's begin creating that backend API inside of our API folder that's inside of the app folder so I will highlight that we have the example hello folder or directory if you will let's highlight the API folder and let's create a new one here and let's call this to Do's because we're just going to get the example to Do's from Json placeholder and pretend it is a secret resource now inside of this to Do's directory let's create a new route file so we'll need route.ts now before we begin building the route let's go ahead and create our types dot d dot TS file that we're going to use so I need that in this top level once I'm down here I'll just type types.d.ts and inside of here we're just going to have one type today and it is a to do set this equal to a type that has a user I D that is a number then we'll have an ID and that's a number a title that is a string and then a completed and this is a Boolean and now we're ready to go back to our route and we'll start adding some code here and we'll create the first route which will be the get route but we'll start with the import and we need the next response that's going to come from next slash server after that we'll go ahead and Define our data source that we can use in each of the handlers so I'll say const let's call this data underscore Source underscore URL and let's set this equal to that Json placeholder URL I'll press alt Z so it wraps down but you can see jsonplaceholder.typical.com to do's and this will give us 200 to Do's that we can request and of course send all types of crud requests too so create read update delete so now before I begin the first route Handler you might want to use this tutorial as a challenge so maybe you want to pause here and try to create the route Handler before you see how I create it so this will be the get request where we will request all of the to Do's now you can go ahead and do that first if you want to or just follow along with me we'll start with export once I get lowercase async function and it is a git Handler now we're not going to send the API key with any git request so here we can just get our response right away once again lowercase and I'll just call it res for response that's going to be a weight Fetch and we're going to fetch the data source URL that we have above and it's just a simple get request to to do so we don't need to add anything there and after that let's define our to do's and it is a type of to do that is an array of to do's and we'll set this equal to a weight and once again response then Json so we get that Json response there and then we can return next response dot Json and just pass in the to do's and that should finish out our simple get request route Handler let's go ahead and test this Handler so we need to start our application with npm run Dev and once it's running we're going to use well basically anything we want I'm going to use thunderclient you could use Postman if you're more comfortable with that or there are some other extensions that also allow you to issue requests we'll be looking at localhost 3000 and then slash API slash to Do's so I'll go ahead and close the terminal I'm going to use thunderclient which I have right here if you don't have the ThunderClan extension and want to get it you can search for it in your extensions it's two words under client there we go and it looks like this you can see mine's already installed and enabled good to go so you'll see how I use that I'm going to choose thunderclient here from my bar and then I can issue different requests I'll create a new request here this will be localhost 3000 then slash API slash to do's and now we can just send the request and I have an error because I left the s in the HTTP I need to remove that because here on our local host and if we look back at our terminal we'll see it is just HTTP and not https so we'll close that out again and hopefully I won't make that mistake again but it's very easy to do but here we got the 200 response and we have all of the to Do's we've received you could scroll through all 200 of those if you want I can even drag this up a little bit higher if we want to and of course with the other requests we'll be sending a a body as well so we might need a little room for that but that works as expected so our get route Handler is good to go okay let's go back to our route TS file and now we'll go ahead and create the delete route I'm going to scroll for just a little room here and now at the top we'll type export async function and we'll use the delete route now this will receive the request and it is a type request now we need to receive the ID in this route so we know which to do to delete so I will destructure the ID that is coming in and this is going to be from a partial to do type we'll set this equal to a weight request.json now just to note here this is the portion that currently just the very new version 13.3 is having an issue with so this is why I rolled back to 13.2.4 right now if you're watching this in the future hopefully there is no issue but if you're watching this around the time this tutorial was just created you may need to roll back to 13.2.4 for this portion of the code to work in the delete route Handler so now we need to check to see if we received an ID or not so here we'll say not cost I'm sorry but if we do not have an ID then let's return a next response dot Json just with a message that the ID is required so we'll say message and here we'll have to do ID required and there I am using single and double quotes let me just select that so I'm consistent and switch those to double as well so that's the message if that ID is not supplied with the request but otherwise we can await fetch once again and here let's create a template literal and we'll pass in that data underscore Source underscore URL after this the way the API works that we are requesting from needs it needs to receive that ID value right here inside of the URL so we'll put that but then we also need to put some options with the fetch so here we'll have method and that is delete after that we need headers and we'll be using these on all of the requests that are not get requests here we'll have the content Dash type and we'll say this is application slash Json and after that we'll have our AP Pi key now this is not really necessary for the Json placeholder API that we're requesting from but this is just an example if we needed to send it because this API won't complain when we do send it now I'm setting it equal to API key but we haven't defined that yet so let's do that at the very top of our code where we defined our data source URL as well we'll say const once again lowercase Now API key and this is going to equal well let's say it is a string first too because we want to set the type and this is going to equal process.env Dot data underscore API underscore key that we set and now notice we still have a problem with typescript because it says string Union type here with undefined can't be assigned to string so what we want to do here is an assertion so I'm going to say as string and now this will be okay with the API key now let's scroll back down and finish our delete route Handler so we have the await Fetch and after that we don't need to do much more so we're just going to return nextresponse dot Json and here we can put in a message once again because we won't really get anything back from the API when it deletes something but here we can just say again a template literal and I'll say to do then we'll pass in the ID value and deleted and I can tell by the red in the file name we still have an error and when I look over here where I scroll I can see that dot is right here and there is the error I did not put a comma before I put in the options with the fetch so you need to have the URL comma and then the fetch options object so now let's save this route and we want to make another new request to test this out so here I'm going to switch the method to delete and now we need to pass some Json so we can't just go to slat well this is actually going to just go to our API slash to Do's once again because it's just the delete Handler for that but when it gets sent to the actual Json placeholder here in our route it needs that ID so we need to send the ID in the body because that's how we're destructuring it here from the request.json so now we'll go to the body I need to drag this down and let's just send an ID to delete so this needs to be valid Json here and we'll just say delete to do number five you can see that X went away over here once I had valid Json there the x is back saying this is not valid now when I put that in there it is valid so we're sending a delete request with Json here in the body of id5 and it's going to our API route in our next JS app which will then go ahead and make the request to that data source URL it is our hidden resource so now let's send this request and we've got our message back message is to do five was deleted now of course since we're working with this Json placeholder site it doesn't really delete the to-do's but we do get the success for the status and it gives the appropriate response for each crud method create read update and delete and so on so we know we've got that and now we are ready to build our post request route Handler so I'm going to highlight all of this from line 15 down to 29 use shift alt in the down arrow to copy it down because there are a few differences from post and delete but we can certainly use this to start out without typing everything all over so I'm going to choose delete here and switch that to post it's going to once again receive the request after that it's not just getting an ID as a matter of fact it doesn't really need to get the ID that will be assigned because it's a new post it does need to receive the user ID it also needs the title of the to do and now once again we need to check to see if we received this data so here we can say if no user ID or if no title and then our message isn't quite right so instead of to do ID required we can just say missing required data and now we're going to send a fetch again but we want to get the response so let's say const res equals and we'll await the fetch now this resource the data source URL is the same but we do not need to append an ID at the end so I'll just remove all of the template literal information and we'll just send that directly to the data source URL and now the method needs to be switched to post and after that we'll have the exact same headers but now we're also going to have a body that we send here so the body will have Json Dot stringify and we're going to stringify the data that we are sending so we're going to send user ID and we're going to send title and we'll also send completed faults because every new post would be false it would not be completed yet okay and now with that new response we've got we can say const new to do and it is the type to do set this equal to awaitresponse.json once again and now our message just needs to be changed here and what we want to send back is that new to do that was created so we can just put that in the response and now we're once again ready to try out our route Handler and this is a post so let's go to new request instead of an ID we're sending a user ID but then we're also going to send a title and I'll just have something simple here like make the coffee Okay so we've got what's required here user ID and title being sent in the body and once again this is going to go to our next JS back end and API to Do's we just need to pick the appropriate HTTP method which is post and then our route Handler will take it from there so let's go ahead and send this and we've got a 200 it was successful and we received the new to do in return and you can see it was ID 201 so that means it was added to the 200 that were there now of course Json placeholder doesn't really add the to do so next time we would send a new one it would also have the ID 201 it doesn't really add to its data but it gives you the success like it did so I can send it again and we still get 201 back let's go back to our route TS file and now we're ready to create the fourth route and the final one that we'll add to this route TS file and this is the put request route Handler so I'm going to go ahead and highlight all of the post down here to line 34 press shift and click and now do shift alt and the down arrow to just copy that full post request down because put is very similar now once I'm here I'm going to change the post to put and the put request needs to receive everything about the to do so we're going to have an an ID a user ID a title I'll put the ID in between in the same order that we did the type I believe and after that we're also going to have completed so that makes this not a partial to do but the full to do type right here now we need to add some more checks for missing data so we can check to see if the ID is missing as well so we've checked the first three here now we can't check the completed in the same way because if you just put an exclamation mark with Boolean when it would be false it would become true and so on so what we need to do here is you could really check to see if it is the type of Boolean and that's what I'm going to do you might have another check in mind as well but that's what I'll do here so type of completed we'll just make sure it's either true or false so if it's not equal to Boolean we have a problem now the message missing required data is fine so let's scroll down here let's switch the method to put once again we'll keep the same headers where we're sending our fake API key and now we're going to stringify what we're sending as well so we're going to send user ID title and completed and I'm going to change this to just say it's completed whatever value we receive will be what will be updated so we'll just leave it as completed now notice we're not sending the ID because we need that back in the URL once again like we did in the delete request so I'm going to copy it down here the data source URL and that ID needs to be right at the end so Json placeholder knows which to do to update so I'm going to just select data source URL and change it to our template literal that includes the ID at the end of the URL now at the very bottom while this would work it just doesn't seem right to call it new to do because it is the updated to do and then we'll just copy that and that will be the response as well so it will just send back the to-do that was updated with the new information so now let's once again go test our route so from here we're sending a put request it's the put HTTP method once again to the same URL for our next JS API that will then handle it in the route Handler so in the body now we don't just need user ID and title we need to go ahead and add the ID as well so we'll say post ID 5 is fine and then we need to send completed which has to be either true or false so we'll say completed and we'll say this is true and that's not going to work so we need lowercase true I was typing uppercase true because I was just working python as well and that's what that's what it likes so once again back to JavaScript typing true and lowercase okay we're ready to send our put request that will update the to do with the ID of five let's see what we get and it was okay user ID 5 title make the coffee completed true and the ID of the to do is five once again Json placeholder doesn't really update the data that it has but it sends us a response as if it did now if you wanted with each of these handlers you could also go through and test to make sure that our messages for when it doesn't receive data that it's expecting works so here instead of sending Boolean data I'm just sending my name when I send that we get that missing required data which it is missing I guess but we could get more specific if we broke that down into a statement for each one instead of one statement that handles all of it but either way I believe you understand the concept of how to do that we're now ready to create our last route Handler but it doesn't go in this route TS file so let's go back to the file tree and take a look at what we have here and we're inside of the to Do's route and then we go to the route.ts file but we could also create a dynamic Dynamic route in here so I'll select that to Do's directory and create another directory that has a dynamic route based on the ID of the to do and then inside of this directory I'm going to create another route.ts file now this file is going to start much the same as our other route so I'm just going to go to the top here and copy everything from the top line all the way through our git Handler so I'll just Ctrl C come over to this new file and Ctrl V to paste it in now we're not going to need the API key so I can delete that this get request is actually going to need the request so we're going to put request here and have it be type request that's because we need to get the ID from the request because it's going to be in the URL for this Dynamic route so here I'm going to say const ID and I'm going to set it equal to the request.url now this would be the full URL as string and then I can say dot slice and I'm going to slice the request dot URL and then use dot last index of and I'm going to look for that last slash that is in the URL because after that slash is actually where the ID would be but with the slice method we're telling it where to start not just where to end so we don't have to put in an ending we just need to tell it where to start is what I guess I'm trying to say so I don't want the slash I just want to go plus one and have it start and get everything after that whether it's the to do ID number 200 or the to do ID number one so it could have as many digits after that as it wants and we would get all of those we just don't want the slash okay now that we have the ID we need to add that once again to our data source URL so I could go back to where we've typed that just so I don't have a typo and we can get that from one of these other methods that used it so here is our template literal that has the data source URL and the ID so I'll control C to copy that come back back here and I'll replace this data source URL with the full template literal and now we're just going to get one to do back because we're only requesting one so I'll make this a to do and instead of an array of to-do's it's just one to do so that's what we expect there now we need to just check to see if we do not have a to do if we don't receive one back so let's say if no to do dot ID that's what we'll check to make sure we have it to do we'll say return nextresponse dot Json and we can provide a message here I'll say message and this will be well let's put that there we'll just say ID not found or we could say to do not found do not found and that would work fine I'll press alt Z to wrap that down and then if we do have a to do we'll reach this final return here at the bottom and we'll just return that single to do so now we're ready to test this route Handler out and it's going to have a different URL it will be basically the same URL as before where we look at API to Do's but then we'll go ahead and add the to do ID at the end of the URL for our next JS app so when we send this request we'll have API to do's and I'm going to request say to do number 199. this will be a get request let's go ahead and send that request and we've got 199 back from the Json placeholder website Okay so we've created a very simple API where we're simulating relaying information from a third-party secret resource or pretending to get data from a database and of course we're practicing sending an API key as well which by the way you could console log that API key to get that value in your console that we would see here in the terminal for next JS that would be the console where you would see it but you can take the next step and do either of these by accessing another third-party API that you really do have an API key for say you're getting a weather information for a weather app or something like that you want to hide your API key that would be perfect for this or you just want to hide the actual resource that you're using in your app and of course by keeping that resource URL on the server that will never be sent to the client and your users couldn't find that in your code so next JS API route handlers can be very useful people and in the next lesson we're going to go over middleware that can also be very useful today's starting code is the completed code from the previous lesson on building a rest API and you'll find that completed code under lesson 8 in the course resources and note that I'm still using next JS 13.2.4 today the new 13.3 still has some unresolved bugs and if you're watching this in the future hopefully they've moved on from that and there are no issues to consider however if you're watching this as it's a brand new video then consider going to 13.2.4 for now one other quick note from the last lesson before we get started on middleware so I want to go back to the API folder that's inside of the source and then app and then API and then let's go to to Do's then let's go to the dynamic directory the dynamic route for the to do ID and look at the route file route TS I'll press alt Z to wrap any code that you can't see and in the previous lesson I got the ID from the request like this I didn't consider it to be too complicated just using the slice method on a string however some noted that we could use the second parameter here inside of the route Handler that is the params that allows us to get the ID as well and yes you can do that and that's probably the appropriate way in next JS and maybe this was an old habit but at least I showed an alternate alternative way to do that so I'll comment this out and let's go ahead and do what the next JS way with that second parameter to start since I'm using typescript I'll need to put a type above so I'll just put type props and I'll set that equal to a type that has params and then we have the prams object which is ID and it will be a string now this is something you had seen me previously do in past lessons for a dynamic route that we used on the front end but you can do this with the route handlers as well so that's what we're doing right here so so the second parameter here after the request is an object that has params and then the params object we can destructure the ID from and then over here we just need to say this is type props and now we have the ID ready to use so again from the previous lesson you could get the ID from the request URL as I did here with the slice method or probably the appropriate next JS way of doing things would be to use this second parameter in the route Handler with the props here and destructure the params to get the ID that way so let's save this file and now let's move on to middleware I'm in the beta docs and in the last lesson we built a simple rest API with the new next.js route handlers and if we look at these beta docs we can see for middleware they just have a to do that's not very helpful right now but this may have changed in the future if you're watching this tutorial so always reference the docs but this is still going to let us go back to the stable docs and learn learn some more about middleware now I'm in the stable docks for next JS and note that they do have version 13.1 and version 13.0 noted here in the stable docs and while we're not really going to use these Advanced middleware Flags today when we talk about middleware and create some middleware we are going to use this feature that was added with 13.0 where middleware can modify request headers response headers and send responses we'll definitely be doing that so let's just scroll down on this same page and it talks about using middleware and we already have the experimental version installed remember I'm using version 13.2.4 of the experimental app right now with the betadocs you can ignore this but other than that we do want to create a middleware.ts we are using typescript in this tutorial series at least if you're not you could use dot JS but we're going to create this middleware file and they give an example of some middleware here and we're going to follow this fairly closely one thing that is different is it says it needs to be at the same level as your pages in the root or Source directory well we don't have Pages anymore but we'll still put it in the source directory because that's what we're using or what we used in our previous code that built the rest API we're back in vs code so now let's go to that Source directory not the app directory but the source directory if you're not using the source directory you would just create this file in the root directory just where we see TS config and the readme.md and all of these files but since we have a source directory it's going to go in here so now we'll create a new file and it has a special name which is middleware.ts and now we'll create the function by typing export function and this could be an async function if we need it to be then it is the middleware function it's going to receive the request which is a type request and then of course we have the body of the function we're also going to need the next response so let's go ahead and import that with import and then we'll say next response and that comes from next server so now we have that as well and we're ready to do something inside of the middleware to start off with let's just create a few console logs to see how this works I'll say console log and I'll just say middleware here but we've also got the request and that means we can get some information about it so let's console.log request dot method and I'll shift alt in the down arrow because let's also get the request URL and this means the URL that is being requested from our application after that let's get the origin if it exists so I'll say const origin because this will come in handy we get this from the request headers which by the way you could log these headers to see what other useful information is available in them here we'll say get because it has a get method and we'll get the origin value if that origin exists so as I Mouse over you can see it's string or null right now it doesn't necessarily exist but if it does we'll log that value as well so we'll say origin here now let's just return our next response and we'll call next which means just move on to the route like it was supposed to let's go ahead and test out our middleware by opening a terminal window typing npm run Dev and with the application running then I'll go ahead and click localhost 3000 I need to control click there it started and we see several requests rolling through the middleware already so any one of these URLs that was requesting some type of resource applied to the middleware as well and that's the thing about that middleware file is it applies to every request on the web page not just the request to our API so I should say every request for the web application not just the page and that means we might want to limit where that middleware is applied because right now all we did is load the home page and we're seeing all of these requests roll through the middleware and surely some of those we don't want there so I'm going to go ahead and stop the application and close the terminal window and now I'm back in the next JX stable docs and here we're talking about matching pass so note it says middleware will be invoked for every route in your project and that's what we just saw for every resource needed that middleware file was invoked and that's not necessarily what we want we want to pair that down to probably just our API routes today but you may have other needs where you need to specify where it applies this will help you do that and there's actually two ways to do it one I'm just going to scroll up instead of down to show a very simple way you see this matching paths here where we Define a config and then it has a matcher defined now as we discuss this matcher it can be constructed in several ways it can be a static match just without any parameter like you see here with path or the asterisk it could just be a static route that is provided here however this path parameter with the asterisk could be very useful so let's see what that's about as we scroll down here and they discuss the matcher a little bit more you can see it can also be an array so there could be more than one path that matches or one URL in the or end point if you will and it also accepts reg X so you could even do something here like a negative look ahead which is a little more complex when you're working with regex but there's many different options but essentially let's talk about this path if we can find where it's discussed a little bit more essentially this path parameter matches anything after about Slash so it matches about a also matches about B but it doesn't match about Slash a slash C however if you put the asterisk after it that does match anything that might even go deeper into directories like slash a slash b c because the asterisk is zero or more now you can look here in the docs to find more details about that but that's basically all we're going to need today is something just like you see here with the slash about Slash path and then we put the asterisk which means we could have nested directories deeper than so now I'm back in our middleware file in vs code and let's go ahead and apply a matcher so I'll say export const config and we'll set this equal to an object that has a matcher and with the matcher we'll set it equal to slash API slash and then put the path parameter and we'll put an asterisk there as well so that means basically any route we have inside of our API folder will be caught in this middleware file will be applied to it so now if I go ahead and restart our application we shouldn't see the same thing we saw before I start with npm run Dev once it starts and if we request this localhost 3000 page so I'll control click and it goes ahead and loads in the browser notice we don't see all of those requests coming through or all of those console logs we have in the middleware file because that home page although it opened in my browser and I'm not looking at that right now I'd rather a look at this to see the output we are seeing no console logs because that middleware file is not being applied to that path in our application okay I'll close the terminal window and now let's talk about the second way you can optionally apply this middleware file to only specific paths we can use conditionals to accomplish the same thing or to apply specific things to other routes as well so inside of our middleware function I could say if the request dot URL dot includes and then if I wanted to just blanket our API routes I would say slash API slash and of course that would be true or false and then we could put everything else inside of this if statement if we wanted to so this means we wouldn't need this config with the matcher here if we didn't want to use it that way we could just use conditionals or we could just use the matcher or you can use a common nation of both another example would be to create a reg X so let's say if I said const regex equals and then make a new reg X which it's a regular expression and then I made this expression slash API slash with the asterisk after it here so now that I have that we could test that inside so instead of the request.url dot includes we might say regex DOT test and then we pass in the request URL and of course it's testing to see if it contains this pattern or if it matches that or not so a couple of different ways to accomplish the same thing I'm going to leave this here for now because we will be coming back to this middleware file to apply a conditional statement later and now that we know how the middleware file works we can consider adding some useful middleware with it but not all middleware works with this file so we'll come back to this file for now let's look at a middleware dependency I'm on npmjs.com where we can look up different packages that have already been created that we can use as dependent agencies in our application here I'm looking at limiter it's a rate limiter that we can use in our application and this is something you would easily use in a nodejs and express rest API but we can use it with our next JS rest API as well you can see the install here is npm I limiter so we're going to need that to add that and you can get details here but I'll put this link in the description for the video and the course resources and besides that I'm going to show you how to apply it so let's go back to vs code we're back in vs code let's open up the terminal window again Ctrl C to currently stop the application let's type npmi limiter as we saw in the npmjs website okay it says it's installed let's check that in our package Json which is always a good idea after you install something and yes we see limiter is now listed in the package Json dependencies and I'm back in the next JS docs now it would be very convenient if we could run that rate limit which will protect our application from being overloaded with abusive requests but it would be convenient if we could run that rate limiter in the middleware file but it has a dependency on node.js that won't work in the edge runtime and that is where the middleware actually runs in the edge runtime at least that middleware file so we're going to have to apply that dependency for limiter inside of our routes instead okay we're back in vs code so now let's go to our routes so we're at source app API and then we have the different routes inside of our API directory now what I want to do just inside of the API directory itself is create another directory and I'm going to call this config and then I'm going to create a file inside of config and I'm going to call it limiter.ts now inside this file is where we're going to create our limiter instance or you could have multiple limiters and you could create one for each different route if you wanted to apply different rule different limits to each of those routes here I'm just going to create one so I'll say import rate limiter comes from limiter after we get that we'll say export const and Define our limiter because I'm only going to use one so if I created one just for a get route or a post route I might say git limiter post limiter or if it was a specific route I might say get to Do's limiter or something like that or get hello limiter but here I'm just going to say limiter and I'm going to say new rate limiter and then inside of this we'll pass some options one is tokens per interval and here let's start out with something small like three so we can see how it works after tokens per interval let's create the interval itself and we should be able to see those options here and yes we do so there's day hour minute second and for now I'm going to choose minute so we've only got three tokens per minute right now after that one other thing to make this work asynchronously and go ahead and continue to the rest of the code or of course to remove tokens immediately we want to put fire immediately here and I'll set that to True also okay now let's go to our simple hello route that comes with every next JS application currently when you build one and we see the hello route right here at the top of the file we need to import our limiter I'll say import and this is limiter comes from config limiter where we have it and then inside of the function there's a couple of lines we could put well really only one line we need but if we want to see the result then we'll put in a console log as well so I'll say const remaining and we'll set this equal to await limiter dot remove tokens and we'll just remove one token so you could remove more than one but we'll just remove one then I'm going to console.log and here I'll just say remaining and after that I'm going to put in the remaining value just so we can see what happens here with this request and the limiter so let's start the application once again so I will npm run Dev in the terminal we'll get that up and running and I will use thunderclient to go ahead and try out that hello route for our API so I'll close that out you could use Postman if you want I'm going to use thunderclient to send the request and now I'll go to a get request and it looks like I've set that to the to Do's for now so let's switch this to the hello route it is a get request we can send that it's process the request now let's open the terminal again since we're still here in vs code we can see that we have two tokens remaining let's send it again now we've got less than two now we've got less than one and now we're at minus one so now if we send another request we still have minus one but everything was okay so there's something else we still need to do let's close this out and let's go back to our hello route and we need to put in a response if we don't have enough tokens remaining so here let's say if remaining is less than zero then we want to send a response so we will return a new next response and so that immediately Imports next response at the top when I type that now the first param in next response would be the body so this is where we would send Json we could stringify Json here if we want to I'm just going to make that null because there's no body to send but now in the second param we can put all of the other things we would normally send with a response like the status which needs to be a 429 when we have limited the requests here after that we can put in status text and we're going to say too many requests which is the typical response you see when your rate is limited and then we'll put in headers that's an object here we'll have the access control Dash allow Dash origin and we could put this as the origin if we had defined it or we could just put all if we wanted to which would be the asterisk here so if we want to get that origin above we could do that as well this isn't really required but it is good to put this in especially if you are working with cores which we'll get to so let's go ahead and grab that origin also here and we get that from the request that's coming in so here I'll say const origin that needs to be equal to request dot headers dot get and we get the origin as you saw me previously do in the middleware file so now this could be equal to the origin value or you could just have this asterisk here for all because possibly this request is being sent from thunderclient or Postman and then An Origin won't exist okay after that the other header we'll put is the content Dash type and right now we are sending back Text slash plain content okay let's go back to our Thunder client here and we'll of course open up the terminal again so we can see the replies we'll send one one request now we have two remaining tokens another less than two now less than one and now we have our 429 too many requests here and that's what we expect to get when we are being rate limited and you can see we have remaining minus one now the nice thing about pulling this instance in from our config slash limiter is it's going to share that token count between the different files so if you wanted to use this in the hello route like we are here and then also use it inside of the to do route you could and it's still going to count those tokens you would want to create separate limiters for separate routes if you didn't want to share the tokens between them or instead of using the config file just create it in the route file where you're using it of course you could do that as well I am back in the next JS docs once again and of course we've already applied rate limiting middleware we've learned how the middleware file works as well that runs in the edge run time but one piece of middleware that you almost always have to use if you want to make your API public is cores and here let me quickly jump from the docs to the npm JS website once again and here is the cores middleware that many use with node and express now this is actually recommended I will show in the docs coming up as well I want to scroll back down to where I was here just we'll come back to this but in the docs where we're learning about API routes here in next JS it talks about core's request helpers and this will end up linking you to a GitHub repo where they created a wrapper but this is with the older version of next JS it's not going to work with the new version that we're working with in the beta docs so just telling you this ahead of time so you don't spend too much time on that however you don't have to specify core's middleware with next JS and this new version of the routes to make it work work so I'm going to show you how to do everything cores would apply without actually using that middleware from npm so right now the big thing this is under caveats when we're talking about apis here if I come to the API routes but under caveats the main thing to note when you're creating a rest API in next.js is that those API routes are always same origin only so you're always going to get a cores error unless you work around that now that is great if you don't want anybody else besides your own application to access your rest API but if you want to share it with the rest of the world or at least in a loud list of URLs where a few other websites are permitted to go ahead and access that API well then you need to know how to do this workaround and actually it's not so much of a workaround as it's just applying everything that the core's middleware does in a different way without using that dependency so as we apply this there are some things we need to keep in mind this is essentially what the core's middleware does it checks the origin and it says if it's allowed or not the asterisk means all Origins are allowed but we can provide an allowed list and you'll see this provided up here as they put in a white list is what they call it here in the docks I like to call it allowed origins or in a loud list But whichever you prefer anyway from there you're going to check those Origins other than that next JS already handles the options request and that's pretty awesome because it bases its options reply on what methods you already have in your route handlers and then it also handles the options request success status for you so essentially we're going to handle checking the origin and who we want to access our API and everything else next.js is pretty much going to handle for us now I'm in the beta docs and if you're wondering where to find that information I found about the options request well it wasn't that easy to find but here we're under HTTP methods and this comes under route.js now what we've got here is the comment if options is not defined as a function here inside of the routes next JS will automatically Implement options let me not scroll too fast will automatically Implement options and set the appropriate response allow header depending on the other methods defined in the route Handler so essentially it handles it for us and this is the only place I found this information but it's good to know that way we don't have to create our own response for those options requests and those options requests are triggered by requests for Json data and other complex requests and of course if you want to find out more about that you can look under mdn and look under the options request and pre-flight course that's also a place where you'll learn more about that I'm back in Visual Studio code and let's go go back to our middleware file because here is a great place to check all of the origins we're talking about or create that allowed origin list I'm going to do that above the function here because this would be a static list that we would add to just as we wanted to allow origins or not so I'm going to say const allowed Origins and this list may change depending on what mode you are in say development or production and we can check that mode so let's set allowed Origins equal to a ternary statement and I'm going to say process.env dot node environment this provides which environment we're in so let's say if it's equal to production this would all be lowercase so if it's equal to production now we can provide our list and this list for you for example if you deployed your application which would be production it might be https colon slash slash www dot whatever your site is named so I'll put your site.com that would be an example of that another one might be the same thing but maybe without the W's here so let me go ahead and copy this of course you'd want to test this out to make sure everything was working as expected we just go ahead and remove the W's a couple of different URLs that are fairly common for a deployed site of course replace your site with whatever your domain name would be but now in development we might have a totally different list so we might have something like our HTTP instead of https colon slash slash and then we might have our Local Host three thousand that's the current website and of course it's already same site but let's go ahead and include this because we're going to use this in a conditional so we want to do this here after that you might also say you'd replace localhost with the IP address 127.0.0.1 that still means your computer or translates to localhost or localhost actually translates to that IP after that let's put in something else we might just play around with and we can see examples of how to work or not so I'll put in HTTPS colon slash slash www.google.com and we can issue a fetch request from the dev console while we're on the Google Website and we can see if we get access or not so we'll put in those for now and now remember I've already left this config in for the matcher I just showed a couple of alternative ways to do that here with conditionals but I'm not going to leave this in I'm going to put in a different conditional so I'll just highlight all of that and hit backspace and now let's put in our conditional for our Origins and here I first want to say if we have an origin so I need to get that origin ahead of time so let's go ahead and do that up here and we'll just control X put it back right here above so now we have the origin wherever it's coming from and we want to make sure we have an origin and let's say it is not in the list so we'll say not in the allowed Origins dot includes and then pass in the origin so here we want to make sure we have an origin value but that value is not in the list we've applied above and now we'll do an early return here so from here let's go ahead and have our if block and we will return a new next response and inside the next response once again this is where the body would be and we don't need a body here so I'll make that null then we're going to have a status 400 which is typically the status for something that is blocked by cores so this would be the same status we would get from that Coors middleware package if we didn't have the allowed Origins matched up and then from there we'll say status text here we'll just say bad request which is what a 400 is and we'll have headers and inside the headers we're going to have our content Dash type and this is Text slash plane once again now this will essentially block anything that is not in our allowed Origins list but there is a problem here as well because thunderclient Postman and possibly other tools that we might test our API with would not have an origin at all so for now those would bypass this and that that's fine and you might want to leave it that way but in production for example you might also want to block those when you deploy your app and if that's the case you could just put in an or here like or no origin so then it would block those rest API tools as well I'm not going to leave this in because we are going to use thunderclient today but I did want to let you know if you want to block those you would just look for no origin at all and that would do the trick however that might also block some browser requests and things if you didn't limit it to your API for example so there could be a trade-off there as well just always remember to test everything out and make sure your conditional routing logic is working as expected okay let's make sure our application is running and it is still running here so now we can test out this logic to see if it is working okay I'm back in the web browser and here on the Google home page now from here I'm going to open the dev tools with Ctrl shift I and I'll have a terminal here so I'm at the console not a terminal but actually the dev console and I want to just fetch from my local site now when I say localhost that means my computer I can do this because I'm running this browser on my computer too so when you fetch on yours you're not checking my website or my API you're actually checking your project localhost refers always to your local machine so here I'm going to say fetch and I'll say HTTP and then colon slash slash we have localhost on 3 000 from there I believe we had slash API slash to do's and that should be all I really need to do here so let me go ahead and press enter and we have a promise pending and it is currently blocked by cores you're thinking wait a minute we put that in the allowed list but yes we're not quite finished yet so Google should be able to access our API but we haven't changed everything we need to but we did check the origins so let's go back and go ahead and make the rest of the changes and try this again okay I'm back in vs code so now let's go to our to-do's route and we were issuing a get request so that hits this route right here that is get inside of our to Do's route.ts file so from here where we have our next response dot Json we need to change this so we can apply the appropriate header so first of all we'll need to create a new next response once and we'll change all of this so the new next response is going to receive Json here as the body and we'll use json.stringify then I'll pass in the to do's and then after that let's go ahead and put in everything else that we would expect to have here and to bypass the core's response we're getting we need headers and that headers is an object and it's going to have access dash control Dash allow Dash origin and that is going to be set to the origin which we once again need to get above and if we were testing with a tool like thunderclient instead of making a fetch from Google we might just want to put in a reply like all right here as well after this let's put in the content type as well we're replying with and that is going to be application slash Json here now what we don't currently have yet is the origin remember we're getting that from the request and of course that's going to instantly make this a dynamic request instead of a static request as next.js is documented but we need that request object here so we're going to go ahead and put that in and then we're going to Define our origin so we'll say const origin set this equal to the request dot headers dot get and we'll get the origin if it exists on that request now that's in place we'll will open up the terminal and yes we're still running the application here so let's close the terminal out again and we'll go back and check this on Google okay we're back in the browser back at Google I will clear this out now I can just Arrow up to pull that fetch up once again and let's send our request now we're not getting a course error at all it's a promise pending I didn't await the fetch or anything like that but the fetch doesn't error out due to cores and that's because we're sending that appropriate header in the response okay I'm back in vs code so what you want to remember about cores is not only are we checking our allowed Origins list inside of our middleware file that applies to everything the middleware file is applied to so here we limited that to our API routes but after that then inside the routes themselves you have to make sure you're always sending this Access Control allow origin header and specifying the proper value of course the origin that actually came from or if you're wanting to work with rest API tools like Postman or thunderclient this is an appropriate response as well just to have something there so that's the short circuit here in JavaScript the or so if origin doesn't exist you're at least replying with that but once again it's only made it this far because it made it past the middleware where it's checking the allowed Origins now a couple of things we could still check here one is let's remove Google from the allowed Origins and make sure our bad request response also works okay I'm back at Google let's once again issue that request after we've removed Google from our allowed Origins and yep now we have a 400 bad request and of course it's blocked by cores now too because we didn't put that header in that response so they get the cores message that is expected and then it's also getting that 400 bad request and this essentially mirrors what that core's middleware would do that we looked at at npm JS now one more thing to look at on npm JS we see that options success status is a 204 and I said that next JS already handles that for us so let's confirm that back in vs code I'm going to go back to thunderclient and I'm going to just go to our request that we sent here we had too many requests let's make sure it once again works all good there but now let's send just an options request now we should get a 204 and that's exactly what we get so next JS is handling that appropriately so today we've learned about this middleware file and it runs in the edge runtime and of course we learned how to apply the different routes with either the config down here and the matcher or conditional logic or you can use both together and after that we also learned how to apply rate limiting middleware and we of course had to do that inside of the routes file itself because it had a node dependency that won't run in the edge runtime then we learned about next.js handling those options requests and how to provide all the checks that the popular core's middleware provides without really needing that dependency in your app at all and while I don't expect it to with nexjs things can change quickly so remember to check back to the docs for whenever this to do is completed today's starting code is the completed code from lesson six where we built a Blog project today's lesson is lesson 10 in the series but you're going to find the starting code under lesson 6 in the course resources that are linked in the description so after the blog project in lesson six I received several questions about ISR that's incremental static regeneration and how to apply revalidation to the blog or other similar projects without rebuilding the project every time a new blog article is added so today I really want to break down the ISR process and show how you can use it with and without fetch so this should not only help the current project that we're working on but also it will work if you're using Fetch with a headless content Management Service also known as a CMS now also note I'm using next JS 13.2.4 today currently 13.3 still has a few bugs to work out now in the future I hope that's not the case and you may even be be working with a stable release that's higher if you're watching this video at a later time but right now I'm using 13.2.4 now if we look at the structure of the app over here in the file tree you can see I'm not using the source directory here which would just be a parent directory for many of these other things but right now if we look at the structure of the app we'll just look inside of the app directory you can see we have a page and with this page we are bringing in a posts component now this is what we need to update it's going to display all of the posts so when we add a new article or a new post then we want that added to the list so users or visitors to our website can click on that new blog post so from there let's look at that post component and we can see oh I'm looking inside of the dynamic directory sorry we need to look inside of components where we have the post component where we bring that in to the main page now here we are and generating that list of post and you can see we are calling a function called get sorted post data now we're not using fetch here notice we're not awaiting this it's all on the server already and if we look inside of our lib directory here for our library we can see this post dot TSX and let's look inside of this and actually we could have named that just TS as well looks like I named those TSX but they are not components that have jsx in them for example so you could just name these TS if you want to but anyway inside of here we've got the get sorted post data and it's Gathering those markdown files where we create the new blog posts and it pulls them in so we're not using fetch but we can still revalidate with or without Fetch and then here of course inside of the blog post directory we see our markdown files there's one for each article for our blog and we'll be creating a new fake one today as well so that's the overall breakdown of the application and we're just really going to focus on back here in the app directory on our main page that pulls in the posts now I'm back in the beta docs here for next JS and we're talking about revalidating data and it says there are two types of revalidation in next JS the first is background revalidation and it revalidates the data at a specific time interval that's what we'll be doing today and then later on we'll learn about on-demand revalidation and we're also going to learn how to do that but first we'll look at background if we scroll down here it shows how we have learned this before in a previous lesson we had set this with fetch we have the next property here and then we set an object inside there that says revalidate and we give it the number but we can also use a route segment configuration and I will go to this page but here's an example of it and it just says export const revalidate and sets the number now you can set that in a page for the tree that that page is in and if that page is apparent it applies to the rest of the tree however the fetch request if you have a fetch inside of the tree that's also using this route segment config the fetch will override whatever is here so you can still set individual values four different fetches if you want to let's look at this route segment config page now here it took me directly to the revalidate part of the page but I'm going to scroll to the top because there are other configs as well and we'll be looking at two one is the dynamic params now this default here shows all the default values this is set to true and that's important because when we add a new blog post a new markdown file essentially when it's not inside of the generate static params function it didn't exist earlier when we built the site for example well then it's important that we can use Dynamic parameters as well to get any new blog Post article so they will also be available and notice here an important note is that can only be applied to page layout or route Handler so as far as our front-end app goes it could only be applied to the page or layout that's where we will put these configs let me quickly scroll down to the dynamic param section that we were talking about just so we can see a little bit more about that and here's what we need to know that the true is the default and it says Dynamic segments not included in generate static params are generated on demand that's important for our new articles and now if I scroll further down to our revalidate section we're going to set this notice the default is false and that's not what we want we're going to set this to a low number so we can see the revalidation happen very quickly now when you deploy you would probably set this to a high number maybe a common value would be 86 400 which would be all of the seconds in one day so you're essentially setting it to one day where it would revalidate at that interval but remember we will also learn about on-demand revalidation and how that works as well okay I'm back in vs code and I'm in our page remember this is one of the only places we can put the route config options that we want to either a page file or a layout file so even though I'm talking about the post list that I'm importing from components I need to put that config here inside of the page.tsx file so here at the top let's put export const and then revalidate and I'm going to set this very low so like 10 seconds right now that's what the number is equal to and like I said later if you were to deploy you'd set this very high like 86 400 would be one day but let's just set it to 10 seconds for now because I can talk over 10 seconds and then of course we can revalidate and see what happens now when it comes to the dynamic params config that we saw we don't even need to set that because we're already using the the default value so that's already applied so with this revalidate config now applied we cannot test this inside of the dev mode so we really need to build our site and then we can test it when we run the build so let's type npm run build and I'll come back after it's built and we'll look at the results okay the build has completed let's scroll up here quickly and look now notice our home page where we're importing that post list is considered to be static and then we have SSG here for the dynamic posts that are of course using the generate static params as well and that's why they're SSG we had learned that earlier in the series I believe around Lesson Four but it's important to note that this is static but by applying the proper revalidation this incremental static regeneration format or design that we can use then we're going to be able to see our new post eventually anyway without rebuilding the site so now let's go ahead and start the build we just created we're with npm start and we'll make sure that's running and it's currently running now now let's look over at our blog posts and we have two of these here so I need to create one more but I'm going to create it out here in the root area for now so I'll create a new file I'm just going to call this new DOT MD now I'll come inside of one we already have I'll close the terminal for now I'm going to copy everything and then just paste it into the new one and alter a couple of things here so let's make this 4 and let me see maybe today's the 19th so we'll go with that and then I'll just put my new post up here for the title we can leave the body the same so this will be our new file when we put it in the blog post but first we just want to look at our application without the new Post in there and to do that I'm going to press control on the back tick open up the terminal window here and we have our localhost 3000 I'll hold down the control key and click and it's going to launch this in a new browser window that's fine we've got our two posts listed here so we can navigate to each one of those go back to the home page I could also use the back to home that's down here as well everything's working as expected and it's very fast because these are SSG articles so everything's behaving as if it's a static page and it loads very quickly right now now back in vs code I'm going to drag this new blog post into our blog post directory and we still have our site running we did not rebuild the site that's important to note we just put a new article in our blog post directory so back in the browser now as we navigate from article to article and back to the home page we're being served cached versions of these articles and the home page but notice after I navigated away twice and came back then we see the new blog post so it didn't happen right away it took two clicks so that's important to know so I want to go back once more to vs code and bring this back out so we no longer have that there and of course after we come back to the home page now I'll be able to refresh but it should take twice there's one refresh there's two refreshes and now it changed let's talk about why it takes two and I think I can demonstrate that best by putting the blog article back in and showing how this works once again and just using refreshes instead of clicking away and clicking back so now we have our new blog article back in the blog post folder and now out here we're not displaying the new one so when I refresh the first time we don't get it the first refresh or reload after the revalidation number essentially 10 seconds in this case has passed so after 10 seconds the first refresh or reload of the page essentially triggers the revalidation but while it is revalidating it still serves the old version so the first request triggers it the second request gets the new version and that's not what everybody expects to happen I think they expect to see it right away so that taking two times either two clicks away and back or two refresh crashes throws some off but it's important to understand that that's how it works and let's go back to the docs to see how they outline this process okay back in the beta docs we're on the revalidating page and we're looking at how it works so it says when a request is made to the route that was statically rendered at build time it initially shows the cache data that's what we expect but then any request to the route after the initial request and in their example they use 60 seconds instead of 10 but any requests before that time period are also cached and they're instantly responded to but after the time period the 60 second window they give we gave 10 seconds the next request will still show the cast or you could consider it stale data and that's what we got after the first refresh but it triggers a regeneration of the data in the background and then after that successfully regenerates the next time you request data it's going to invalidate the cache and show that updated route so then we see the the updated information that has the new blog post in it and that's how the process works now remember we're not using fetch but if you are using fetch whether it's with a sanity i o request or some other headless CMS or you're requesting data from an API somewhere or who knows where you can of course specify the revalidate number right inside of the fetch request and this will override what you might have for a route config as well and remember your route config can only go inside of the page or layout for your front-end app now all this is great you say and of course we can set that number higher like 86 400 seconds so that's not going to be 10 seconds and we would have to wait that whole time of course to have two requests go through after a day passed to then get new data on our site and we may not want that to happen and in that case we can use what's called on-demand revalidation I'll just scroll down further on the page and we see it right here here so what on demand revalidation will allow us to do is after we create a new blog post we can hit an API endpoint that revalidates the data and then of course updates the site immediately when it gets the next request so we're essentially putting in the first request ahead of time that would trigger the revalidation so now let's go back to vs code and we'll apply this okay I'm back in vs code I'm going to go ahead and press Ctrl C to stop the application for now close the terminal window I'll also drag that new article back out here into a top level and we'll put it back when we're ready to as well and while I'm in the top level what we need to do is create a DOT env.local file as we're going to use an environment variable so dot env.local and of course it should match a pattern that is in the git ignore so if you have a repository on GitHub you would want this in here so it does not add your Dot env.look to that GitHub repository you never want your environment variable values stored in GitHub so I'm going to call this environment variable my underscore secret underscore token and that matches the docs if you're looking at the docs as we go and you could put any value here you want I'm going to show you how to generate one as well but I'm going to use a simple one that I'll remember like Dave Gray teaches code and you could do a phrase that you remember as well we're going to use this later in the revalidation request URL but now after we make that let me show you how to generate one with node also so I'll press Ctrl in the back tick to open the terminal I'm going to type node so then I'm in the node environment and I've got a prompt here where I can type node commands and I'm going to type require and I'm going to bring in the crypto module and then from there I'm going to use dot notation and add random bytes notice I'm using camel case there with the capital B and now inside of these parentheses we can put essentially how long we want this token to be like a long one would be 64 or maybe even 32. I'll make a short one with just 16 here then we'll say 2 string and inside of two string we'll say to hex here and now I'll just press enter and this should generate a random tokens so you could use this instead of my value Dave gray teaches code for example and this would be your secret token value so I just wanted to show you how to do that let's go ahead and exit out of the node environment Now by pressing Ctrl C twice and now we're back out now we can close the terminal once again and this would be our DOT env.local that's all we need is a value for my secret token now as we scroll back up there is something about the revalidate request that we need to discuss because it's probably going to change and that is currently it only works inside of the Pages directory and right now when you create one of the new next JS projects it doesn't even create that Pages directory it needs to be at the same level as the app directory so I can just highlight the dot env.local file once again create a new directory here and name it pages I do expect this to change and maybe it will work with the other API directory that we have inside of the the app directory in the future where our route handlers are but for now it must be in a Pages directory okay now inside of the Pages directory we'll create another API directory and then inside of the API directory we need a specially named file that is called revalidate.ts now one question you might have as we discuss this is will our route handlers still work here as we have a Hello route yes they will and we could demonstrate that or you could just test it out on your own but yes your example hello route Handler for the new route handlers in the new API directory that's in the app folder will still work even though this Pages API directory now exists so now we're going to work inside of the revalidate.ts file but let's quickly go back to the documentation back at the on-demand revalidation documentation what we need to highlight is the URL that they are suggesting we use to request the revalidation and so I'm just going to copy this here and then we'll go back back to vs code and I'll put it in a comment back in vs code I'm going to put a comment here at the top of the file and just put their example URL now this is close to what we want to use but I want to show you what we're going to use and it's just a little different so what I can do is actually just copy this down and modify it so shift alt in the down arrow the first thing we're going to do is not use https now of course after your site is deployed then yes you would use https but just here in development even though we're only going to use this on a build we need to use HTTP on our local computer so of course as we're testing this on a local computer this your site.com will need to be localhost 3000 then it's going to go to API revalidate and here we're providing a parameter called secret and then it's going to have a value my value was Dave gray teaches code so this should match the secret you have in your dot env.localfile but we need to add one more thing that they don't mention here and that is a path because we want our revalidation request to work for any path that we decide we need to revalidate if we had a larger application of course that could be very handy so I'm going to say path equals and we need to revalidate the home page the root so it's just the slash but then we need an ampersand before we get to the next param in the URL I can press alt Z to wrap that down so you can see the full URL here so we're providing two params path equals r slash just for our home page and then we have an ampersand and then secret equals and whatever your secret value is so I just wanted these at the top for reference of course you could delete them later if you want to but I'm just giving the examples comparing to what is inside of the documentation so now let's create this route Handler for the revalidation request we're going to start by importing next API AI request and also next API response and those are going to come from next after that we'll go ahead and start our functions so export default async function and let's just call it Handler and from here we're going to have a request and this is the next API request we'll also have a response and this is the next API response now let's just scroll up a little bit and well not quite that far there we go and from there I'll put the curly braces and we can create the rest of the Handler here inside for the function so the first thing we need to do is check our secret so we'll say if request dot query dot secret is not equal to what we have in our EnV file so our environment variable that's process dot EnV dot my underscore secret underscore token so if they are not equal we're going to return right here we will return the response status is a 401 and from here we'll use Json and provide a message and just say invalid token and that's really all we need for that response but now if it's successful if the secret matches we would normally have a try catch here but I'm going to recommend not putting the try catch in at first so if you have an error you can see the details of that error inside of the console where next.js is running here especially after you build the application it would be very handy to see that compared to just having a catch where it always gives you the same error and that's what they show in the docks where it says error revalidating you don't know what the error actually is so it's better to maybe not catch that error in development and get more details in the console so for now we'll say const path equals request.query.path and now let's notice the type here so path is not necessarily just a string it could be an array of strings or it could be undefined but that's not what we need here when we use the revalidate function in just a second so I'm going to use an assertion and I'll say as string so we know path is a string and that's what we'll set it as from there we can await and we'll have response dot revalidate this is the important function and this is the function that is currently only available in the revalidate file that comes through the API that is in the Pages directory and once again I'm sure this will change in the future and if we validate is then later on available inside of the route handlers for example we would use the other API directory but now let's just pass in the path value that we have so that makes this path value very important and of course that's also being sent in the the URL above that's where we set the path equal to slash because we need to revalidate our home page essentially that has the list of blog articles on it but whatever the path is that could be altered so if we needed to revalidate a different route if we had a different route here inside of our application here we also have posts for example and inside of posts we have a post ID and of course this is a dynamic route but if for any reason we needed to set it here to revalidate one of these Pages you would give that specific route so maybe the posts slash ID of one or whatever that would be so you could provide that specific information for the path and this Handler would still work now after this we just need to return our response so I'll scroll up just a little and here at the bottom we'll say return return if I didn't misspell that return res dot Json and here we can say revalidated is true and that would be the good response there now of course once again you could set this to a try catch and of course you would try the await and the return here and if not you would catch the air but I think it's better in development that you see any errors happen inside of the console now remember we cannot test this Handler in Dev mode it will give you a 500 error if I remember correctly it's not going to work if you do npm run Dev so we need to rebuild our application so I'll do npm run build and I'll once again come back when the build is complete okay we've built our application and if we scroll up here we can even see I believe inside of the blog posts yes there are only those two posts right now we don't have the new one in there yet so it will be added after the build let's go ahead and type npm start and get our application running and then we'll go back and check it okay we're back in the browser and we're running the application here and we've got our two articles and I can navigate between those two articles and back to the home page everything's looking good so let's try adding the new article and then revalidate okay back in vs code I'm going to close the terminal let's go ahead and collapse some of these other things so we can see more of what we're doing here and we need to open up blog posts and we're going to drag the new article back in to the blog post directory over here so I'm dragging that in that looks good now remember at the top of the route here we had put the revalidation path so I'm going to copy mine again just using HTTP and then the localhost 3000 and then it has my secret right here inside of the URL so Ctrl C to copy that now I'm going to use the thunderclient extension to test this out you could use Postman as well or some other client if you want to so now I'll just open up thunderclient here and I'm going to do a new request and I will paste my URL directly in there and a get request is what's expected here so you can see it breaks out the query so we've got path equals slash secret equals my secret and now I could send this and we should get a revalidation response and we did revalidated true now I'd also like to highlight that we can also request whatever we had for that API was it uh hello or not that one let's find it here here's our API hello so that route also works with the build and I'll send that and we get hello nextjs of course that's the default one with the new route handlers so again they're both working but our revalidated true did work so now let's go back to our blog okay I'm back in the browser with the blog I have not refreshed at all but we already triggered a revalidation so now if we reload the page we have our new post there so we did not have to send a request or wait for any longer time to expire we triggered that revalidation with our URL with that new API endpoint that we just created and once again remember you can only test this out with a build not in Dev mode and so now that we've learned about this let's talk about the workflow with your blog when you add a new article you should add the new article and then send that on-demand revalidation request and of course remember this replies to however your blog receives data so it could be markdown files like this project but it could also be fetching data from a headless CMS or requests coming from elsewhere and then remember to check back to the documentation because sometime after version 13.3 I don't expect the Pages directory to stick around and those revalidate requests are probably going to be up in the API with the other route handlers that's just my assumption though I don't know for sure but it would be great to see it work alongside those new route handlers we're talking about mutating data today in next.js and today's starter code is available under lesson seven in the course resources and it provides a fully working to-do list if you've completed the course prerequisites listed in lesson one of this video series you've undoubtedly built a to-do list before so I'm not going to step you through building the to-do list instead we're going to specifically look at how nexjs handles the data mutations from our crud operations and also how nexjs handles hard and soft navigation and what the difference is so overall we're focusing on understanding concepts now the first note is the next JS team is working on something new for mutating data in next.js and that's part of why I waited till near the end of this series to cover mutating data but the new approach still isn't available and I do feel like I need to cover the current approach but just note if you're watching this video at a future date you should check the documentation to make sure the approach that I'm showing today has an changed so on the mutating data page currently in the beta docs for next.js I'm going to scroll down and they're going to show a server component here and it's part of a to-do list application so we'll look at this first before we look at my code that's available in GitHub in the course resources again under lesson 11. so here we've got this server component they have an interface for it to do you could create a type either one and then they've got a get to Do's function now something we want to notice here is the cache equals no dash store now that's important because if you want to see immediate updates in xjs you need to do that and also you could do it another way so there's two ways the other way would be what we learned in the previous lesson and that was setting a route segment config and you could set your revalidate equal to zero and it essentially does the same thing it will make sure you are not storing those requests because you want to see those immediate updates when when you update a to-do you don't want to see a cached version held over because then even if you checked complete it wouldn't show that check so this component for the list page as we see here is a server component that renders the list but each item has its own client component and that's going to allow that interactivity where you update or delete a to-do so that's important to realize as well so you're creating a list with a server-side rendered component but then your actual list items will be client components and that's what we see down here now my code's going to have a little bit more in it because I actually added a delete and I've added a separate use client component that you can add a to do with as well so we'll just break this down first and as we see this here you can see they are using a router which will cover part of how that works as well they're also using the use transition Hook and the use statehook to create a use or a I'm so sorry and is pending and an is fetching State and then they're kind of combining both of those into this is mutating state so they can see if either one is active notice here on the change Handler for the input if they're updating here with their put method for example that's all they do of course like I said my code is going to handle more than just that but either way their setting is fetching true before the request and then false after the request so that's handling the is fetching part the transition is actually going to handle the router refresh here as well so that's the use transition hook and they're combining both of those into is mutating and then when they render the jsx below for the list item you can see they're using style here to just change the opacity of that item to make it kind of dim a little bit so you might see it flicker it's going to be fairly quick in Dev mode when you're not actually reaching out to a server that's further away but the really important part to note here is when you want to see those updates immediately in next.js they're calling this router refresh and of course they're using the use router hookup here to Define router and then they call router refresh and you see that description here it makes a new request to the server for the route it refetches the data request and it re-renders a server component so it's going to re-render that list and then sends the updated payload to the client so that's what's going to happen when we call router refresh so we see the updates in our list so now let's look at my code in vs code now we're in vs code and you can see I'm at the home page a couple of things to note here one I'm pulling in components rather than constructing the server component itself right here that builds the list and that's because I've also got to add to do component that's a client component where we can add a new to do also note this TS expect Airline is needed or you'll see a typescript error here this was noted earlier in the series the next JS team is currently working with typescript to hopefully avoid this error in the future this is what they currently recommend in the beta docs to avoid the error that you would see here for the to-do list it is a legitimate component it's just a typescript thing currently with nexjs also note that I have the route segment config up here export const revalidate equals zero that achieves the same thing as setting the cache equal to no store in those fetch functions so if we go down to the lib directory here and look at the fetch to Do's function for example you can see I'm not passing in an options object where I set the cache to no store because I'm achieving the exact same thing by going ahead and setting that revalidate equal to zero here with a route segment config now if we look at the to-do list component that we're pulling in we see much of what we saw in the documentation here very similar I I am reversing the to-do's for sorted to Do's just so the new to do is added at the top but other than that it goes ahead and renders the list and this is a server component now the individual to Do's are in a to do component that is a client-side component because it allows for the update and delete of any individual to do so if we look at this component it's much like what we saw in the documentation as well and you can see I just added a little bit of extra code here so I have a handle change as far as updating the to do then I also down here have a handle delete but you can see they both use a transition where router refresh is called so we can see that updated data once again inside of the browser immediately and we're not seeing a older version of the data a cached version because then we would click update for example and then we would still see an empty check boxes if we hadn't checked it now notice I'm also fetching data from 127.0.0.1 which is an IP address that's the equivalent of saying localhost I just happen to use the IP address this time and it's at Port 3500 so we're going to have to start our Json server where we're getting that to do data from as well as starting our project in Dev mode and you can see in this db.json file that you'll also find in the repository for this video you're going to see the to Do's here that Json server is going to read from inside of this file so it will update the db.json file after you start Json server so we'll do that as well otherwise let's go ahead and just start this and see how it all works in the browser so I'm going to open up a terminal window and I'm going to type npx Json server so we can start our data server first Dash W4 watch and we're telling it to watch the db.json file Dash p for port and we'll put that at 3500 then Dash H for host and I'm going to put that at 127.0.0.1 and press enter this will go ahead and start the Json server you can see it found the resources at to Do's it lists the URL as well and if you wanted to come back to this terminal window it will log any of the requests here as well as the request method now let's go ahead and open a second terminal window now I'm going to go ahead and type npm run Dev to start this project and after it starts up I'm going to hold down control and then click Local Host I'll have to scroll back up to it there control and click localhost 3000 here is the to-do list now we should see updates right away or when we add a new to do so let's do this with new to do and I'll press enter and there we see our new to do I can update it and we see that right away notice how it fades just a little bit and that's because during the transition then it's going ahead and dimming the opacity of the individual to do so when I uncheck it we see that just kind of blank just a little bit I can delete it as well and we see these updates immediately this is all working just fine when it's all on the same page and remember those handlers are calling that router refresh which gets the server side re-render and then we see the updated list immediately now as I mentioned this works very good when it's all on the same page we call router refresh it refreshes the component everything's good but what if we took these same components our ad component or the individual to do component and we put them in a different route and if we look at vs code we can see that but let me show you how it functions first before we go back to BS code so I'm going to go to the add route right now I'm going to add a new to do now press enter notice we went ahead and went back to the list page because I called router.push and it sends us back here but we don't see that new to do I added do we it's missing from the list so that's not good what if I went to an edit page for any one of the individual to do so I'll go here for say this write code to do now I'm on an edit page for this to do and I'm going to click to say okay this is complete now let's go back to the home page and I can do that by clicking next to Do's here notice it's not complete here if I go back to this individual route it is complete so that's out of sync two so we've got a couple of issues to talk about okay we're back in vs code and as noted before I have the route segment config here revalidate equals zero and we see those updates immediately as long as we're doing them on the same page but when we go to either one of these routes either the ad here's our page TSX for that and it just pulls in that add to do component that it's the same as the home page essentially where it pulled in the add to do component and there's no difference there other than that but let's also look at the edit route that pulls in an ID here and if we look at this it also has the revalidate here set equal to zero and then of course it pulls in this to do so this is the same as when we created our list with the to-do list that pulled in the to do but we're not getting the same result and if we look at the to do up here at the top and come down what we will notice I believe let's find it here in the transition here is the router refresh or the delete and then here is the router refresh for the update so it's calling router refresh but what's happening is we're not on the same route so when we call the router refresh and we're on the same page then we see the update in the list but when we call it on this separate route we're not not seen it in the list and we really need to go ahead and look at the docs to see why this is happening we're back in the docks I'm back at the mutating data page and we see here it says after mutating external data you can use router refresh to refresh the current route and then it says from the root layout down but that doesn't mean it's going to go to another route emphasis here on the current route so that's one thing to note now let's go ahead and look up use router itself so we'll find that here in the beta docs and now that we've found use router let's scroll down to where it talks about use router a little bit more and under the good to know this is also something we want to highlight here the push and replace methods will perform a soft navigation if the new route has been pre-fetched and either doesn't include Dynamic segments or has the same parameters as the current route so that's important to note because we were using a push when we added that new to do and we noticed that it was a soft navigation it wasn't a hard navigation or we would have seen the new to do and there it says if the new route has been pre-fetched and either doesn't include Dynamic segments or the same Dynamic parameters as the current route well it probably was pre-fetched and it doesn't include any Dynamic segments so one thing we can do in our code is set prefetch to fault let's go back to vs code and see how that works okay I am back in vs code now we want to set prefetch defaults and that was in our nav bar because we clicked on the name it said next to Do's here that we have inside of our header so let's go ahead and just set the prefetch equal to false on this link and save now we'll go back to our browser and see if we get the same behavior okay I'm back in the browser and I'm going to reload the application here with a hard reload just to make sure we have that new behavior and so I'm going to delete the new to do that showed up as well and now we can see right code was already checked as completed and so now I'll uncheck that so now we have the fresh app here once again I can refresh with a hard refresh again just to make sure now we already put that prefetch equal to faults for this link so let's go to the add page now let's add once again let's just say hey hey as our new to do and submit notice it shows up right away so what we did was not prefetch the next to-do's link on the render for that individual ad page and by not prefetching the link it didn't do a soft navigation so now we need to discuss the difference between soft and hard navigation and what's happening okay I'm back in the beta docs under linking and navigating and we can see hard navigation and soft navigation to find so here it says for hard navigation on navigation the cache is invalidated and the server refetches data and re-renders changed segments so that's what we really want to see that new updated to do is the hard navigation because it says the cache is invalidated now this is where it gets complex because we spend so much time talking about server components and we don't really talk much at all about a client-side cache but next.js does have one and you see that on soft navigation you see what's cached on the client side and that's not what we want but you need to realize that a client-side cache does exist even though we don't spend much time talking about it here for soft navigation it says the cash for changed elements is reused if it exists and no new requests are made to the server for data that means it's all client-side that's a client-side cache but can we avoid all the issues by setting prefetch defaults I'm not so sure let's go back to the application here in our browser and let's go to the edit page for our hey hey to do and let's see if we update the to do say it's completed now let's go back to the main page it says it's completed we see that update that's great now let's say it's not completed now let's go back to the edit page it's still completed something's still out of sync and that's not working the problem we have is that all of these links that we have for the to Do's are not set to pre-fetch so that could also be a solution but do you really want to set every Link in your application prefetch equal to false maybe not but we might as well see if it works so let's go back to vs code okay I'm in vs code and we need to look at the to do component because that's where the link is and let's look at the link that we have as we create each item and let's find it down here somewhere oh these are the buttons and that's the input here's the link right here I'm going to press alt Z just to wrap any code that we need to and let's set prefetch equal to false in this link as well which will apply to every to-do list component and now let's go back to the browser once again I'm back in the browser I'm going to do a hard refresh here just to get everything updated just to make sure and now let's go ahead and click this hey hey as it's completed and now let's go to the edit page it did work so it says it's completed so we've figured out one way to solve this problem when we're trying to keep things in sync between page routes and that is to set prefetch defaults on the navigation links but now let me use the back button and make sure it stays the same way because that should also be a soft navigation right so I've unchecked hey hey it is not complete now let's go back hey hey is still checked if I use the back button we still have a problem unchecked now let's go back still checked unchecked let's use a next link now it's unchecked but that doesn't solve the problem for the back button so there's a better way or at least there needs to be let's look at what else I've found I'm now on GitHub under issues for next JS and somebody posted an issue that says next link is choosing soft navigation for dynamic routes that's not the exact issue that we're talking about but we found this discussion that applies all the same now this is Tim from the next JS team and he says we're reworking the client-side router caching Behavior we'll share more soon but he does share more just down here just a little bit further so I'll scroll back down to his next post and here he says router.refresh on Canary invalidates the entire router cache and there we're talking about that client-side cache so he says for now using router refresh is fine just as a previous post said so what he's saying is if we use router refresh in the canary release which means the very late latest release that we would have to install and it's not even an official release yet Canary can change several times per day even but if we go ahead and install Canary we should be able to call router refresh and this behavior that we're currently seeing will change let's head back to vs code okay I'm back in vs code and I'm going to take the prefetch equals false out of these to do links and save that file I'm also going to go back into the nav bar and take the prefetch equals false out of the header as well so we've eliminated those and we're going to still see if we can get the behavior that we want I'm going to open up a terminal window and I'm going to go ahead and stop the application and now let's look at the package Json real quick I'll close the terminal for a second let's see what version we're currently using I was using 13.2.4 the current release of the beta version is 13.3 something but Canary would be even newer than that as I said any updates come out sometimes more than once daily so what you can do is open your terminal window type npm I for install then say next at Canary and now this is kind of Hit and Miss there could be other bugs so let's see what happens here after we install Canary okay Canary is installed let's close the terminal window for a second and look and we have 13.3.2 Dash Canary dot six now I don't know if it's going to work in this version or not because this has changed just since yesterday it may have even changed since earlier today but I do know a canary version where the behavior is working so let's just try this new one first I'll open the terminal again and I'll see if we can even start our app in Dev mode sometimes that doesn't work you never know with Canary so it's currently working let's go ahead and go back to the browser okay I'm back in the browser I'm going to do another hard refresh because now we're using a new version of next JS and we'll see if everything works as expected now remember we took those pre-fetch equals false attributes out of the links so we're no longer using that solution let's see if I can check this as it's completed now let's go ahead and go to the edit page it's completed there too remember we don't have prefetch equals faults anymore this is the behavior we want and we can tell the next JS team is working on that let's uncheck it I'll go ahead and use this next link we went back to the home page and it's unchecked very nice let's go ahead and check it again let's go back to the edit page now let's use the back button after we uncheck it and it remains unchecked this is exactly what we want so I think the next JS team is headed in the right direction this is not in a release yet it's currently only available in the canary version which you would never use in production you wouldn't even really want to use the beta version yet as I've had several ask me but it's good to learn this stuff now and see that next.js is headed in the right direction now if you're watching this in the future this could all be standard it could be out of beta even so it's good to know all of this and of course we're going to work on deploying an application before this next JS series is over earlier in this series we created a next JS blog that uses markdown files and the last time we touched this project was in lesson 10 so the completed code from lesson 10 is today's starter code that you see over here in the file tree you can find the code for lesson 10 and for all other lessons at the course resources Link in the description we were previously storing our markdown files on the server and you can see them here in our blog post directory and that works but it also means when you add or update a markdown file in your project you need to redeploy and that's not really ideal so today for the final project of this series we're going to make some major changes to this blog project and I'm going to move a little faster today because we really have a lot to cover if I'm moving too fast you can pause the video and the source code is available under Lesson 12 in the course resources I also want to note that next JS 13.4 was just released and also the beta docs I've referred to throughout this series are are now being redirected to new docs pages that means no more beta docs now this was a bit challenging with the docs updating literally while I was making this tutorial but I've managed to put some new things in here as I've reviewed the docs while they have updated okay let's start by installing the latest version of next JS currently in the last lesson that we had this code in we used 13.2.4 but let's go ahead and get the latest now with npm I next at latest and we'll install this latest version and we should see it update to 13.4 where it is next again here we are 13.4 so when it finishes yep we've got next 13.4 so the first big change we'll be using MDX files now instead of just regular markdown files so what is MDX well I'm going to put a link to this in the description of the video and in the course resources also so scroll down here real quickly and we can just look that it says markdown for the component error so MDX allows you to use jsx in your markdown content essentially it's going to make our MDX content more flexible than just normal markdown files would be our next big change today will be pulling MDX files in from a separate remote GitHub repository using the GitHub API and this really solves our biggest problem by using a GitHub repo for the MDX files we'll be able to update or create new content and push it to the remote repository without needing to redeploy our next JS site and then by utilizing xjs revalidation that incremental static regeneration that we set up with the revalidation settings we'll be able to see the new content so hopefully you already know how to use git and GitHub and if not stop this tutorial now and go to my get tutorial for beginners otherwise you'll not understand the next part of this tutorial okay so going forward here you want to take the blog posts that you have in the current project and that was in the blog post folder and they had the extension.md for markdown files take those and either copy them or just drag them over into a new folder and a new repository like you see I have here this is a different folder a different git repository and I have changed the files to MDX as you see also previously we just had title and date meta tags up here you want to go ahead and add a tags also and notice it's an array and you can put in the topics like hashtags that this topic would be found under so we can just see that at the top of each one of these and then some other things you can add are code Snippets if you know how to write markdown already it certainly helps because you can put in a code snippet and this just shows an example of that let's look at this one here here and you can see I've put in a typescript it's abbreviated with TS and we've got this code snippet right here now later on we're going to create a couple of components also so you can pull in a video like you see here and we'll update that later also another one's going to show maybe a image here's a custom image we're pulling in so you can see we can do things with MDX files that we really can't do with just markdown files so we'll tackle those extra components later but right now create the MDX files and add the additional tags header up here with a few tags you think apply to your articles or just whatever you want to make up for now as an example okay after you have accomplished this you need to go ahead and initialize a git repository as you can see I have done here and then you want to go to GitHub and create a new repository there link the two up and push these files there so you're storing them on GitHub now you can see my GitHub repository here now we're going to use the GitHub API to request these files because if we do it when we're unauthorized they actually rate limit you to 60 requests per hour and you would quickly run out of those especially during development so much better to set it up with the GitHub API and just make sure you're making authorized requests then they give you more like 5 000 and that should be plenty okay so we'll go to the top right here where you see your icon in GitHub because we need to create a token to authenticate with the API so we're going to go here and then go to settings and then we're going to scroll all the way down on the left hand and go to developer settings and then we're going to go to personal access tokens and then tokens classic and once we're here we want to click generate new token and then click generate new token classic now GitHub may ask you for your password before you get to the screen and then of course you can put a note here what's the token for it you're essentially giving it a title so I'm I'm just going to call this test token and of course I'm going to delete this token after this tutorial but it's for a public repository I'm not really hiding the information I'm just going to make authenticated requests with GitHub so I don't get rate limited and so the only scope we need to give it is the public repo here so just check that also for expiration you can choose no expiration again you don't have anything you're protecting here you're just making authenticated requests so no expiration public repo your name there scroll all the way down and click generate token now after you've generated the token you'll get a screen like this where you can see the token it says make sure to make a copy of this now because you won't be able to see it again so you can just click copy right here and we're going to go back to the project and put it in our DOT env.local file right away we're back in our next JS project and we want to go ahead and put this GitHub token inside of our DOT env.local file so I'll call this GitHub underscore token and say it is equal to and I'll paste in the value and that's all we need here for now okay let's scroll up in the file tree now and let's go to our app directory and let's look at our root page TSX file here and let's click allow there is it asks me that every time I think let's go ahead and do alt Z to wrap any code that we want to see there and we're going to make a few changes here as we go one thing we want to do here at the top is I'm going to change this main element to a div I want lowercase but I want to do that because I'm going to just put the main element inside of the layout here in just a moment so I'm also going to get rid of the padding the psx-6 there so we'll go ahead and change that and now we also will need to add a typescript error comment just because this I don't believe has been addressed yet in an edition of next JS so we're going to need to put this in here just saying that the post component will need this when we change the post component after that I also want to import in the profile pic we're only going to use it on this home page now instead of every page we previously had it over here in the layout so I'm just going to cut or yeah Ctrl X to cut that import here and paste the import here at the top and then we're going to use the profile pic just above the class name here so I'll say my profile pic and go ahead and add that component as well now one more change we're going to make and I know this red squiggly May bother you temporarily but after we make the posts it will go away so one more change we want to make here right now we're using an HTML entity here because in a previous lesson we had a build error because of putting in the apostrophe that we would have just right there with the word I'm let's go ahead and remove one of those and now let's go ahead and use it because we might put in an apostrophe in one of our MDX files as we're writing an article that could easily happen and we'd rather just set up the eslint rule to skip that error so let's save this file as is and now let's go to our es lint rule file which is Dot eslintrc.json and I've pulled this directly from the docs so you could also look up eslant there but what you need to do is add a rules object and then inside of this you put react slash no unescaped entities and just choose off and that will of course ignore that rule that was preventing us from building when we had an apostrophe in there okay let's go to our layout page now and we're going to change a couple of things here too one is we already removed the import for my profile pics so we'll remove it there as well the next thing we'll do is after the navbar I guess I didn't need to delete that empty line let's scroll up here where you can see it but after the nav bar we're going to put in a main element here and I've got some Tailwind classes on it let me go ahead and press alt Z and I want to put this closing tag of course after are the children here so put it right there and save and you can see I'm using some of the same classes that I had used in the nav bar and heading as well remember from a previous lesson if you looked at that one we used this prose class here from Tailwind CSS and that goes ahead and applies some general Styles overall and we're using the same width on everything so I've applied that to a few and you can check those out in Tailwind if you're not familiar with those one other thing I would like to do that we didn't previously do here is just import The Meta type that is available so we will import and we'll go metadata and that comes from next so there we go and now we can use that type here let's see what the type is currently and we look at it and it says it's a metadata type but I guess we could just spell it out here by using it I have used that in the past after these changes we're ready to go to the components folder I need to just add one class here in the nav bar and it's going to go to this first div that we have here after the nav element itself and I'm just going to put in a medium so it has a break point here that's what that is in tailwind and then a padding of six just so it matches some of the rest of the page we could alt Z here to have all of this code show but we really haven't changed anything else it shows the icons and it has the heading for the nav bar okay now it's time for a little cleanup so we'll go ahead and close up that components directory for now and the blog post hope you've moved those to a new repository because I'm just going to delete this folder now we do not need those in this project anyway longer after that we have a few dependencies that we will no longer need so let's look at the package Json and we're going to remove gray matter remark and remark HTML so these two right here and gray matter up here are no longer needed so let's go ahead and open a terminal window say npm uninstall and we'll say gray Dash matter and then we can say remark and then we'll say remark Dash HTML press enter and we should see those leave our project we can verify that up here now we no longer have remark and we no longer have gray matter so we have definitely got fewer dependencies right now but we will be adding more okay let's close the terminal window let's scroll back up now to our lib directory because if this red file here in the page TSX is bothering you as much as is me we want to change that function so when we call it in the posts that we no longer have this problem here so we'll come to the post.ts file and now inside of this file we're really just starting over so let's go ahead and Ctrl a to select all and just backspace and get rid of everything inside of post TS and we'll start over in this file I'm going to start by defining a function so it's export async function and it's going to be git hosts meta and then this function inside of it is where we're going to request some GitHub data but we need to do something first we need to set up a type that we don't have so let's scroll down in the file tree all the way down to our types.d.ts file here and we previously had a blog post type let's just change this name to meta it's going to have an ID that's a string a title that's a string a date that's a string and let's add tags and if you remember from our MDX files that is going to be an array that holds strings so we'll just put in that type and now back in our post.ts file we can add the type here for this function so here I'm going to say promise or return type I should say and it's meta an array of metadata or it could be undefined as well and so we'll go with that and now just to save time I'm going to paste in the fetch request to GitHub I'll press alt Z here so it wraps down you might want to get this from the course source code or you could pause to see this full URL but we've got the api.github.com repos then I have my username and then another slash and then the repo name which for mine it's just test Dash blog post then you have get trees Main and then you also want to put the question mark and put in this one param that is recursive equals one and that will flatten out the repo so you can just get everything from it here as objects and then the other things and of course I looked at the GitHub API documentation you could go do that as well well but the other things you need here in the header so you've got accept and this is a specific type of data we're accepting then this is important here this is where we're passing in that GitHub token we created so the authorization header must start with bear and then it has a space and then you want to insert the GitHub token and so this is a template literal string and then here you need this GitHub API version and this is exactly what they have in the docs right now so that's why I have it there as well now we did say the return type could be undefined and that's what we'll put here underneath so if the response is not okay we're going to return undefined and then I'm going to add a type here at just above the function and I've named this type file tree this is essentially the file tree that we're getting from the get trees here in this URL when we send this request and we're going to get this back it's going to have a tree and then inside of there it's got the path and the string and we're going to want to get that string out of there and I should add it this time if you want to copy this URL or make your own URL for your repo you could just paste this in a browser and it will make an unauthorized request but that's okay you get 60 of those per hour so no problem there just go ahead and put that in and you should be able to see what this will return okay let's scroll down and continue to complete this function let's look at the next couple of lines here so I'm defining a repo file tree this is what we're getting from GitHub it has the type file tree so we're just awaiting that Json data but here this is a little more important just a little more complicated I want a file array and so I'm using that repo file tree and we're mapping over each one of those and getting the path as a string from the object and that's important before we filter because if not if we just try to filter here without map we're going to have an object so I'm chaining map and filter together so after we get just an array of strings then we're filtering those to make sure they end with the dot MDX extension because later on and you saw in my repo already we have an images folder and some image files and we don't want to try to process those we just want the MDX files okay scrolling for a little more room we'll add the next couple of lines and review so now we have got posts and we're creating an empty array here that will hold metadata and that's fine we're going to go ahead and loop through that metadata and I'm using a four of loop because I want to await inside the loop and it's usually better to use something like four of in that case four each will not await just so you you know I've got a separate video on that anyway we're going to each post then we're going to create another function here that processes each individual file because then we'll have the URL the path that we got up here for each file and then if we have the post we're going to get that metadata from there push it here into this posts array and finally to return for this function we're going to sort the posts based on the date and that is from that metadata that we should receive okay let's scroll up and create this get post by name function and we want to create it above this get post meta function so here I will say export async function and it is git hosts by name and then it's going to accept a file name and that will be a string after that we need to add another type for the return type so let's go back to our types dot d dot TS file okay in this file we are going to have a blog post type so we'll call this blog post and set this equal to an object here that has meta and we'll set that as the type we defined Above So this meta type right here other than that we're also going to have content but I don't have that type ready yet so I'm going to temporarily put in any we're definitely going to come back and change this back in the posts.ts file now we are ready to put the return type here for this function so this is going to be a promise once again and it's going to be a blog post or undefined I'm going to scroll up just a little bit now just like before with our git Hub fetch here I'm going to paste in the GitHub fetch for this function you'll see it is very similar it's just not quite the same because we're getting the raw.githubusercontent.com URL here and then I've got my username the repo name Main and then the file name so we're getting the specific file and we're getting it from that raw data and you can view that in your GitHub repo as well I believe GitHub offers a button that says view raw data or something like that so you could see that as well once again you could put this request in your browser and put in the file name and you should be able to see it also now just like before we want to say if the response is not okay then we're going to return undefined okay scrolling for some more room again but underneath this return undefined line we'll look at the next two lines and essentially what we're getting now from this request test is the raw MDX file and notice we're awaiting the response dot text here not Json this needs to be text but if the file doesn't exist what GitHub does it gives a 404 page and so what we'll get back as text is this 404 not found so we're checking for that as well and so you might have a 200 response in other words that gets by this if here so if we get a 404 page even though the response comes through is okay we're going to return undefined here as should have been caught here you'd think they would send a 404 with that but for some reason our response is getting through so we send it here okay now we're ready to work with our remote data we've pulled in our remote data and we need to process these MDX files and we're going to do that with a dependency that's recommended by nextjs I'm back in the next JS docs under remote MDX and you can see they say there are pop two Popular Community packages for fetching MDX content and of course using that MDX content the first one here is next MDX remote and that's what I'm using today so let's just click on that and then we should go to directly to the part of the repo that applies to next js13 with the app directory support and react server components now this goes into quite a few details basically we're going to use this bottom example and then add a few extra things into it so it says access front matter kind of like the gray matter we previously had for that metadata outside of the MDX so we can pull that front matter out here with parse front matter and we can access it like frontmatter.title that you see right here and then we're still going to process the markdown that's in the file and be able to create content from that okay back here in our code let's scroll up to the top and let's import what we need actually we can't import it yet we need to install it so let's look at the pack is Json again and here let's open up a terminal and we're going to type npm I next Dash MDX remote and that should quickly install and once it's installed we'll confirm that here in our dependencies and now we have next MDX remote here in our dependencies so we can go back to the file so we will import and what we want is compile MDX and that's going to come from next Dash mdx-remote and this part's important we need to put the Slash and RSC and that supports what we're doing with react server components in next JS okay let's scroll down and complete our function so after this 404 where we return undefined I'm going to paste in how we use the compile MDX and then of course I need to close out the bottom of it here we're going to add more to it later but this is the basic we'll start out with the basic setup essentially so we're getting the front matter so we can use that as you saw in their example and we're also getting the content then I'm putting the type in here for the front matter itself and that has the title the date and the tags now remember in the type of blog post when I said we would come back that needs to be the content type and not any that we temporarily put in here so I'm just mousing over to get the intellisense I'm going to come up here and copy this part I still see some innies in there but I think this is better than just putting one plane any for everything and this is the type that's coming from the compile MDX so that's what I'm going with so I copied that let's go back to our types.d.ts and I'm going to paste that type in okay back to the post.ts and we'll finish out this function now that we have called the compile MDX function that we have from the remote dependency okay the last few lines here what I'm doing here is getting the ID without the MDX extension so I'm using a regex expression here to remove the MDX I'm calling replace on that string with the MDX regex and we're just putting in an empty string there so it removes it other than that we've got a blog post object and we gave this the type blog post that we just defined so it starts with meta and then meta is the type meta so it has to have everything that was in that type and you see that here we're using a lot of that front matter that we received up here from compile MDX so we get the title the date and the tags the ID we just got here when we removed the dot MDX from the file name so that's what the I ideas and then here we have the content and then we just return that blog post so let's save this file now if we move down we should see where we were using that and here we do with the await get post by name and as we can get both meta and content from it here in this post meta function that's what this is get post meta we're just destructuring the meta after we get it and we're pushing it into that posts array now I'm not sure why we have the little red underline here it says cannot find this that's because we had it here first oh get post or get posts that could be a problem as well so get posts by name let me go ahead and put the S there typescript just saved me from a typo but now that I think about this this function is actually just to get one post so instead of adding the S here let's remove it up here where we Define the function and call this get post by name okay we're finished with the library functions in in this posts file for now but I just want to add that if I'm moving too fast for you if you want to go ahead and re-watch part of the video or go ahead and view the source code that I've provided at the link in the description for this lesson that's okay but for now we're going to move on to the components directory and then we're going to look at the post.tsx file for the posts component let's start by replacing our get sorted post data function and I'm going to press Ctrl D to just select both instances of that and we're going to bring in git hosts meta that we had already created in our posts library after that we need to make this an async function and now let's go ahead and put an await in front of get post meta as well now we still have posts but we might have undefined posts as we check the type here of post you can see it's an array of metadata or it's possibly undefined so let's just quickly handle that and I'm just checking to see if there are no posts and if that's the case we're going to return sorry no posts are available and now just a couple of quick classes to add here to our unordered list class name we're going to add a list none so there will be no bullets and then let's add a padding of zero here to our Tailwind classes and with that we're finished with this file and you can see typescript is underlining post here as we pass it into the list item so let's go to list item component now and let's just change our props type here so we have props post but instead of a blog post it's just going to be that meta type that we created and now you can see the problem is gone from our post component as well now we're ready to close the components directory for now and let's go to the Post directory and the page.tsx file inside of our Dynamic post ID directory here under posts let's start by changing out the functions we're importing so we're going to import git posts meta and then we're also going to import git host by name and after those two Imports I want to go ahead and add a type to this file for props so I'm going to say type props equals it's going to have params and then that object is going to contain a post ID which is a string one other thing I want to do is set a route segment config at the top for revalidate and during development it's easiest to set this to zero we can change it later and this will automatically make our Pages server side rendered because it will not cache anything this is like setting the cash to no cash and this is a good way to catch errors during development but then we'll come back and we'll add a longer duration here so we do use cache data and can create SSG pages and that those will be statically generated of course so we're just going to put this here during development and we'll do this on a couple of other Pages as we go as well now let's scroll up and look at the generate static params function so we're going to get posts and so here we'll need to await but of course we need to set this as an async function as well so we'll put async function here and we're going to await our call but this is not the call it needs to be get posts meta and note I said dedupe here in the notes from the previous code the previous lesson in 10 and this is still correct all of these fetches that our server side will be deduplicated during the build so we're not worried about using this essentially just request data wherever we need it and these will be deduplicated by next.js so that's good now we have a note here from typescript because posts could be undefined so let's go ahead and handle that as well and we'll just say if there are no posts we're going to return an empty array and we can see that generate static params should be returning an array that is an object inside with a post and ID but we could just return an empty array if we don't have any posts that's essentially what would happen if we didn't have any posts and we tried to map over it but since we could possibly be undefined we would have a problem if we tried to map over undefined so that is the complete function now I should note that while we have revalidate set to zero if we attempt to run a build or even I believe run in Dev we'll have a problem revalidate equals zero and having a generate static params function do not mix this would cause a problem so so we just want to comment this out while we're using that revalidate equals zero now we're ready to scroll to the generate metadata function and I'm going to change what we have here for props so let's just start over with that and we'll have an object that has params and then we're going to destructure the post ID and then outside of these brackets we'll put our props and that should be good now the problem we have with post ID is that we were previously destructuring it here inside of the function so let's just remove that as well now we need to make this an async function and then we also need to await our function call and our function call is going to change this is going to be git post by name and we need to pass in a template literal string because we're going to pass in the post ID that the function is receiving and we also need to put the file extension.mdx right here at the end this will also be deduplicated now we're no longer trying to find a post we already have the individual post so we'll remove that but now we can say if there is no post we want to return post not found and I can see typescript is telling me I have missed something and I should have said post not posts up here so if there is no post we're returning post not found for the title this is very minimal metadata of course you could return more and there is much more metadata listed in the documentation I'm just doing something very simple here now post is going to have meta content in it from the blog post and so when we check that we actually now instead of just post.title it should be post dot meta dot title now I'm going to copy the props that we have up here and then scroll down to the next function which we already have as async and this is our post component so I'm just going to paste in the same props here so it's structured the same way of course get rid of where we're now destructuring or we previously were destructuring post ID inside of the function now here we want post once again so this is essentially the same line As Above also so we could just copy our post equals again being deduplicated and we'll paste it right in here and after that we're ready to move to the next line which should once again be simpler than what we had here before so we can just say if there is no post now we're going to call not found and we had already imported this not found function up here at the top from next navigation now in the past I may have used the return keyword with not found but it is not required and I noted that in the docs because not found uses a typescript type never so there is no reason to use the return keyword with not found now let's replace this line so instead of getting post data ID we've already got our posts so here we're just going to destructure our metadata and our content and that's going to come from the post and now our publication date is going to come from that meta object so we just need to have meta dot date there there's one more thing we want to add here and this is creating the tags now I just pasted this in but I will walk through this with you because we have our metadata if you remember it has a tags array of all the tags we relate to our articles and we can map over that array and then create these links because we're going to use these as related content at the bottom of the page so we're just creating related links to other hashtags and we're going to have a dynamic route for these tags where we can see a list of the related articles if we click on one of these we just haven't created that yet and now I'll scroll down to the jsx and I've made a few changes remember the main element is already in the layout so we're not going to need that what I'm going to do is just highlight this and replace and quickly break it down for you so we have our fragment here and if I save I think we're going to get better 4 formatting because the fragments the parent and then we have our heading here that's the meta dot title now there's our Pub date still and I may have changed some of these Tailwind classes now we have the article with the content that we previously had in a note I moved the link to back home outside of the article as it was previously inside and we also now have a section with related links and that's where our tags go now let's go to our not Dash found page just in case that not found fun function gets called now this is very basic right now so I'm just going to replace it with something that's not quite as basic but still fairly basic just as sorry the requested post does not exist and it gives a link back to home so I have imported link from next link and I also want to create an error.tsx file and we have done this in the past in this next JS Series this is nothing different this is essentially the Arid component the file error.tsx the example that was is in the docs so I haven't changed much of anything here error.tsx is always a client-side component and they must be we come down here I believe I may have put a link back to home that might not have been there before but I might have used this in the previous example as well I literally changed nothing from what I had previously had looks like I still need to save the not found file and we'll go back to the page.tsx file where we started here inside of the dynamic posts route with all of this complete I'd like to try out the app but remember when I said we would come back to that compile MDX function now is the time to do that so let's go back to post.ts and it was in our get post by name function let's scroll down to where we find it here we go it also accepts options so we want to add an options here and this is an object inside of this we're going to say parse form front matter I almost said formatter parse front matter and this is going to be set to true now there are some other options we're going to come back and add in the future as well but we'll just go with these for now so this is saved and I believe we're ready to go ahead and try out the application so let's open up a terminal window let's do npm run Dev start the application in Dev mode just to check it out and remember our revalidates are all set to zero so we should just be getting server-side rendered Pages let's go ahead and hold down control and click localhost 3000 and see what we get here inside of our Chrome browser and there is the blog so this is pulling in everything that I have for articles from GitHub in that other repository it looks like it says I have one error here already which is not totally unexpected because we're not finished yet but this is working so far let's go ahead and just check out a post and yep now we have an error there because of that let's see if I've got a post that doesn't have any other components in it possibly this one is okay because we didn't put a video component or an image component in it yet and of course we haven't handled those yet but look at this we've even got our code Block in here now it looks a little bit plain so we're going to do something to make this look a lot better as well I'm on npmj JS and we're going to use highlight JS to highlight our code and make it work better or at least look better it's going to work the same actually the code examples in the blog posts and in combination with highlight.js we're going to use this re-hype highlight extension and we're going to pass that to our compile MDX function through the MDX options a couple of other packages we're going to use so we'll install those while we're at it we're going to use re-hype slug this will add an ID to headings now when I talk about headings let me pull in a markdown file here from the other repository where we have our content this is a heading in markdown you can see it's got the two hashtags a larger heading would just have one hashtag I guess I don't have any up there for that but you can create different sizes of headings and you may or may not be familiar with creating markdown files but that's what a heading is in markdown okay so we're going to add IDs to the headings then in combination with that we can use this re-hype Auto Link headings and this is going to add links to these IDs so we can link the specific parts of the article as well and all we'll have to do is create a heading in our markdown file okay I'm back in vs code and I've got the package Json open if you have your Dev server running go ahead and stop that for now with control C we're going to install these new dependencies now I'm going to right click and paste them in but what you need is npmi and then you can install them all at once if you want to or you could do a separate install for each one but here we've got highlight JS then we have re-hype Dash highlight and we have rehype Dash Slug and finally rehype Dash Auto Dash link Dash headings I'm going to install all of these dependencies at once here with this line so I'll just press enter and that should get started with the installation and then we'll see them added to our dependencies here in the package Json hello it looks like I had an error there with that let's try that again I don't know what happened but we can check it out let's see it says rehype Auto Link headings not found okay maybe I typed that one wrong let's go ahead and paste the others in and I'll just backspace over that and we'll go back to the npm page and double check that one so all of these will go ahead and install and that was fairly quick we can check here we've got re-hype highlight rehype slug we've got highlight JS up here as well let's go back and check npmjs or this rehype Auto Link headings yes I put a dash between Auto and Link so let's just copy that go back to vs code and install this last dependency as well so now I can just right click and paste that in press enter and it should be good I had one extra Dash in there so all the dependencies are now added okay let's go back to our lib directory here with the post TS file and we need to pass all of these in to compile MDX and of course we're going to need to import those as well so I I guess we could start at the top with the Imports and we'll say import re-hype and that's all lower case and here we see them at the top so I'll just go through them Auto Link headings that looks good then we'll import re-hype and we'll get react highlight and finally we'll import re-hype and we'll get re-hype slug so we've got all three of those and now we're ready to scroll down to our compile MDX function and pass these in so scrolling down to where we see that I think I went past it there it is compile MDX and now we've already got the options object and they're going to go inside of here so after parse front matter set to true I'm going to paste this in and we'll look at this so inside of the options object we've got an MDX options and then we set rehype plugins now you can use other plugins with this compile MDX as well so you can look at the documentation I'm linking to for that I chose to use the re-hype ones we've got rehype highlight here we've got rehype Slug and then notice we've got an array and inside this array here or these brackets we've got rehype Auto Link headings with a comma and then we're passing in an options object and this is behavior set to wrap so a essentially we're creating the link with that there are some other settings you can check out as well but we're not quite finished we still haven't used highlight yet even though we have rehype highlight here okay so let's go back to the post directory and the page.tsx inside of the post directory and here we need to import highlight JS and then we say slash Styles and there are Styles we can choose from and the way to find these is to scroll down and go into your node modules and then scroll all the way down alphabetically to highlight JS which I'll be there in just a second once you get to highlight JS you can come down to the Styles directory and now you see all of these CSS files they are all themes that you can use for your code Snippets and so you can experiment with this and choose what you want I'm using GitHub Dash dark dot CSS so that's what I'm going to put Hub Dash dark dot CSS now I'm going to close up the node modules because it is huge and it just displays so many files it can get out of hand so it's best to keep those closed when you're not browsing those okay now with that complete we will save the changes and then press control on the back tick to open a terminal window type npm run Dev to start the server and then hold Ctrl and click on localhost 3000 to launch the blog in your browser and here it started so now let's go to a post that I know should have a code snippet in it but probably doesn't have one of the other components we haven't handled yet here we are look this looks much better than what we had before it is color coded with that theme GitHub dark now if we scroll further down on the page you can see our related area that gives us our tags but we haven't created those Dynamic Pages yet at the tags route where it goes tags and then it has the actual file name there or tag name if you will so let's go back to vs code and do that quickly we're back in vs code now we want to go to the app directory and inside of the app directory we want to create a new directory named tags and this is going to be a dynamic directory so inside of tags let's go create another directory that holds what we pass to it and that will be the tag inside of brackets so now inside of this Dynamic directory here actually in the tags path the one in Brackets is the dynamic directory let's create a new file name page.tsx our page inside of this Dynamic directory is going to display a list of matching blog posts that all have the same tag so a lot of it is going to be like the page we have inside of our post ID Dynamic directory but when it's displayed the display the jsx is going to be more like we saw inside of the components for the posts component so I'm I'm going to move quickly here because it's kind of a repeat of things you've seen before so what I put in first are the Imports where we bring in git post meta the list item component because we can use it for this list as well and the link from next link I'm going to set a revalidate and I don't want that set to 86 400 right now I want that set to zero here during Dev mode during development so it's easier to see any errors if we have those and we're not viewing cache data then I've got to type props it has params and then a tag instead of a post ID that is still a string now let's look at the generate static params function and here we're going to get all of the post metadata with get post meta and of course if that doesn't exist we're going to return an empty array because generate static params should return an array of objects and if those objects don't exist it will just be empty but then we're going to get all of the tags from all of the existing blog posts now this part is important here so we're going to map over all of the tags we're going to have an array of all the tags but then it would actually be an array of arrays because remember each tag itself is a collection of tags this tags here is an array to begin with so we need to call flat on this array that's created with maps we flatten all of that out and then we wrap it in a new set to remove all of the duplicates so at this point we should now have a new set of tags with no duplicates but we do have all of the existing tags but now we need an array of objects so we're going to use array Dot from on the tags and we're going to map over that array and then create the objects that we need and it would be a tag for the key and then of course the actual value is whatever the tag is so that's what we're returning from generate static params now we can't forget this we're going to comment this out for now while we have revalidate set to zero so control and the Slash and we still have revalidate set to zero again we'll come back and uncomment this this is just during development in case we have an error just much easier to find when we're not working with cache data next let's look at generate metadata so here I'll paste this in which is very small in my version I've got generate metadata we're getting those params that match the props and then we're just returning a basic title posts about and then whatever the tag is however you could put something in here to say if there was not a tag maybe you would say No Tag provided or something like that I just kept it very simple here and again you could add much more metadata to this if you want to remember to reference that in the docs okay I will scroll for some more room and we're going to call this component tags post list and I'll start the component here and then I'll add the curly brace to end it now we're going to add more to this but I'll go over what we currently have and I'll wrap this down with alt Z as well so it's receiving the params with the tag and we're getting all of the post metadata once again remember this is deduplicated so just request data where you need it now if there's no posts we're just going to return sorry no posts available and of course that that also applies to our tags list it's going to display posts that match the tag and then we're going to get the tag post by filtering all of the posts to see which posts include the tag that is being passed and then if no tag posts exist we're going to return this sorry no post for that keyword or we could say for that tag and also provide a link back home but now if the tag posts do exist let's go ahead and return some jsx here and this is going to be basically what you saw with our post component so we have the heading here results for tag and then we're using that list item component as we map through the tag posts let's open a terminal again with control on the backtick we already have Dev mode running let's get out of that with control C and we'll start it once again with our new changes npm run Dev to start the blog application once again and I'll click on localhost 3000 and this should launch it in the browser I'll close the old version of the blog and now we should be able to test if our hashtags are working now this first post has a video component in it that we haven't handled yet so I'm going to click the second one so we don't get an error scroll down here and I'm going to look at the tags related here so I can click any one of these I'll just click the first one and here's a list of all the articles that have that tag now that's most of them so let's go back let's click the new tag which doesn't have as many and we see only three articles have that tag so our tags page our Dynamic list of articles that share tags is now working I'm back in vs code again let's go ahead and close the terminal window here after we close out of our app and now you'd think we'd have enough dependencies but no we need to add one more and it's specifically for Tailwind you can see what I'm adding here npmi then it's at Tailwind CSS slash aspect Dash ratio at latest and then here at the end it should just be a Dash D so I don't know why those other characters were there but we'll just have Dash D because this is a Dev dependency let's go ahead and add this and we're going to use the aspect ratio as we share videos in our MDX file so we can pull in some YouTube videos let's check our package Json to make sure we added that dependency as well so we should see that here in the dev dependencies and we do right alongside the typography dependency we have the aspect ratio dependency from tailwind and now in the Tailwind config file just like we required the typography here for plugin we're also going to require the aspect ratio as a plug-in for Tailwind now let's go to the components directory once again and we're going to create a video component so inside of here we'll create a component called video.tsx I'm just going to paste this in it's fairly short we see our props is an ID with a string use the props here and there's the ID then we're going to return this now this iframe is what you get from YouTube if you say you want to embed a video and YouTube provides that so a lot of what you see here is just from YouTube as far as the allow and here the title I'm just putting YouTube video player which I believe is the default from YouTube as well and they always provide this URL now what we need to do is pass in the ID of the video every video has an ID but also important to note that we're wrapping this iframe in a div and notice the class names here we've got aspect Dash w-16 aspect Dash H dash nine so that's that aspect ratio that we just installed as a Dev dependency for tailwind and it's allowing us to size this video responsibly to a 16 by 9 and that's the normal size for a video so that's important that makes it very easy to do for videos when you add that aspect ratio dependency now as I bring my blog post back over here and we look at this other repo you can see I've added a video component directly to my article that says post for today or my blog post that is post for today and actually that was yesterday today is May the 4th as far as I am of course you may be watching this in the future but anyway here is the video component we've got the ID that we're passing in and that's all you need to do in your MDX file so May the 4th be with you if you're a Star Wars fan now we're back here with the video component and we're not quite finished because we need to pass it in to our compile MDX function let's head back over here to the file tree into the lib directory post back to our compile MDX function there it is so at the top we're just going to import our video component there it is and then we can come down here and we're going to add something here to these options once again so we had the parse formatter or I said parse front matter there we go and MDX options we also have a source well this is outside of the options object so after Source I'm just going to put it right here and it is components and then it accepts an object and inside of here we can pass each component we want to pass and I don't know why it just set that to lowercase but I want that upper case and then we might pass another component here in just a few oh and I need a comma here which type script caught for me and now it should be good to go just to save a little time we will test out the video component and our Custom Image component at the same time so let's get started on that as well before we go anywhere else so let's go to the next dot config.js file because this is the first thing you need to do if you're bringing in images from a remote source so I'm going to paste in my config here you want to have images and remote patterns and then inside of this remote patterns array you need an object that provides the following so the protocol is going to be https you're really breaking down the URL that you have for your images then here the host name is raw.githubusercontent.com and the path name has your GitHub username and then it has your repo name here as I have test Dash blog post then your branch name which I had main which is probably yours is as well now I have mine in an images directory and then the two stars go where your actual file names would be that would be changing so that is your full path name and you need all of this in your next config.js now let's go back to the components directory and create that Custom Image component inside of components so here a new file and I'll call it custom image.tsx I'll just paste it in and review it with you here alt Z so everything shows which was just the curly brace I guess but here we need to import in image from next image first we've got some props we're going to have a source and an ALT that are required priority is not required at least the way I have set this up so this Custom Image component is going to receive a source an alt and possibly a priority so here I'm just checking to see if we received the priority because it's either set to true or false so if we did receive it we set this to true this variable here otherwise false and then we go ahead and set this up now what we want to notice here is I've gone ahead and used some Tailwind classes right inside of this component and that's part of why I wanted to create a custom component and then after that we're passing in the party here and here with the width and the height they're set to 650 but not every image is going to be 650 pixels height you know as a square height and width the same however these are just approximations for next JS next JS will take this into consideration but it will size your image to what you think is best so what I'm really setting here is my Max width but we'll see with a couple of images that I've put in my articles that next JS goes ahead and keeps their aspect ratio as it should be it doesn't turn a rectangle into a square for example so let's save this component and then we can go ahead and try everything out and I should highlight back in my blog here to show the Custom Image component and how we're passing everything in an MDX file so here it is passing in the source and you want to have that full URL for the image and you can get that at GitHub and then you can pass in your alt text as well and notice I did not set the other the priority I just didn't send one so that will be set to false but you do set priority to true if your image will be above the fold if you think it will load immediately that's when you want to set priority to True let's go ahead and drag this back out of the way and check everything out by opening up a terminal and once again doing npn run Dev and we'll start up the browser vocal host 3000 this is probably going to move on me right as I click there we go and we've got it open I'll close the previous one just so we get the fresh and it'll get this page going here Dev Mode's a little bit slower than if we of course had our static Pages already okay we've retrieved the data everything is probably going to look okay but let's find out this page has a video there it is right in line with the rest of the article it also has a code snippet that's good let's go ahead and scroll down to the page that I think I put oh you have an error here I think I put an image in this page let's go back and see if there is another one and it also has an error might have to check out what those errors are and I think I already know we probably got ahead of ourselves there as we started up this application because we needed to go back to posts and we needed to import Custom Image up here at the top and then pass it to our compile MDX so that's part of creating a long tutorial forget a few things along the way so here we go video now let's put in Custom Image and now we have both components being passed to the compile MDX let's go back and see if we still have an issue I may have to restart everything or if it's going to be okay let's try out post for today still has the video okay let's go here and we still have an error so probably going to have to restart that side of our terminal here so let's go ahead and Ctrl C to get out now we'll npm run Dev again so it passes the component to the compile MDX now with that going I'll click localhost 3000 come back close the previous browser window looking good got our video let's come down here and check this article now this article is working scroll down here and we have our image notice it's it doesn't really look like a square it's taller than it is wide now I've got another example where we're going to have one that is 16 by nine and I believe that's this one as it loads there we go and this is actually a really large image so nextgs has to work with that a little bit and it also looks good here so it's keeping the aspect ratio of the original image even though we put in the height and width at 650. okay I'm back in vs code if you haven't stopped the dev server go ahead and do that there's one other thing we'd like to add that next JS recommends for production deployments and that is to install sharp so we'll say npm I sharp we don't have to do anything other than install it to our project next.js will use it automatically to help optimize our images so we went ahead and added that while we're talking about images packet npmjs.com one thing we can really do to help our blog project or any project with the search engines and SEO that is search engine optimization is create a site map and one dependency that will really help us do that is next Dash sitemaps so we're going to install that here you see in PMI next sitemap I'll just copy that and head back to vs code back in vs code I'll open the terminal once again and I'll just paste that in and we'll install next sitemap as a dependency and then we'll get that set up okay let's close the terminal window scroll down to our package Json just to make sure we've got next sitemap installed and you can see it right here so now that we know that's installed we need to create a config file for it so just in this area where we have package.json and next dot config.js let's create a new file and this will be next Dash sitemap.config.js okay inside of this file we've just got a few settings to put so I'll just put those in here and we can review so we have this line at the top that has at type and then has the import next sitemap.i config but after that what's important here is the module exports with the settings the site URL we're setting to a environment variable so this is one when we deploy we would want to find out what our URL is if you don't have your own domain like a.com if you do you'll already know of course and you'll want to put that in your environment variables and then we're just putting in the short circuit here or so if that's not the case when we're here in development it will set everything to localhost 3000 then generate robots text true and generate index sitemap false or that is for larger sites so if you had hundreds and hundreds of pages you could actually have a page that says okay here are the sitemap pages and it will create many sitemap Pages for you we don't really need that we're just going to create one sitemap page so we set that to false and just to be accurate let's go ahead and remove the S here from The Local Host because localhost runs on HTTP here in our Dev environment not https and then we have one other setting so we need to go to the package Json and in our scripts above we need to add a post build script to create the site map so we'll put a comma after lent and here at the bottom I'll put post build as all one word and after that we'll put next sorry next Dash site map right there and that is all we need as we near the Finish Line it's time to go ahead and check our revalidation settings and that will lead to our incremental static regeneration of our pages so let's go to the root page TSX inside of the app directory and we want to change our route config that has revalidate equal to zero to a small number like 10 seconds and then it will expire quickly and allow us to check the revalidation which was actually the ISR or incremental static regeneration okay now from there we also need to change this setting in our tags page TSX so we'll go ahead and make that a 10 as well and remember we commented out our generate static params function because that wouldn't work right if we had revalidate set to zero because we wouldn't have static pages so now let's go ahead and uncomment this function and save this file let's move on to the page TSX inside of our Dynamic host directory also and we'll do the same thing so set revalidate to 10 and let's uncomment the generate static params function as well okay we're ready to open a terminal now and make a build if you remember we can only check our ISR our revalidation essentially when we create a build we can't do that in Dev mode so I'll type npm run build while this is building I'll tell you the rest we'll go ahead and start the build after it completes now after we have it started that 10 seconds will expire and while it's expiring we're going to change one of those posts that we save in our other repository that has our MDX content and we're going to send that up to GitHub and then we will refresh our page and we should get that new data and also remember revalidation with ISR it's going to take two refreshes the first one will trigger the revalidation the second one will give us the new data okay the build completed and take a quick look at this it did generate a site map we have that notification here so that's working as expected we have SSG Pages now our server side render is probably our old revalidate route that we're still going to change yet and that's the on-demand revalidation that we'll check later but let's look at our Pages up here so the dot that is filled in with white indicates SSG and here's our Dynamic post ID directory here and here are the posts so we did generate those static params the same for the dynamic tag page as well so here's all of the tags from the different articles so everything's looking good there let's go ahead and start the project with npm start and we'll pull that up it's running on localhost 3000 so control click and we should launch that in the browser I'll close the old one we had running for Dev mode and now here's our project with the static generated Pages they should load fairly quickly it pulls in the video everything looks good there I'll scroll down here everything is loaded quickly as well we've got the image it's looking great so now let's change an article and send that to GitHub and then we'll check our revalidation I'm pulling my blog repository over and here's the blog post once again let's just change this file I'll change it from today.mdx to tomorrow.mdx I'll also make this say post for tomorrow we'll save this I'm going to push these changes to my GitHub repository and then we'll go back and check the revalidation in the browser back in the browser now I've pushed my changes to GitHub and it's been way past the 10 seconds for revalidation so we're going to go ahead and refresh once to trigger that revalidation and now the second refresh should get us the new data and it does this change from post for today to post for tomorrow let's go to the page and we have post for tomorrow in the page as well so our revalidation route segment configs are working as expected okay we're back in the next JS docs and we're at the revalidate path API reference now this wasn't available even yesterday so if I'd made this tutorial just a day ago we wouldn't be able to go over this new information but this was just released with the new docs and I wanted to make sure to add it so now we can go ahead and delete that old Pages directory that has the API folder that previously support ordered on-demand revalidation and now xjs has provided two different ways to do this and one is the revalidate path and that's what we're going to go ahead and use today okay we're back in vs code in the file tree find the app directory and in the app directory you should have an API directory if not you'll want to create one but there is this hello example here inside of my API directory if you started with the starter source code for this tutorial so I'm going to click on this API folder right here and then I'm going to create a new directory inside of it we're going to name this one revalidate and then inside of revalidate we're going to create a route TS file but before I forget we've now created a duplicate route because we had the older version of this route in the past and that was in the Pages directory and then there was an API in our revalidate.ts we can get rid of all of that so click on pages right click and choose delete and just remove it from the project and of course I'm getting some message about deleting permanently but now it is gone if you get a message of course just okay that as well now we want to go back of course to our revalidate route right here okay in our route TS file we're going to import next request and also next response and those are going to come from next slash server okay after those Imports we also want to import revalidate path and that's going to come from next slash hash okay with those Imports complete we can start our function export async function and this will be a git request so we can just pass in a URL we have a request here and this is a next request and then inside the function we're going to get our secret from the URL that we pass as a parameter so we'll say const secret and that's going to equal request dot next URL dot search params and then we'll say dot get so we get it from the URL and it will be the param that is titled secret after that we can say if secret is not equal to our environment variable so process.env dot my secret token is what we have named it we're going to go ahead and return a response or a new next response and the first thing we're going to do inside is json.stringify right here and we'll pass in a message or an invalid token well there we go a single quote invalid token and let's go ahead and wrap the code with alt Z so that comes down after that we need to go ahead and put a comma here at the end of that and oh not there at the end after the first parentheses then we're going to need to supply the next one and then we'll put in an object here and we'll have a status that is a 401 then we'll put in status text and that's going to be unauthorized and then we'll put another comma and add headers inside the headers we're going to say content type is application slash Json there we go now we're going to need to wrap this here at the end with that closing parentheses and all looks well as far as this response where if the secret doesn't match now if it does match we'll make it down to here so let's go ahead and get the path param at that point so that's once again request dot next URL dot search params dot get and then we'll get the path and then we could actually add a short circuit here and say or just go ahead and revalidate the home page and that would work as well now after that we need to call our function revalidate path and we pass in path after that we're going to return the next response dot Json and here we'll just say revalidated and say that is true and that's the complete function for our on-demand revalidation route so we'll once again be sending it to the same route it goes to API slash revalidate and now this will just handle it and of course it is a get request at this route now that we've added this new route let's go ahead and delete the default hello route we no longer need that or want it there let's go to the root page TSX file once again and now let's set the revalidate time to something more like we would actually use let's go with like 86 400 which is one day in seconds now I'm going to copy this because we're going to use it in the other route segment configs as well so let's open up tags and go to that page TSX and we'll change this 10 to 86 400 make sure you save these changes as you go and then we'll go to the page TSX inside of the post route we'll also change this to 86 400. now that we've made these changes let's create another build and we will test our on-demand revalidation with that build so I'm going to quit with Ctrl C the build that was currently running and now I'll do npm run build and when this completes of course we'll start the build again as well the build is complete let's go ahead and start the new build with npm start and now we have localhost 3000 control click get that open here in our browser I'll close the other one everything's running as it should be so let's go ahead and bring in the blog articles again here's my blog article repo that I'm pulling back over in another instance of vs code I'll go ahead and rename this file and I'm going to name it weekend.mdx now and I'll say post for the weekend and we could even add something else in the page even though that would probably be enough I'll just add a heading here that says hello okay we'll save those changes now I'm going to send this up to my GitHub repository and then we'll go ahead and test out our on-demand revalidation okay my file changes are now in the GitHub repository that we're pulling the data from those MDX files and now of course we have our revalidation time the route config set to 86 400 so it's one day so no matter how many times I refresh here we should not see a change and there's three times I'm still not seeing post for tomorrow change that's what we expect okay we're back in vs code I'm going to use thunderclient to test our on-demand revalidation route you can use Postman or you could even just paste the URL into your browser and it would probably work as on-demand revalidation as well because it's a get request so let's change this to its HTTP localhost 3000 slash API slash revalidate and then we're going to have a path and we'll set that equal to our slash just for the home now if you remember we could leave this out as well and it would default to home and we can put an ampersand and then say our secret and that's going to equal at least for my secret Dave Gray teaches code and now if we pull this down a little further I think thunderclient shows us our params here as well so we see those query parameters I'll close the terminal window just so we can see the response also and let's go ahead and send this request and we get revalidated true right away so now let's look at the browser and we'll refresh to see what we get and now it took two refreshes there I was thinking it was only going to take one so I don't know if that's something because I'm running it on localhost or if it's just the way it is but after I revalidate it it still took two refreshes I thought that first on-demand revalidation that I sent would trigger that already and it would just take one so that's an interesting thing but besides that everything worked as expected here's the new heading that I put in notice it has a link too because remember that rehype Slug and re-hype Auto Link heading that we added as well and then it's got post for the weekend up here so that also works as expected and now we're ready to deploy our project so if you haven't already you'll want to create another GitHub repository for your blog code not the other code that we had not the MDX files we've already got a repository for that so if you don't have a GitHub project for your blog code that we've been working on go ahead and create one of those and send that up to GitHub as well and then we're going to go ahead and deploy this project at versel.com okay I'm on GitHub and I have pushed my project here in a new project so if you go on my GitHub you can find this at my nextjs remote MDX blog so that's what we're going to look for when we log into versel and pull our project over for deployment let's go to versel.com okay I'm at versel.com and it automatically logged me in because I already have an account you can create an account and Link it to your GitHub account that shouldn't take you long if you don't already have a versel account and then you can go ahead and be at this dashboard which is where it will take you immediately when you come here when you're already logged in and you can see my GitHub username up here in the top left okay we want to add a new project now so I'm just going to click that and choose project and from here we can search our GitHub repositories so that's what I'm going to do right now and I may need to adjust my GitHub app permissions if I can't find what I'm looking for let me see if it will even bring in what I'm looking for here for repositories no results found so that means I haven't given it permission to view all of my repositories you can do that or you can do it on a repository basis so I'm going to go ahead and configure this in my GitHub and it pulls this up here to my GitHub account so let me bring this to full screen and I should be able to tell versel to be able to access essentially which repositories here so now I can select the repositories here because I've chosen only select repositories you could choose all repositories and that would be fine as well so I'm going to select repositories and I can search I'm going to search for my Dash next JS and it pulls up here immediate immediately so now I've got that project I'm going to save this setting here in GitHub and we're back at versel.com and it now has access to my next JS remote MDX blog and I'm going to import that now into Purcell okay we're now ready to configure our project and it's already filled in the project name directly from the repository and I'm going to leave it at that we're using xjs the root directory here basically the default build and output settings there's nothing here that I want to change either so I'll go ahead and let that slide back but let's go to environment variables which we have a few to add so if you remember we had in our environment or dot env.local file we had my underscore secret underscore token and then we want to bring that over from what we had inside of our code and I had Dave gray teaches code for my secret token so we'll click add for that now we want to add another one and we had a GitHub token so GitHub underscore token and we want to put that value in and of course I'll be changing these values after I publish this tutorial so no trying to use these essentially because they will not work you need to create your own and then there's one more environment variable and if you remember that was in our next sitemap config file and it refers to the site URL so we want to put site underscore URL but the problem here is we don't know what we're being deployed to yet what our URL will be now if you already know this information like you have a.com that you're going to use with your blog then you would know your site URL but at this point we'll have to add this later and then come back and redeploy essentially so let's just go ahead and leave it at these two for now and let's deploy our site so I'll click deploy this will take a little bit and I will come back when it's finished and of course we can see the progress here if we look at building we can see the logs and everything so you might want to do that as well just in case you encounter any errors and our build is complete so now we've got a congratulations page we got a little bit of confetti we can see the project here and now it gives us some next steps so instant previews add a domain that's one thing you might want to do uh enable some speed insights any of those things really we just want to go back to the dashboard now and then we can see where we're deployed so here's our domain which is my Dash next JS remote MDX blog.forsale.app so that's a pattern there where we have the name first and then dot versus app where we would probably know where our project would be deployed now let's go ahead and use that the only thing that we needed an environment variable for that we didn't put in the value for right away was for the site map so the site map will be wrong and we'll need to update that but otherwise let's go ahead and launch this in a new browser window and there is our blog and everything is deployed let's check out out a post here able to pull in the video we have the big hello heading that I left in there so of course you can adjust this content the way you want it but everything seems to be working here as expected if we scroll down we have the static generation there is an image and so on okay back in the dashboard now let's go to settings for our site and if we scroll down here on the left we see environment variables so we want to add one more and that is going to be site underscore URL and we just paste in the URL for our site that we have deployed here at next and I'm not so sure we need the slash there actually let's just go without the Slash and let's save this URL and that looks good and now when we redeploy we're actually not going to have to pull the code since we haven't changed the code so that is one nice thing here let's find where we redeploy maybe under deployments or I bet there's three dots right here and now we have inspect deployment or role back at that point so I think it's going to be under deployments and now let's go ahead and choose something like redeploy there it is now it gives us this nice question here use existing build cache and really that's what we want to do it's the same build we've just put in the new project configuration and that's what it says but with the newest configurations from your project settings and that's exactly what we want so we'll click redeploy and it shouldn't take too long to go ahead and redeploy this we can see the duration right here and when this finishes I'll come back okay the redeploy is complete it took 32 seconds let's go ahead and visit the site once again everything still looks good here let's see if our site map built as we deploy to our site so at the end of our URL we just put slash sitemap.xml press enter and there is our site map so the next sitemap dependency is working as expected and you can see it created a map of all of our statically generated Pages those SSG pages that we created are all there so that's working as we want it to and now with our blog deployed let's check out our on-demand revalidation one more time so I'm going to pull over our blog post once again so you can see me make a change I'm going to change this weekend file and rename it to Saturday and now that I have a Saturday file instead I'll call this post for Saturday and I'm going to remove that big hello header that we had here as well so we've made a few changes now I'm going to push this back to GitHub and then we'll try out the revalidation okay I'm in thunderclient now all the new updates to the MDX file have been pushed to that GitHub remote repository and notice the address I now have up here for my revalidate my on-demand revalidation it has our new URL for our project at versel slash API slash revalidate and then you can see the params here thunderclient makes them easy to see down here so we've got a slash just for the home page and then of course the secret for our revalidation let's go ahead and send this and we should get a revalidated true and there it is now let's go check our site so here we're back at the blog project and I'm going to refresh once and let's see we've already got the update so previously on the computer when I did the build it took two refreshes but now that I've deployed to versel and we did an on-demand revalidation request that triggered the revalidation so then when we reloaded here it just took one reload and we have our new post for Saturday and we're seeing all of those updates here on the page as well so next JS 13.4 was just released here two days ago as I have been making this project video and it made that just a little bit more challenging but what I really want to highlight is the docs have been updated too and there's more things to learn about nexjs I'm going to post more things to my channel but it's hard to do these things as they're changing underneath your feet as you create a tutorial so this has definitely been a challenging series that started with next JS 13.1 about 12 weeks ago as I began the series and here we've finished with next JS 13.4 so there's always something new to learn just keep checking back to my channel and the playlist a couple of things I want to highlight here and one of those is the revalidate the on-demand revalidation so we can just search for that here in their new search entry and we have on-demand revalidation we used revalidate path but you can also use revalidate tag and they give an example of that as well and then something else that just came out in this new version is server actions and I really didn't get a chance to add those to this series and it didn't take me to the server actions page let me try that again here here's like server mutations so we previously covered mutations in another way and I think some of those things have been changed or at least we could use server actions to get involved with mutations so we'll see what all of that is about I don't really know yet as I haven't had a chance to explore those but more information coming from next JS and versel and of course you'll find more information on my channel in my next JS playlist as I continue to add to it remember to keep striving looking for Progress over Perfection and a little progress every day will go a very long way please give this video a like if it's helped you and thank you for watching and subscribing you're helping my channel grow have a great day and let's write more code together very soon
Info
Channel: Dave Gray
Views: 94,462
Rating: undefined out of 5
Keywords: Next.js Full Course for Beginners, next.js tutorial for beginners, next.js full tutorial for beginners, next.js for beginners, next full course, next full tutorial, next for beginners, nextjs full course, nextjs full tutorial, nextjs for beginners, next.js 13, nextjs 13, next tutorial, next.js tutorial, nextjs tutorial, next course, next.js course, nextjs course, next, next.js, nextjs, js, next js tutorial, next js, next 13, next.js 13 tutorial, next 13 tutorial, Next js app
Id: 843nec-IvW0
Channel Id: undefined
Length: 423min 58sec (25438 seconds)
Published: Fri May 19 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.