The Most Efficient Next.JS 13.4 Beginner Tutorial (TypeScript)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone welcome to my updated next.js 13 course where we will learn how to use the latest version of next.js with the new app directory and with react server components in case you don't know nexjs is a react framework which means that it makes react a bit easier to use for us and it also adds its own features on top of react which just makes it easier to build full production ready web apps that actually do everything you need as you can see on the next JS showcase page next to S is actually used by big companies so this is not just a Toya framework this is the most popular react framework right now and you can build real production websites with it now you might be wondering why do we need a framework on top of react isn't react already a framework why do we need next.js now in the past this distinction was very clear because classic react apps could only render client-side using JavaScript which means that in a traditional react app we would get an emptier HTML page back from the server where there is no data on the page yet then we would use JavaScript to fetch data from the browser basically on some back end and then after it is finished display it in the UI this made development easier for a lot of people compared to the server side Solutions we had before but client-side rendering also has some downsides for example JavaScript is necessary in order to render these Pages which means that if someone has JavaScript disabled in their browser a classic react app just didn't work they would just see a message instead that says JavaScript is required to view this website but client-side rendering also has some other downsides for example it's not so great for a search engine optimization because when a search crawler like Google Bots for example that crawl websites to index them in Google search when they crawl your react website some of these crawlers actually can't execute JavaScript so idz is this MD page and they don't have anything to index now Google's crawlers can actually execute JavaScript so a classic react app can also be indexed by Google but as far as I know it's not as optimal as if you would get back all the data from the server already instead of this empty HTML page but then next.js came along and they added some functions to react that we could use to fetch data on the server and return ready HTML pages to the client and we also could decide if we fetch the data when the website is accessed in this right moment which means that there is some loading delay or we could also fetch the data when we compile the project cache this HTML page with the data already inside it and then just serve this to the user when in this page is exist this means that every user would always get the same page until we compile the project again but of course this also meant that opening this page was extremely fast like almost instant because next.js also implements some prefetching strategies and so on so overall nextges really allowed us to build search engine optimized web pages that are super fast now the playing field changed a bit because react now has so-called server components which again are a way to render react components on the server fetch data on the server and just serve some kind of HTML to the user when they access the page so this is basically the same that nextjs has done before with their special functions that we could use but they do all of this in a bit more optimized way if we use react server components we don't have to pass any JavaScript to the client if we use a heavy npm package in a server component for example and this npm package will never reach the client it will just be executed on the server to do whatever we need to do with it for example renders are markdown and then again the ready HTML page will be sent to the client now technically it's not HTML it's some special format they invented but conceptually it works like this the difference is now also that we don't have to decide on a page level if we want to fetch data on the server or not in xjs before we had to decide it for one page at a time now we can decide it at a component level so we can have server components in these server components can be client components those are basically classic react components that are rendered on the client with JavaScript but in these client components can be server components again so this is much more modular now which means that we can optimize our websites further so now the question is what is the role of next JS now that react has these server components natively where the role of these Frameworks is now to a basically wire everything together because setting up a project that supports server components by hand is difficult next.js provides all of this out of the box for you and they also add their own features on top for example nextgf provides the owner routing system out of the box so we can create different subpages on our website just by creating folders in which we put files with special file names but you will see all of this throughout this tutorial next.js also adds stuff like image optimization so it can automatically resize images for you which is also important for website performance and SEO they actually improve server side rendering so on top of react server components we get some improved Behavior here and you can actually build your whole back end in xgs as well because they provide API route handlers which only run on the server and to This Server you can make HTTP requests just like twin Express or some other kind of backend server especially for small apps these API rods are very useful because then you have a full stack website and can make database requests and everything without having to set up a separate backend server you have all of this in one project for bigger projects you often still need a separate backend server like an espresso but this is no problem either you can also use nextgs with a separate backend but it's definitely a nice to have feature okay so next JS makes all of this react setup much easier for us in fact in the react documentation they actually recommend to use a framework because otherwise you will hate your life trying to set this up yourself and xjs in my opinion is the best one the company that maintains next.js is called bezel and they are also hosting provider and their web hosting is of course optimized for next.js which means that you can just connect your GitHub account to Brazil you click some buttons and your project is deployed super easy and all of this server component stuff and API routes all just works but if you are completely newer to react then there is nothing wrong with learning classic react first where everything is rendered to client-side and in fact I think it's a good idea because trying to learn one of these Frameworks right away is probably too overwhelming because you have the complexity of react which is fun but not easy and then you have these additional features on top so if you have never worked with react before then I recommend that you learn vanilla react first for this you can watch my immune beginner course here on YouTube where you learn react with an Express backend but it's enough if you just watch the first I don't know few hours of the course where we learn the react part and then if you feel like you understand the basics of react then you can come back to this tutorial video where we learn how to get to the next level with next.js OK let's take a look at the project we will be building here so we will not build the most fancy website because the point of this tutorial is to teach you all the important xjs app router features in the most efficient way I want to make more fancy project tutorials in the future so make sure to subscribe to the channel if you want to see this but this project here is rather simple I really distilled it down to the most important things and we will not only learn about the Nexus 13 app directory features I will also compare these features to the old Pages directory which means that if you have used the quote-unquote old approach and xjs before then you will understand how these approaches map to each other and how you can convert your existing nexjs project to the new app router so on this website we have different pages and each page will teach you a different caching strategy in next.js because caching is what it's all about caching decides when they the data for a page is fetched when we access the page or only when we build a project or at a certain time interval we can configure all of this in next.js now this image is a bit big because I set the screen to a bigger size you can see everything properly this is the actual size of the web page but this doesn't matter I will keep it like this now here comes the interesting part the end point where we get this image from from the unsplash API returns a random image every time we make a request to this endpoint so normally when we refresh the page we should get a newer image back but since I set static caching for this page this data is only fetched at compile time which means that when we refresh the page we actually see the same image again we see the same image until we built the project in our IDE again so now I went ahead and compiled the project again I'm gonna start it again then when we refreshed to pay a true busier a different image because again this is fetched at build time and then cached it takes a moment to load the image probably because we are in a Freer unsplashed account so I guess it's a bit slower but there is our image and if we refresh the page we get the same image again whatever this person here in this photo is doing I don't know but this is not how I tie my shoelaces anyway the opposite of the static caching is this Dynamic page here this page is not statically cached instead we make the request to the exact same endpoint as on the static page just that here we do it each time this page is accessed so if I refresh this page I get a newer picture back from unsplash the code and the markup for these two pages is almost exactly the same just the caching behavior is a bit different and you will learn all of this in just a moment and all of this was possible before the app router in the older versions of nexjs but now it all works a bit differently but there's also a middle way between static and dynamic rendering which is called incremental aesthetic regeneration or short ISR with ISR we can zoom okay fetch and cache the image aesthetically just like on the static page but we validate it in a certain time interval here I have set the time interval to 15 seconds which means that for a duration of 15 seconds we will get the same image back just like on the static page and every user gets this image back but once a user opens this website after this time window is over next.js will go ahead and render this page again with new data so this is a middle way between the static and the dynamic rendering so now since more than 15 seconds or over if I refresh the page we should see a new image but for the duration of 15 seconds when I refresh the page again we see the same image until another 15 seconds have passed then when we refresh the page it will trigger a newer re-render so we have to refresh it twice after 15 seconds the first refresh will show the old image and Trigger the re-render and the second refresh will then show the actual new page so 15 seconds should be over by now and there's the new image and again for 15 seconds we see the same image this is a really useful feature because this way you can serve static pages to your users which are just where we are fast to load because you don't have to make a request to the back end every time this page is opened but you also get relatively up-to-date data depending on how big you set this time window here for some pages it's enough if they are refreshed every hour also for some maybe every 5 minutes depends on what you need and these Dynamic Pages load just as fast as the static Pages because they don't need to fetch anything when the page is opened whereas the dynamic page took a moment before the request to the unsplash API was finished we will also learn about Dynamic roads which allow us to put something in the URL that can change so here we are showing Fitness images and this page is also statically rendered and cached this is why it opens so fast but this part of the URL is actually Dynamic meaning that we can replace this for any word like I don't know Sunny for example then when we open this page it will behave like the dynamic page it will fetch the data from the unsplash API generate this page and then cache it so if I refresh this page again we should see the same data and then we also have the search page which uses good old client-side fetching just like in a vanilla react app so of course even in xjs we don't have to use server-side fetching we can also fetch data client-side with effects and state this requires JavaScript to be executed but this is useful whenever you need some sort of interactivity for example here I can type in docs for example it will show this progress spinner fetch some images from the back end and show them in the UI so we learn how all of this works and we also learn about other features that are important in nextges 13. for example how to set the metadata for each page for example the title you can see at the top this works a bit differently now as well compared to the old Pages directory we also learn how to use the next image component which as I touched on before automatically resizes images so the image we get back from the unsplash API is actually a lot bigger than this but if we open this image in a new tab we can see that it has the perfect size for how we display it here it's just slightly bigger but it's much smaller than the image we get back from the API and we can also see that we have this special underscore next image URL where we load this image from this is because again nextgs resizes these images automatically for us which just makes them faster to load so this is a very useful feature that next to us prints out of the box we will also set up an API endpoint so one of these back-end routes so you will learn how this works as well and at the end we will even deploy everything to Brazil and Brazil even gives you a URL for free so you will be able to reach your website over the internet not just on localhost and of course we will write all of this in typescript because vanilla JavaScript is for lunatics okay so again if you don't have any react experience yet you should watch my moon beginner course first at least the react part there is no next year as pre-knowledge required to follow along so if you are complete next JS nope this is fine I will teach you everything before we start make sure to subscribe to the channel because I want to make many more tutorials like this with more advanced projects using next.js and react and maybe some other Frameworks in the future and I also want to give a shout out to my paid course because I actually have a paid next JS course where we build a bigger project with more advanced features and there we actually built a whole separate Express back end and we really make it production ready with everything that is required and redeploy everything and when I recorded the course about one or two months ago I used the Pages directory in next.js but I'm currently working on an update where we migrate all of this to the new app directory and this is especially useful because there you learn how to use the old approach and then how to refactor it to the new approach and you can see how all of this relates to each other I think knowing the old approach with the Pages directory is still useful because the newer app router still has some bugs actually and there are a lot of issues on GitHub and I personally have already filed a lot of bug reports so the old Pages approach will still be used in companies probably for years and next year as they already confirmed that the pages router will be supported for many more major versions of nexjs so many more years to come so again I think it's useful to learn both approaches which we do in my paid next.js course you can find the link under coding and flow.com nextjs I will also put it in the video description below and in this tutorial here we will completely focus on the newer app router approach alright then I wish you a lot of fun with this course in order to work with next.js we need node.js installed on our machine if you have worked with react before then you probably already have node installed we can check this by typing in node minus View and it shows version 18.15 for me if it doesn't show anything for you go to a nodejs.org install the latest ATS version just follow the installation instructions then type this command again and then you should see something here then creating the actual next.js app is very easy because nextgf provides this create next app command that we can use which sets up a new index.js project with everything already wired together so we can execute this with node with this command here gonna copy this into the command line you can type this out by hand if you want then we press enter and now the setup will ask us some questions now if you watch this tutorial in the future then some things might change for example packages that we use get new versions and sometimes this breaks things so what I will do is I will also put a link to the starting code of the project I'm using here with all the dependencies already installed and the project already set up into the video description below it's a GitHub link for the starting code if you watch this tutorial in the future and things stopped working instead of setting up the project manually like we do here you can download the starting code and use this one instead but if you are brave enough you can also set up a completely new project this is what we are going to do now so it asks us for a name for our project you can call this whatever you want I'm gonna call this next Js 13.4 image gallery 13.4 is the version of next.js we are using in this tutorial we press enter then it asks us if we want to use typescript we select yes with the arrow keys and press enter again eslint as well this just helps us find mistakes in our code we will not use Tailwind CSS here we will use bootstrap instead now I know that bootstrap has fallen out of favor a bit and tell when CSS is more modern but it's just easier to set up a quick small project with bootstrap instead of having to write either CSS ourselves but this is not the only reason I pick bootstrap here these component libraries like bootstrap also need some special handling now with react server components and I want to show you how this works so for Taiwan CSS we select no and again all of this is already set up in the starting point project which you can find in the video description below the source directory is optional it just puts all your source code into this folder I like this for organizations so I select yes here as well I accidentally pressed enter two times so the next question here is if we want to use the app router we select yes because this is the new approach right the old one was the Pages directory but this tutorial uses the app router would you like to customize the default import Alias no and this should be the last question now we have to wait a moment and this sets up our new nexjs project when this is finished we can close the command line and open the folder where we set up this project here it is and then we can right click and open in code if you don't have this option available you can also just open vs code and drag and drop the folder in there or just click on open inside vs code and open this folder here okay so and this create next app command set up this project with a lot of files already inside it we have the typescript configuration because we selected typescript in the setup we have of course a package.json with the dependencies and some scripts we have a next configuration we have a git ignore in case we want to push this project to GitHub and we have the srz folder which contains the actual files that make up our website before we run this project I want to install the bootstrap dependencies that we will use soon so we open the terminal which you can do with this command new terminal and then we type in and again this is only necessary if you are not using the starting point project from GitHub that I provided only if you followed the manual setup in the starting code the dependencies are already installed we type in npmi short for install bootstrap space and react bootstrap this is actually the only dependency we have to install this is the only thing we will use in this project beyond the ones that already come with a newer nexjs project okay and then we can actually run this project in development mode which we do with npm run Dev like this and this is a script that is set up by default in the package.json it executes this next Dev command which again runs this next.js website in development mode so as you can see this by default runs on localhost 3000 so you can open a browser window and just go to localhost 3000 and you see this yeah boilerplate page that is set up by default of course we will get rid of this page eventually and set up our own pages so that's what we will do in the next section okay and the front page we can see here on localhost 3000 is coming from this page.tsx file this is where all the jsx code for this front page layout here is in and this page TSX is inside sr0 and then in the app folder and the app folder is where we put all the code for our pages in the newer next.js app router before we have the pages folder now we have this app folder in the pages folder this file was called index.tsx now it's called page.tsx so they are equivalent and whenever we want to create a page that we show on our website we have to create such a page.tsx file and we will create more of these pages in a bit next to the page we have this CSS module which contains CSS yeah just for the front page in case you haven't used CSS modules before they are basically a way to scope CSS just to a specific file so here we import page.module.css and this way the CSS classes will set up here are only in effect on this one component this is just a nice way of organizing CSS because this way we don't have to set up a bunch of global classes that can interfere with each other instead the main class here for example will only be applied on this page and we can have a separate main CSS class on another page later now the big difference to the old Pages directory is that we can now put these files like CSS files and other files directly into our app router next to our pages in The Old Pages directory and xjs this was not possible that we had to put these files outside of the pages folder into a separate folder so now we can co-locate these files which is really nice for organization then another important file is this layout TSX file and again the name of this file Metals if you change the name of page TSX or layout DSX this will stop working this layout wraps our whole application so the home page TSX file is actually rendered right here as the children inside the body tag if we navigate to a different page later it will also be rendered in here so the layout is where we can put enough bar for example that should be shared between other separate pages of this app so if we have used the Pages directory in next.js before then this is the equivalent of the underscore app and underscore document file they now merge into a one layout file and you can actually create nested layouts as well so again this layout here is applies to the whole app but you can also have sub layouts only on certain routes that should share some similar elements like a sidebar for example but this is more advanced for simple apps is usually enough to have a single layout in the app folder that wraps the whole application and again later in here we will put the navbar from pages and layouts we can export this const metadata and again the spelling is important it has to be spelled exactly like this in our lowercase yeah in this way we can Define the metadata of a web page for example the title is what's shown up here in the tab and the description will be shown for example when we paste the link to our website on social media later like Twitter or Facebook so let's actually change this and I'm gonna use double quotes but this is just personal preference I set the title to a next.js 13.4 image gallery and as soon as I saved this we can see the change here in the tab now the title has changed again we can set a different title for different subpages of our app we will do this later and since we set this title in our layouts that wraps the whole application this will basically be used as the fallback so whenever we don't set a more granular title on a specific page this one here will be used so this is the global Title so to speak I'm also gonna change the description tool tutorial project buyer coding and floor we can't see the description here because it's not shown in the browser but again this is shown for example on social media when you paste the link to your website we also have this Global CSS file which is imported here so earlier I explained how a CSS modules work but we can still use Global CSS as well so whatever we put in here will be applied to all pages throughout our home page and to set up our own route we have to create another page.tsx file but we already have one at the root folder right which points to the root URL which is localhost 3000 let's say we want to create a page under localhost 3000 slash hello for this we have to create a new folder in the app directory with the relative URL in this case hello this is just an example and then in here we put a page.tsx again it has to be called page.tsx because this tells next.js okay whatever we put in here should be rendered under this URL so now here we can export a component which we do with export default function the name of the component is up to you you can call this page you can call this hello page whatever you want and in here we will simply return a div that says hello nextges 13 Maybe we save this and then we can navigate to localhost 3000 slash hello and there's our page doesn't look beautiful yet but now we know how we can set up pages in our next js13 app so again the naming of the page TSX file is important and it's the equivalent of the index.tsx file in the old Pages directory now it's called the page.tsx in the old Pages router the file name could be part of the URL so we could name this Bazinga for example and we would reach our page under slash hello now in the app router this is not the case anymore now we always have to name this page.tsx there is no other name possible and the URL structure is completely defined by the folders where we put this page.tsx file in if we wanted to have our page available under slash hello then we have to create another folder called balzynga inside the hello folder this is how your creative nested URL routes now in the layout which remember wraps the whole application by default you have this Frontier setup this is a Google font and xjs comes with these Google phones out of the box which are then stored on your server which by the way is also great for privacy because then we don't have to fetch these phones from Google they are coming from our own server you can also try out different fonts all these Google fonts are available here by default we will stick to enter and it's applied down here in the body and the body wraps all our pages so if we remove this class name the font should change on our hello page to this very hideous font but also on the front page if we refresh this because again this is applied to the whole app but this looks terrible so let's add this in the front back and again any element that we want to share throughout our whole app on all pages we can also put into this layout so let's reformat the code and for now let's put a div in here later we will replace this for an actual navbar but for now I just put some text here this div is shared across layouts now when I save this we should see the stiff here okay it's hidden by this top section so let's remove this quickly in the home page.tsx file so this one right here in the app folder not the hello one and if we remove this part here and save this yeah we see our shared div when we navigate to slash hello we'll see this div as well because this is inside our app layout okay so layout.tsx and page.tsx are special files in xjs because just by giving them these names they fulfill a certain purpose and there are more of these special fights in next.js that all play a certain role in our router for example if we try to go to a page that doesn't exist like hell for example we get to this generic 404 page this is set up in next.js by default but this is not great because our shares diff is not here and in fact nothing in our app layout is here so even if our app has a nice background color for example and branding none of this will be shown here we get this very blend white 404 page so it's a good idea to replace this for our own 404 page and we can do this again by creating a file directly inside our app folder here it has to be placed here and it has to have this execut name not minus found.tsx this automatically turns this into the 404 not found page this is why when I create this file the screen here becomes empty because right now we are not exporting anything from this file yet so let's export a simple page here again export default function gonna colored not found again the name is up to you and here we want to return some layout again we will keep it simple but you can make this more sophisticated in your own project here I'll put a div in the stiff I put an H1 headline which was a not found and maybe some text below sorry this page does not exist and when we save this we should see this here let's refresh the page and there it is again it's not beautiful but it works just like me but now the difference is we have our quote-unquote branding because we have our own background color and we even see our shared stiff which means that if we have enough bar in our app layout this navbar will still be visible even on the not front page the next special file that we can set up is the loading page for when one of these Pages here takes a while to load we will see this loading page instead again we have to put this into the app folder but again you can create more granular loading Pages inside your different routes so we could also put a loading page into hello which will only be used when we navigate between any roads inside the hello folder usually you want to have at least one Global loading page right in the app folder because this by default will be used for all pages again the naming is important it has to be called loading.tsx or jsx if you use JavaScript by the name of the file must not be different let's set up a very simple layout here again export default function and here we will return just a div for now that says loading and I forget the function name again this is up to you I'm gonna cut this loading now the loading page will only show up if there is actually some delayer in the page we are trying to open so let's go into our hello page once again and now we do something in mind blowing if you come from vanilla react we turn this function into an async function and then in here I will put an artificial delayer which we can do with a weight new promise this is just a little trick to insert an artificial delayer just type out exactly what I am typing here resolve and we create an error function and call set timeout to which repairs resolve entity layer for example one second so again this just creates a promise which waits for one second and we await this right in here so we only get to this part after this one second is over this is just a delay and now when we save this and open the hello page again we should see the loading page for one second as you can see here the text says loading and then it's replaced for the actual page and the reason why we can just make this component in async function is because by default in the next js13 app router all components are server components by default meaning that whatever code we put in here will only be executed on the server this will never reach the client meaning that we can await async code in here we can even make API calls and put sensitive data and credentials in here instead the client only gets back this part here basically the rendered HTML with the data already inside it if we need interactivities with States or effects and react or click handlers for example that should do something when we click a button or apis that are only available in the browser like the local storage for example then we have to make this a client component instead of a server component and if you try to do this wrong you will just get an error so for example let's put a user effect in here which we normally have available in reacts right just put the use effect in here with an empty block save this then we get an error you are importing a component that needs use effect it only works in a client component blah blah blah and in order to turn such a server component into a client component we have to go all the way to the top above the import statements it has to be at the start of the file and here we are just add a string which says use client this turns this into a client component now we still get an error because now this can't be an async function anymore it's just a normal client component but now we can use user effect in here and when we make a component a client component all components that we use inside these components are also considered client components meaning that you don't always have to put this us client string here which is also called a directive into every single client component it's enough if you pull it in the topmost client component and again all components that we use in here are client components as well so if we would render a bunch of I don't know a block posts for example and we have a blog post card component then this blog postcard components would also be a considered client components if we use them in here if we use them inside the server component they would be server components unless we produce client directly into this block postcard component as well so this always trickles down to the components we use in here there is one exception for that which we will learn about in a moment where we can put server components into client components but generally it's a good idea to try to move the source client as slow as possible only use it where you actually need it because server components are just more efficient and you should use them until you actually need a client component which again is the case if you need state or effects or a custom hooks that use any of these hooks or browser apis like local storage so since we don't actually need the use effect and here I'm going to revert this to a server component and there's one more special file we can set up again we do this in the app folder here this one is called error.tsx and this will be shown for any unexpected error that happens inside our components and the error page has to be a client component I'm not sure why I just know that it has to be one so we put the use Clan directive all the way at the top and then we export the page here as well export default function we don't need to do anything asynchronous and we couldn't because this is not a server component and again we return a symbol UI here a div with an H1 which is a error and I also put this Emoji here of course you can set this up however you want again I put some text in here something went wrong let's save this and to try this out let's throw an error in our hello page here at the top or maybe below the weight so we still have our loading page throw around bazinga let's save this and then we get to our error page this is what the user will also see in production they won't see this part here this is just for development to show us where the error originates from and the error page can actually accept some arguments and since this is typescript we first have to define a type for these arguments we do this by creating an interface I'm going to colored error page props but this name again is up to you and the error page can take the errors input so we can do whatever we want with it read some data out of it and lock it for example and it can also take this reset function when we call reset it attempts to re-render the page and maybe then the error is gone so now we can pass these arguments to the page we set the type to error page props and now in here we have the error and the reset function and now for example we can put the button in here again a button requires the component to be a client component otherwise clicks wouldn't work but again the error page has to be a client component this is why we have to use client directive at the top and here we use bootstrap button you can also use a normal button that's up to you when we click this button we will color this reset function up here and by the way this has to be named reset because this is passed To Us by next.js and let's say the text of the button to try again and then we get this button here okay The Styling isn't the place yet because we haven't added the bootstrap CSS yet we do this in the layout file because again this should be applied to our whole app and we put this above the globals.css so that this CSS here is executed first and whatever we put in here overwrites the bootstrap CSS so you can pause the video and type this out by hand and in case you're wondering where I got this from this is coming from the react bootstrap documentation here are the installation instructions in this CSS we have to copy but it's probably faster if you just type this out by hand or copy it from the GitHub repository that I Linked In the video description below then Reserve this and The Styling should be applied to this button after refreshing the page looks a bit better so now when we click this button it attempts to re-render the page but we are still throwing the same error so nothing actually happens but it's the nice to have and if we remove the error from our hello page of course the page here will render again might have to refresh it so those are the so-called special files in nexjs 13 because they all have a very specific name that gives them a certain functionality and again you can also create more granular versions of these different special files you can create the loading TSX just for the hello routes for example or a separate layout or you can also have a different error page in the hello routes but usually you want at least one of them in the global app folder okay one of the reasons I use bootstrap in this project is because bootstrap and also some other component libraries need some special setup in xjs 13 in the app router because they are not yet adapted to This Server component approach to see the problem let's go to the layout and I want a render all pages into a bootstrap container so I'm going to delete the stuff here we don't need it anymore and instead I wanna import this bootstrap container here and I want to wrap all our Pages the bootstrap container adds some padding and moves the content more towards the center of the screen instead of the edges here it just looks better but if we saved this we will get an error we get the same error as we did earlier when we try to use use effect and a server component because these bootstrap components like container use client component features internally so use state in this case again other react component libraries probably have the same problem because they usually have interactivity they can usually be a clicked in some way or react to some user input the problem is that these components are missing the US client directive inside their source code so they haven't been adapted to react server components yet and we can't use client-side features without declaring the US client directive at the top of the file now we could theoretically make the whole app layout a client component so that we can use client features in here but of course this wouldn't be great because again server components are more efficient and we want to use them whenever possible but there is a simple way of making this third-party components client components even if they themselves don't have to use clients directive set inside them for this we create a new file this time we don't put it in the app folder we put it in the srz folder entry colored components and in here we can put all kinds of components that we share between different pages whereas components that only belong to a specific page we can also co-locate directly with the page where we need it in the components folder we create a file which I'm gonna call bootstrap.tsx but you can give this file any name you want we make this file a client component with the US clients directive and then we can simply a export different components from bootstrap that we want to turn into client components so we export then we add this destructuring syntax here from react bootstrap or whatever component Library you use and in here we can add the components that we want to use in our app so this is our container that we just set up but we are going to need a few more gonna add them right away we also want this SSR provider which is necessary for server-side rendering I also want to use the alert component later and the spinner for the loading page so this way we re-export these bootstrap components from our own client component and now we can use them like client components so we close this file go back to our layout and we change the import here from react bootstrap to add which is the root directory as auxia slash components right and in here should be the bootstrap file that we just set up and when we save this and refresh the page depending of the container is applied and now it works because this container is now a client component now earlier I explained that everything we put inside the client component is also a client component so does this mean that every page is now a client component because we are put it into the Container client component well if this was the case we wouldn't be able to open our hello page anymore right because in the hello page we use a server component so wire does this work why is Hello still a server component even though we wrap it into the Container this is because our hello page is not coded directly into the Container component instead repairs it as a prop we pass it as such a children prop which is the special react syntax that you can see right here when you declare such a children prop in a component you can pass another component between the opening and the closing tag like it is the case for the container here when we do it like this then we can pass server components to a client components so the container is a client component but our Pages can still be server components this is possible because when we pass the component as a prop react doesn't have to know in advance what the content of this page is instead it just has to reserve a slot in the wrapper component so there is an empty spot an empty hole so to speak in the container component where we later put our rendered server component in but if we would hard code our hello page directly into the code of the container component then it would have to be a client component this might be confusing at first but it's an important concept because this way we can have client component Rebels where we still have our efficient asynchronous server components inside and it's especially important here in the root layout because here we usually have different kind of wrappers like our container or a context provider and we still want to be able to render server components inside our layout and this is possible by passing the server components as children props okay let's finish setting up this layout here outside of the container I also want to use the SSR provider which again we import from our own components folder the bootstrap file that we just set up not from react bootstrap directly because again the wouldn't work we wrap the container with this SSR provider this is just necessary by react bootstrap whenever we use server side rendering otherwise there will be some inconsistencies with the ideas this is explained in the react bootstrap documentation we just wrap our whole layout with it and then we can forget about it what I also usually do is I wrap the whole container into an HTML main tag because the part in here is usually the main part of the page and our enough bar later we will put above the main tag lastly I want to put some padding on the container some additional padding we can do this with bootstrap utility classes which we can add with this class name prop we set this to a p y minus 4 which adds some vertical margin this is what the Y is for it's top and bottom now you can see there is some space to the top of the page okay let's also make the whole home page emptier remove all the spoilerplate that we get with a new index.js project as you can see there's a main tag in here but we now have our main tag here so we get rid of everything inside the return statement and instead for now we will just add a diff here that says home page we will later replace this we can also get rid of these import statements and again this is a server component by default because we are not using any client features here so and now the home page looks like this entry can also delete this whole CSS module here because we don't need any special styling on the home page so let's just delete this then I want to go to the globals.css file where again we have a lot of default boilerplate already set up we don't need most of this so we delete the max width and Border radius CSS variables in here we can keep the font and these colors we don't need a primary color I mean you can leave it in here if you want but we don't need it so we might as well delete it we can remove this whole media block here we can remove overflow hidden I think this caused some problems when you make the bootstrap nav pass the gear instead we add the Min height of 100 VH which stands for viewport height so this is the height of the screen and this way we have this gradient stretched over the whole height of the page which looks better then we can also remove this color inherit from the links so they get their normal color back we remove this last media block and instead I wanna add a block that targets all images here I want to set a background color to light blue so later when we load an image we have this light blue background so we can use it as a kind of Blaze holder okay let's save this and one more thing I want to go into our loading TSX file again where right now we just have this loading text and instead of this I want to return a bootstrap spinner again it's important that we import the one from our components folder this way we don't have to make the loading page a client component okay so we import this from this folder it didn't add the import statement so I have to do this manually import spinner from add slash components slash with strap and we have to finish this we set the animation to border I also add some styling we had a class name again I use bootstrap utility classes with the block we can set the CSS display attribute to block and with M Auto we add some Auto margin then we close this and this dialing here just puts the spinner on the center of the page rather than all the way to the left let's try this out let's open hello again which has our artificial loading delay and there's our spinner which we see for one second just looks a bit better but you can also replace this for something else like a skeleton for example but this is totally up to you and in the next section we will set above enough bar and we will learn about next links and the newer next router hook and then after that we will start creating our pages with the different caching strategies okay let's set up enough bar that we can put into our root layout so we could put a snuffbar component into the components folder but since we only use it in the root layout I think it makes sense to co-locate it with the layout TSX file in the app folder so we right click on app create a new file foreign the name is up to you but you should not name it NAFTA with a lowercase Bill why because the bootstrap navbar already has the name with the lowercase b and we will use the bootstrap navbar inside here and then we have a naming Clash this is why I give this an uppercase B okay in here we will later use a hook and the hook is a client-side feature so we make this whole enough bar a client component with the use client directive but this also makes sense because the bootstrap navbar is a client component anywhere and since we don't put any other elements in here we can just make the whole file a client component there is no server part to be rendered in here if you don't use bootstrap or don't use any interactivity in here and no effects and States then you can also try to make this a server component which again makes this component just a bit more efficient but the client component is also totally fine okay and here we export a default function with the same name entry when you return some UI element we want to return a bootstrap Nerf bone so again we type enough bar Auto Import doesn't work and the import has to be below the use client directive as I explained earlier so here we want to import the enough bar with a lowercase beer from we could import it from our components folder or from react bootstrap because we are in a client component anywhere so we can import the bootstrap Naval directly even though it doesn't contain this use client directive but again whatever we hard code into a client component is automatically considered a client component as well this is why we can just use the bootstrap navbar in here directly okay so let's set this up I want to set the background to primary which by default gives it a blue color you will see this in a moment we set the variant to dark so that the text has a light color with that sticky to top but this is all optional VZ expand to SM this makes the snuff bar responsive so when the screen gets small it automatically turns into a hamburger menu that you can click this is why I like bootstrap because it does all of this for you out of the box and collapse on select mixer navbar collapse when we click an item if it's not expanded already okay we close this tag let's make this big in the nav bar we put a container again I want to use it directly from react bootstrap just for consistency and again let's add some spacing to the elements inside the navbar then in here we put enough bar again with a lowercase b dot brand which can add some icon or text to the left side of the nav bar which you can see on almost any website on the internet and this usually brings you back to the home page so we can make this a link with the href attribute and we want this to a link us to the home page so we just add slash entry could add an image here but I haven't prepared one so I will just set this to a text next you add 13.4 image gallery let's save this and put it into our layout already we put it above the main tag because this is not the main content of the page it's shared between all pages entry import our navbar with the uppercase beer important not the bootstrap Nerf Bar and we close this and then we see our enough bar here and this is the link that brings us back to the home page let's also add the link to the hello page So Below the navbar brand first of all we put enough bar dot toggle which adds this responsive hamburger menu that I was talking about then we set this area controls attribute which defines what this is connected to here we have to pass an ID which is up to us I'm going to set this to a main love bar then we close this with a slash and a closing angle bracket then down below we put enough bar dot collabs yeah which makes all the elements inside it collapsible and reset the idea to the same one we set up here in area controls so again this is Main navbar and now whatever we put inside navbar collapse will be responsive and on smaller screens it automatically turns into this hamburger drop down menu now in here we put the snuff component not enough bar but just enough and again we have to import this from react bootstrap we close this and then finally in here we put enough link that brings us to the hello page so again opening angle bracket enough dot link we set the edge ref just like for the brand item this time to slash hello because this is where we want to navigate to when we click this link we close this and reset the text to hello so now when we click this drop down menu we have our hello page to which we can navigate and when we make this bigger the navbar expands and we see the menu item right here so this is a responsive navbar but the behavior of this links here isn't great yet because these behave like normal htmlings like normal ankle tags meaning that when we click on the link the page heart reloads we can see it here from the top in the browser that we get is a loading indicator and trendy navigates to the hello page we see the loading spinner again this is not how we should navigate within a next JS app because this way we lose all the state in our react components and if we fetch the user that's logged in for example then we would also lose the stairs and we have to refetch it again this is just very inefficient it also makes the navigation look very flickery because whenever we click a link we have this hard refresh and sometimes the page even flickers we also lose any caching that's stored inside the router because next.js sometimes optimizes the navigation by caching pages that we already navigated to or even prefetching links that appear on the screen so instead we have a special link class in xjs that we should use for navigation so now what we could try is we could go in here we could remove the href attribute and wrap this text into this link component which we export from next slash link this is the link we want to use we give this the same href attribute that brings us to the front page and we wrap this text inside it so when we save this we can see that the styling of the brand text disappears but at least the behavior will be better now so now when I click the front page we don't get this hot refresh instead we navigate pretty much instantly and we don't lose any state in our components just that the styling here is now off now of course we could fix this with CSS but bootstrap actually has an easier way to handle this so instead of nesting the link here inside the navbar brand we can add the S attribute to the navbar brand this way we can tell bootstrap to use a different kind of component here but render and style it like an offer brand and in here again we pass the link now this whole enough bar brand turns into such a next link so we can remove these inner link tags and just again add the href attribute here now we have the best of both worlds now we have the styling of the navbar brand but it behaves like a next link so this is a special bootstrap prop but I know that other component libraries have similar props available that let you render different kinds of components entry can do the same down here for the nuff link again we pass the S prop with 1s and pass the link as well and now we have this proper navigation through next links within our app much better one more thing I want to improve I want to highlight whatever menu item we are currently on so now the hello page is highlighted even though we are not on the Hello page because we clicked this earlier we can fix this on the nuff link opening tag with this active prop when this evaluates to draw the hello link will be highlighted and render we want this to be highlighted where we want the hello link to be highlighted whenever we are on slash hello right so we have to get the current path we are on the current URL inside this component in the old Pages directory we did this over the next router that we could import with the use router hook the app directory also has a router that we can get refuse router but not from next slash router this one will not work in the app directory we have to import it from a different file but Auto Import didn't suggest it so I have to do this manually we have to import it not from next slash router but from next slash navigation this is the one that will work with the app router and here we can get the use router hook now again in the Pages directory we could now get the current path out of this router but if you add the dot here you can see that there is no such value or method here available anymore because now they have split up the router functionality into three different hooks we have used router which allows us to programmatically navigate between different pages with router.push and so on if we want to have the URL that we typed in we use a separate hook instead which is called use path name this is where we can get the current path from this is actually of type string so right now this is slash hello and as a third one of these hoax called us search params this way we can get the search programs out of the URL search params in case you don't know are these attributes that we can pass behind the question mark we only need the path name in this case so I'm gonna delete your search params and use router you can also remove this import here but we keep the path name because down here we want to check if path name which is this variable up here is equal to a string slash hello then we want to set this menu item to active and if not it will not be highlighted so right now we are on the Hello page so hello is highlighted and when we go to the home page hello is not highlighted anymore you don't have to add this the main purpose is that I wanted to show you these different router hooks that we have in the app directory now okay this one now we have the scaffold of our web page set up and in the next few sections we will focus on caching so how we can fetch data from the unsplash API and the different ways of caching them at compile time dynamically and so on okay so now it's time to learn about these different caching strategies in next.js and what is actually quite interesting is that by default in the zobo component if we are just write it like this without any special setup then this part here will be executed when we compile the project if we fetch any data here then it will be put into our layout and then next.js will automatically cache this generated layout on the server and we will serve the exact same page to the users until we compile the project again which then again executes the asynchronous part to see what I mean let's open the hello page again so we are still in development mode and whenever we refresh the page with Zia the loading spinner because we have this timeout here right but something different happens if we don't run the project in development mode but instead build the project which we can do with npm build that's actually npm run built then it does some stuff it optimizes our code for production and it generates static Pages for Server components like this one here this takes like 20 seconds or so 30 seconds maybe or longer depending on the size of your project and then when this is finished we type in npm starts to start this project but now we start as not in development mode but in production mode which behaves a bit differently again when we compiled the project our server component here was executed and then aesthetic HTML page was generated what does this mean it means that now when we refresh the page we don't see the loading spinner anymore instead we get the static page immediately so if we have used the Pages directory and next.js then this is the equivalent of get static props but instead of exporting get static props and fetching our data and here we do it directly inside the server component without any special configuration we just fetch our data data in here and return our layout and next.js automatically catches this page at the build time but now let's load some actual data so that we can see the effects of this better for this we will use the unsplash API here we can sign up and they have a free tier available which allows you to fetch 50 images power which is enough to play around with this so go to unsplash.com developers you have to create a free account here then you go to your apps then you set up an app I already have tundles and in here you get an access keyer which is down here of course you shouldn't share your access key with anyone I do this here because I will later delete this key anyway so it won't work anymore so we copy this access keyer go into our project and you usually don't want to hardcore these secrets into your code instead you want to put them into the environment variables because they are not pushed to GitHub by default this nth files like nf.local here are inside git ignore that we got when we set up a new next.js project Zoom here in the root folder so not even inside sr0 just outside of everything where also TS config and everything else is we create a file that we call Dot enf dot Locker now why do we use nf.local and not.nf in next.js you usually use the normal end file for some kind of common configuration and you put your secrets into the nth dot logo file this is why nf.local is in git ignore by default but the normal end file isn't but of course if you prefer a normal end file without the logo appended to it you can also set this up and add it to the get ignore but here we just use the nf.local file in here we add the key and splash underscore access underscore key you can give this any name you want but I'll uppercase with underscores is usually the naming convention and then we just paste our key here you can surround this with quotation marks but it's not necessary we can also just edit like this and then I want to fetch from this endpoint here where we can get a random image from somewhere at the top of the page we can also see the root URL where we have to make this request on this part here and then we want to call the random image end point gets a random photo so we add this to it the URL and down here we can see the data that we get back so this will be the structure of the Json response since we work with typescript we will create a type for this so that we can use these values in our app in a typesafe way but we won't need all of these values here because we will not show all of this information in our app what I want to have is I want to have the description of the image so we can show it in the UI I want to show the user that posted the image which is somewhere down here with a username and the URLs contain the actual image I think the raw one is enough because we will resize this image through next.js anyway and then also the width and height so we go into our project let's create a new folder inside sr0 which we call models and in here we add a new file which you can give any name you want I'm gonna call this unsplashimage.ts not TSX because this doesn't contain any HTML code this is just a typescript file and in here we export an interface that defines how this type will look like and we give it a name unsplash image so as I already said and here I want to put the description and these Keys we use here have to have the exact same name as the keys inside the return type otherwise our code would know which value belongs to which key right so the spelling has to be the same then we also want to get the user and for the user we have this nested object which contains for example the username and some other stuff inside it we only care about the username so we add a username string inside here then we want to get the image URLs which are contained inside the URLs object and as I mentioned before we want to get the raw image out of here and then lastly width which is a number and height which is a number as well and that's the type that we will use in our app and we will ignore these other values that are in here of course you can add them if you want to build a more sophisticated app and then we want to create a new page that behaves similar to our hello page it fetches the data at compile time and then it caches the static page until we compile the project again so I want to create a new route which points to not slash hello this time but slash static because this page shows static rendering but you don't have to call it steady you can give this page any name you want so and we already learned how we can set up these new URLs right we create additional folders inside the app folder so if we want to navigate with Slash static we create a folder that we call static and to return this into a page that we can actually open we have to put a page TSX file inside here the same as we did it for the hello page and in here as Joshua we export the default function again I'm gonna call this page you can also call this static page or whatever you want and in here we want to fetch data from unsplash right so again we can make this an async function because this by default only runs on the server then we create a constant response and we can just make a fetch request to a downsplash API you don't have to use fetch you can also use something like axials here that's up to you but fetch is the easiest one and the URL where we make this request too again is here in the documentation of the unsplash API so the root URL is this part so let's copy this into this string and the end point is at slash photos slash random and then we also have to pass our API key this is also described somewhere here in the documentation they tell us that we have to add the API here to the URL as a search program so we add a question mark then we write client underscore idea make sure the spelling is correct and then we want to append the API key that we have in the nth variables so we copy this name entry appended to the string with process.enth and the name of the API key right in the response will be the data of our random image so on the Json will contain this block of data for which we set up the unsplash image type in our interface earlier so to get this image out of here we create a const image equals await and by the way we also have to add the weight in front of fetch because this is an asynchronous operation we want to await response.json which passes this Json body out of the fetch response and this will be of Type unsplash image now the compiler doesn't know this so the type is set to any but you can set its hype ourselves to unsplash image which we import from the models folder and now we get some other completion when we use this image variable now you might be wondering wait but is it safe to use our unsplash access key here isn't this sensitive data yeah it is but as I explained the server component will only run on the server so this will never be visible on the client and there's actually an additional security measure for these environment variables in xjs even if we would use this environment variable directly on the client it would actually be undefined it will only have a value on the client if we prefix this with next underscore public underscore only this way we can make this variable visible on the client this is just another security measure so that we don't accidentally expose sensitive information but since this runs only on the server we don't have to add this prefix okay then let's set up the layout below in the return block so here I want a positive to which again I add a class name with some utility classes we make this a flex box with D minus Flex again this is coming from bootstrap we make it the flex column with this attribute and with a line item Center we can send everything horizontally on the screen and in here I want to put an image and the next JS we have this special next image that we should use instead of the normal HTML image the next image is what allows us to automatically resize images to a fixed size which is good because then the user doesn't have to load an unnecessarily a large image which of course takes longer to load but the next image also forces you to set a fixed width and height so it knows the dimensions of the image in advance because this way it avoids that the layout has to shift when the image pops into existence so for example let's say we have an image here but we don't know the size in advance the height for example and we have some text below then in a normal HTML image when the image has finished loading it will pop up and it will push all the elements below it down right but this is a bad user experience because it moves around elements on the screen it can happen that you try to click a button but then it moves to a different place and for this reason it's actually also bad for SEO so as far as I know Google really punishes this kind of behavior so yeah in the next image it forces you to define the width and height in advance so what we do is first of all we set the source of the image like we do it in a normal HTML image we get this from the image that we get back from unsplash in here we have the URLs that we have defined in the interface earlier and here we want to load the raw image then we have to define a width and height now since we don't know the dimensions of the image in advance some of them are vertical some are horizontal I want to calculators here so we'll just add some little code above you could also set the image to fixed dimensions and then use the object fit cover attribute in CSS to a send or corrupt the image so it's not distorted but here here I'm going to resize the image dynamically so we will just write a little bit of code here that calculates the width and height so we create a const width and I want to set the width of the image to always 500 pixels except when the width of the image itself is already smaller because then I don't want to stretch the image right so we can use math.min which is a normal JavaScript function that just Returns the smallest value of whatever values we pass in here so here we pass 500 and the width of the image we get back from the API so now if the image has a width of for example 600 pixels then we will get 500 back but if this is 400 pixels then we will get 400 back and then I want to calculate the height from this new width so that we keep the original aspect ratio so in parentheses we write width divided by image.width and then we are multiply this with image.heit then we get a new height that fits to this width okay and then we pass our new width down here and our new height and if we didn't pass a width or a height then we would actually get an error so we couldn't show this image on the screen we should also set an ALT prop this is why this is underlined lint is complaining this will be shown for screen readers for example which is useful for blind people or people who have bad sight so whenever possible you should pass an out prop with a description of the image and in the image response we actually have this description which we can use here now when we save this and we go to slash static we should actually see this on the screen if this worked properly we get to the not found page because we have built and started the project earlier which means that changes are not applied automatically so we stop the execution and we execute npm run Dev again to run this in development mode and then when we refresh the page we should see our image here not yet they are still an error invalid Source prop this is because we have to add these URLs where we want to load images from in our next configuration this is because again next.js automatically resizes these images and we have to tell it in advance from which URL it is allowed to resize images this is protection so that no other person can abuse our resizing endpoints so if you have your own backend where you get your images from then you add your own backend URL but here we are going to add the unsplash urls so what we do is we go into our project and we open next.config.js which comes with a newer next.js project we go inside the next config block and we add this images value which again is a JavaScript object so we add curly braces and in here we can set this domains value which expects an array that contains strings for each URL that we want to lower load images from so this is images.unsplash.com that we see in the error message but some images have a different URL so we add the second one here the other one is plus Dot unsplash.com when we save this it should automatically restart our project if it didn't work properly we have to execute npm run Dev again and now when we refresh the page we should see our image thing has crossed and it looks good there's some blue background and there's the image again on your side this will be a bit smaller because I increased the size on the screen so everything is zoomed in a bit but yeah this is how it looks let's style this image a bit so it looks cooler we do this with a few utility classes here directly on the image tag I want to use rounded which again is coming from bootstrap and it adds these rounded corners we can add a shadow like this and I want to set the Min width to a 100 percent enter height to 100 so it keeps the aspect ratio and what this is useful for is that the image automatically gets smaller on smaller screens until we reach the width that we defined here so the largest version is this but we can make this image smaller okay below the image I also want to put a link to the profile of the user that created this image So Below the image I write bio then I add the next link here because this will link to a page within our own app if this was an external page you would use a normal HTML link so an a attack but since this will be another page inside our own app we use the next link and Within These curly braces we pass a string this link will point to a slash user's slash this is another route we will set up later in our project not now but later and then we append image dot user dot username which is contained in the unsplash response we close this and the text of the link will show the username as well so we add curly braces here and in between we write image dot user dot username again okay so it looks like this okay let's save this and now since we are in development mode we can actually hard refresh this page by holding Ctrl down and then pressing F5 and we actually get a new image every time if we refresh this the normal way then we see the same image and this will also be the case when we compile the project and run it in production mode because again next.js goes ahead and fetches this data when we compile the project then it generates this HTML down here and this will then be cached and served to the user whenever we open this page to all users all users get the same page so let's build the project again just so that we see it in action and in development mode the log actually shows you when the cache is hit and when not so this cache Miss up here was when we are hard reloaded the page with Ctrl F5 otherwise we got the page from the cache but we can also run built again to build a project and then start it again and then it doesn't matter if we hot reload the page or make a normal reload we will always get the same page back so when we refresh the page we probably see a new image because we rebuilt a project but afterwards okay it's actually still the same image but the point is no matter if we normally refresh or hot refresh this page we are obviously the same image again because this is fetched only at compile time and again this is the equivalent of get static props in the old Pages directory this behaved the same just that now we do a defetching directly in a server component but of course this is not always what you want right sometimes you want to get a new image every time we open this page and of course we can do this as well this is what we will learn in the next section of this tutorial but before we do that I want to show you how you can change the metadata of this page so I'm going to stop the execution and run it in development mode again so that we see any changes to this page immediately and remember in our root layout we have this metadata block here we can actually copy this and Define more specific metadata for a single page we don't want to change the description of the page so we can just delete it and this way it will use the description that we set in the layout so it will automatically fall back to the description that we set in our layout we only want to change the title so I want to set this to a static fetching minus and then the same next.js 13 image gallery and now when we save this we have to refresh the page because we switched from npm start to npm run Dev but now we can see our new title static fetching next.js image gallery you can also set metadata dynamically so let's say we want to set metadata that needs something out of the response that we fetch here on our page and how do we get this up here this is possible but it requires a different approach which I will show you later when we set up a user profile so make sure to keep watching the whole tutorial to the end because there I will show you all of these features one more thing I want to do is I want to put a little text in here that just explains how this page works so that later when you look at this project again you will remember for this I want to put a bootstrap alert above the image alert just adds a background to the text which looks better again it's important that we import the alert from our own components folder not from react bootstrap because this is a server component so we can't use react bootstrap directly in here because they don't have this use client directive that is necessary so we import it from our own package but again it looks like Auto Import doesn't work so we have to do it manually from add slash components slash bootstrap and in here we have this alert that we exported in this file earlier so we use this up here and in here I just want to put some text I'm actually just going to copy paste it here so this texture says this page fetches and caches data its build time even though the unsplash API always returns a new image we see the same image after refreshing the page until we compile the project again this is what we learned here static rendering lastly let's add a link to our new static page to the navbar and let's delete the hello page because this was just for presentation we don't need this hello page anymore so we delete this whole folder we're going to the navbar here and let's replace slash hello for slash static we set the path name comparison to static as well and the text was there static and now we can navigate between the front page and our static page cool stuff so Dynamic rendering next okay so now we want to create another page where we fetch data from the exact same endpoint but instead of rendering and caching the page at compile time we want to make a request every time we open the page and every time we refresh it we will still have a server component so all the data fetching and the rendering will happen server side but we cache the response differently so for this we want a different URL right so next to the static folder in the app folder we create another folder called dynamic because this is usually referred to as Dynamic rendering and here's a cool little trick as I explained all these folder names are part of the URL right so when we have the static folder we get slash static with the dynamic folder we get slash Dynamic if you put them into subfolders then these subfolders will also be part of the URL but what if we want to organize these different page folders into subfolders without these subfolders affecting the URL this is actually possible for this we simply have to put the folder name into parentheses so let's create another folder in the app folder but we want to use this folder only for organization we don't want this to be part of the URL then we can put a name into parentheses so for example I create an SSR folder for Server site rendering and in here I want to put dynamic and the static folder we also want to update the Imports but now our URL structure hasn't changed we still reach our static page under slash static so SSR is not a part of the URL okay and then we want to put a page into the dynamic folder right page.tsx and this page will look very similar to the static page that we already have so let's open the static page on the right side we need the same import statement so I copy paste them over here we also need metadata just that the title was a dynamic fetching then we also want to export a page component so export default async function async because again we want to fetch data in here in the server component then we can copy all of this Parts here we want to make a fetch request with the exact same endpoint get the image back calculate the width and height and then return some UI so again we have a diff here with the same class names the alert here will say something different we keep it empty for now and below I also want to copy paste the image and the link to the user profile here inside the div okay so right now with this page will behave exactly as the static page let's try it out let's close this one here make the smaller again and go to a slash dynamic then we should get an image but when we refresh the page we see the same image again but turning this into a dynamic page is very easy we go outside of the page function above or below the metadata doesn't matter depends on your personal preference and then we export a const with the name revalidate the state's next JS how often it should revalidate this page and we can set this to zero to revalidate it whenever we refresh the page so this page will not be cached at all now when we save this this is a dynamic page now when we refresh the page we get a new image every time because this is not cached anymore it's revalidated without any delay every time we refresh the page so this is the equivalent of get server-side props in the Pages directory again this data is still fetched server side in the server component this is not a client component just that the request to the server happens every time we open the page this is why we see the loading indicator when we refresh the page because this takes a moment right this has to make a fetch request to the unsplash API instead of setting we validate here for this whole page you can also set it for a specific fetch call so we have await fetch here after the URL we can add a comma and add some configuration in curly braces I added here into another line in here we actually have this cache field which we can set to a string and we can set this to no cache or no store in next.js they have the same effect they do the same thing as revalidate 0 just on the level of a specific fetch call so if I comment this out this should still be dynamically rendered we still get a new image back every time we refresh the page just that now we configured it for this single fetch call here meaning that we can have other fetch cards in this page that are still cached so this gives us more fine control because now we don't have to decide the caching strategy for the whole page at once we can decide it for each fetch call so again you can also use no store here so what I'm going to do is just so you can remember it later I put it here after a slash of course this is not valid syntax but I'm gonna comment this out and there's actually another option you can use you can also configure the cache over this next value here to which you have to pass an object so another pair of curly braces and this next object is added to the fetch function by next.js so next JS basically enhances this fetch function with its own configuration and in here we also have this revalidate field which we can set to zero and again this has the same effect let's try it out when we refresh the page we get a new image there were no cash no store entry validate are all effectively the same they have the exact same effect and next.js I don't know why there are so many different options but this is how it is I'm gonna leave them in here as a comment so later when you will need a refresher you can just take a look at this repository and you get reminded again let's also build the project to make sure that this does not only work in development mode but also in production just one thing I want to note here unsplash has a rate limit in a free account of 50 images per hour so if you exceed this by refreshing this page too often you will start seeing arrows don't get confused by these errors you just have to wait for an hour until you can try again and when you build a project you actually see some icons down here that indicate the caching strategy for these different pages as you can see there is this Lambda icon in front of Slash Dynamic and this means server set renders at runtime so this is the equivalent of get server side props just that get server set props is used in the Pages directory not in the new app directory and the circled xiaomin automatically rendered as static HTML so add compile time basically which is the case for our static page so let's start this and see if the behavior still is the same so when we refresh the dynamic page we should still see a new image but again pay attention that there is rate limiting applied so you can't do this too often I'm also gonna put some explainer text here in the alert which says this page fetches data dynamically every time you refresh the page you get a new image from the unsplash API and then I also want to add a link for this page to the nav bar so I duplicate the static link change this to a slash dynamic inactive as well and the text and then I'm gonna start this in development mode again with npm run Dev okay and next we want to cover incremental static regeneration where we also cache the page statically but just for a certain time as well and if we refresh the page after this time and aware we get a new response back and in fact every user opening our page gets the same data back but by now you probably already know how this works we just have to set a value greater than 0 for revalidate so let's actually copy this whole dynamic folder one more time into the SSR folder and just rename it to a ISR short for Encore rental static regeneration then we open the page in the ISR folder we change the metadata to a incremental static regeneration so this will be the title of the page we delete no cache and no store because they tell our app to never cache the response but we want to Cache it for a certain time interval right we can still do this with the revalidate options if we want to do this on a fetch level we can do it down here in the configuration let's say 15 seconds if we want to do this for the whole page instead we can set it up here with this route configuration before we try this out I also replaced this alert text on here which explains what this does then let's save this and then let's try it in production mode just to make sure that this works properly so we'll stop the execution of run Dev and execute run build the build icon down here is still this circle and not the Lambda icon like for the dynamic page let's start this and then navigate to slash ISR so we see this image if I refresh the page we get a new image that's generated but if I refresh the page again we should still see the image by will Rust but this takes a moment to load the image yeah but refreshing the page shows us the same image until 15 seconds are over then we see another image for another 15 seconds now as I explained earlier when we refresh the page after 15 seconds we will still see the previous image but in the background next.js goes ahead and refetches and re-renders the page meaning that only the second refresh after 15 seconds will show the new data so now if I refresh this I see the same image one more time but if I refresh it again I get a new image and again the same pages are served to all users so they all see the same image until one user triggers the revalidation after 15 seconds let's also add another entry to the nav bar so this will lead to slash ISR and the text will also say ISR and when we run this in development mode again we should seal the new entries in our navbar so now you can navigate between these different pages and you have a reminder how each of these caching strategies work okay and next we will learn how we can create Dynamic URLs Dynamic URL means that we can put a variable into the URL where we can enter anything we want a certain keyword for example and then we can use this value on our page to fetch data for this keyword so I want something like this I want localhost 3000 slash topics slash and then we can enter whatever we want apples shoes holidays whatever and then we will fetch images from unsplash for this keyword so the first part of the URL is slash topics this will always be the same right we already know how we do this we go into our SSR folder which again is ignored from the URL and then here we put the topics folder which is the first part of the URL but now we want this Dynamic part entry can create such a dynamic path by putting another folder in here but this time we put a name into square brackets and whatever we enter in here is the name of the variable so this topic down here will not actually be part of the URL so this will not be a slash topics slash topic instead topic will be replaced for the actual keyword in the old Pages directory you also used square brackets but there you put it in the file name of the page now you put it in the folder name because in here as usual we have to put a page TSX and in here we want to export default async function as usual which I'm gonna call Page and then we want to return some UI down here let's put a diff in here for now in order to get this value out of the URL we have to add props to our page component here so as usual in typescript we create an interface which we call Page props but again you can give this any name you want however what you put in here into this page props is not up to you you have to spell it the same way as I do otherwise this value will not be recognized by an xjs we can get a params prop in here and the params will contain this topic variable in the folder name inside an object so we add a pair of curly braces and then rewrites topic colon and this will be of type string now if this URL param would be called slug for example then this would also be slug whatever you put in here is what you get here as the key there is another value we can get out of the URL and that's the search params search params has to be spelled like this in camera case and since this can contain any value at runtime you have to declare the type like this but I'm going to comment this out because we don't need the search params here again the search params are whatever you add after a question mark to a URL this is usually used for some kind of filtering or query and then we can add these page props to the page component so page props as the type in here are our params and inside the params is our topic right so we want to de-structure this again with a colon and another pair of curly braces and then here is the topic value we care about let's confirm that we actually get the correct value by just rendering it here inside the div as a text so I go to a slash topics slash apples and now we should see apples on the screen and there it is so now we can use this value to fetch some images from unsplash so again since this is a zobo component we can just fetch right in here recreate a const response which awaits a fetch request this time we use a template string with backticks because we have to put more than one variable in here now we actually want to make the request to the same endpoint as on our other pages so let's copy this part here from the string let's paste it over here it's still the random photos endpoint we still want to add our access key since this is a back tech string we add a variable with a dollar sign and a block of curly braces and in here we put process dot nth dot we have to make sure that the spelling is correct so I'm gonna copy it from over here and splash access key entry can actually add a search query to this random endpoint here after the question mark which by the way again indicates that those are search params after the question mark we write query equals and add another variable placeholder here and in here we want to put the topic because we want to search for this topic but we also want to return more than one image so we can add an Amber send sign like this to add another search program to the URL then rewrite count equals 30 and another Ampersand sign for the last search param which is declined ID so now we return 30 random images for whatever topic we insert into the URL and since this is random every request will fetch new images and as we cache it in some way then since we added the count value here we actually don't get one image back we get an array of images back so we create the const images which will be of type and splash image again but this time it's an array so we add a pair of scrap brackets and again we get this from a weight response dot Json then down here in the UI I want to put the topic into an H1 headline and then below I want to render our images in a list so we want to put a map column here and we do this between curly braces because this is a JavaScript expression here we want to take each image in our images array and turn it into a UI element right so as usual in react we cut images.map and again I covered this in my moon beginner course if you have never done this before in this map car we get past each image right and we want to turn them into an image element so I put a pair of parentheses here so I can put this into a new line and this is still considered one return value and the semicolon here is wrong then we want to use the next image as usual because this resizes the image properly foreign is the image from this map call here image dot urls.raw right this time we will set a fixed width and height they will all be square 250 pixels and again next JS will automatically resize these images to this size which is really cool we want to set the alt text again to image.description since this is an array we also have to set a key this makes rendering for react more efficient because it knows which data belongs to which element in the list again I covered this in my beginner tutorial we need a unique value here and since each image is coming from a different URL we can use the image URL as the key lastly I want to add some styling to these images some CSS because we are resizing them to a square which can make them distorted if the original image is not actually a square so we put a CSS module right inside the same topic folder because this only belongs to this one page let's call it topic page.module.css again the dot module is important because this turns this file into a CSS module and here I just want to put one tag one class name which we call image we want to set object fits to cover this xender crops the image so it fits into our Square without getting distorted I want to add a little margin of 0.25 Ram and the Border radius just so it looks a bit better of 4 pixels and that's it then we go back to the topic page we import our CSS module and usually you call the variable styles that seems to be a naming convention import styles from dots to get into the parent folder which is the topic folder and then here we have topic page.module.css and then we want to apply our image class to our image down here so we add a class name we set this to an expression with curly braces and then here we press Styles Dot and the same class name we set over here image and then we close this image tag with a slash and a closing angle bracket now when I make this window smaller we actually already see images here because I saved the changes and they are applied automatically and the dynamic part of the URL is set to Apples now let's refresh the page and see what happens we actually get the same images again so these pages are rendered when we first access them let's try out holidays this will take a moment to load we get this back but when we refresh the page we should see the same images again so they are rendered at first axis and then cached statically if we want new images to be generated whenever we refresh the page we can again set revalidate to zero with export const we validate equals 0. let's try this out again when we refresh the page we get new images but again there is a rate limit of 50 images per hour so if you exceed this you will start getting errors I'm going to comment this out to make this static again and you can also tell xjs to render some of these pages in advance so let's say we know that we want to render Pages for the keywords Health Fitness and coding for example and we don't want to render them the first time a user accesses them we want to render them when we build the project then we can export another function from this file export function this is called generate static params and make sure the spelling is correct otherwise next.js will not recognize this this function can be dynamic if you need to fetch some data in here and this is the equivalent of get static paths in the old Pages router but the syntax is simpler now because the return type is simpler we just have to return an array that contains our object Keys here so since we already know these keywords in advance let's create an array of strings and I said we want health we want Fitness and we want coding you can put any keyword in here you want but what we have to return from this function has to look like this it has to be a JavaScript object that contains our topic here colon and then this keyword behind it but instead of writing it like this for every single element in this array we can just map this to this value so we map each topic to an object and that contains the topic kill so it looks like this note that I added a pair of parentheses and then a pair of curly braces inside it because otherwise this function will recognize this as the function body with the curly braces but this is not the function body this is the JavaScript object we return this is where we have to wrap this into another pair of parentheses so let's try this out let's save this now we have to build a project because this data will only be fetched at build time and then cached so I run npm start again and now when we open one of these three pages here there should be no loading indicator because we've fetch this data in advance when we compile the project so I set this to coding and this page should load pretty much instantly without the loading indicator that's the important part we shouldn't see the spinner in the UI and there was no spinner right now what happens if I try to open a topic that we didn't add to the array let's say a beach for example we enter this then we can still access this page but this one is generated when we first access it because it's not part of our array here and xjs can't know in advance for what keywords it has to fetch the data right only when we return them from generate static params and we can also see in the build log that these topics are pre-generated here now there was no loading indicator when we opened the beach page but I think this was just because it returned the data so fast that we didn't see it but it has to be generated dynamically when we first access it now if you only want to allow these three paramsia and not any other ones then this is possible as well with another value that you can export export coins dynamic params in camel case we can set this to false now when we build the project again we will not be able to access any topic Pages besides these three here let's start the project again and refresh the beach page now this leads us to not found but we can still access our other keywords here like Fitness and coding I'm going to disable this again by commenting this out and then I want to put an alert message in here as well I put it above the H1 again we import an alert from our own folder not from bootstrap because this one will not work inside a server component so we change the import to add slash components slash oops bootstrap and then again I paste some text on here and run this in depth mode again so we can see the changes this page uses generate static params to render and cache static Pages at build time even though the URL has a dynamic parameter this is what we return here from generate static params pages that are not included in generate static params will be fetched and Rental on first axis and then cached for subsequent requests this can be disabled and again you disable this by setting Dynamic params to false if you don't want to Cache the data you can set revalidate to zero now I also want to change the title for this page like we did for any other Pages by this time I don't want to set this to a hardcoded string instead I want to put whatever keyword we use into the title so instead of exporting this metadata value here we want to generate the title dynamically we can do this by exporting another function gonna put it above generate static params but you can put it wherever you want export function generate meta data and again the spelling and the casing has to be correct and this can actually take the same params as the page so the page props and here we have our Paramus value and India is the topic right that we want to put into the title this function has to return an object of type metadata from next so it should add this import up here and in here we can return an object and in this object we have our title we have our description and any other metadata values that we can set we want to set the title but since we have our topic available here we can set the title dynamically from this value and we could also use the search params in here for example so now we can write topic plus and then we want to append the same parts that we have here minus next.js image gallery like this now when we save this we should see our Dynamic title yeah the keyword is up here in the URL Fitness let's try coding and a test coding in the URL now you can also make generate metadata async and fetch data in here for example if you want to use some value from their API response in their metadata we will do this in the next section of this tutorial for now I want to put some entries for these topic pages into our navbar just so that the project looks better So Below the last enough link here I'm gonna put an opening angle bracket enough drop down which we import from bootstrap again we can do this in here because we are inside the client component we can set the title to our topics and an idea two topics perhaps drop down and then we close this I think the ID is necessary for some accessibility features that's why I'm adding it here it can't hurt and in here we put three enough drop down items for our three topics that we pre-generate we want to render them as next links as usual and then set an href the first one will lead to a slash topics slash health right that's the first one here and generate static params and the text what they have and then we duplicate this two times for slash Fitness and slash coding and now we have this drop down in the URL to navigate between our different topic pages perfect okay now I want to create another page that uses generate metadata which we already used on the topics page but now I want to set the value from the response we get back from the API but we fetch it down here in the page how can we get this value up here in the metadata that's the question for this let's set up another page and I want to fetch the user for a username and shows them basic profile data so again we have to create a type for this but we will ignore most of these values we will only care about the first name the last name yeah and the username so let's go back into our project and create a new model for this unsplash user in the models folder new file and splash minus user.ts and here we export an interface called un Splash user and in here we put the username which is a string and again these Keys have to match the return type of the API first underscore name and last underscore name and we ignore the other values then I want to set up a new page and again we want a dynamic URL just like our topics page because we want to be able to insert any username right so let's create another folder inside SSR called user so this is the first part of the URL then in here we put another folder with a dynamic URL parameter which recall username and finally in here we put our good old page.tsx so in here as usual we export default async function which we call the page and again we want to receive the params so we create an interface page props which again gets the params value but now in here we don't have the topic we have the username because this is what we call the variable in the dynamic URL element we pass these params to the page component and in here is params and in there is the username then we want to fetch the user from the unsplash API so we create a const response equates a weight fetch we use a back text string and in here we add this URL so the base URL is the same API dot unsplash.com then we make the request to slash users then we insert the username that we get from the params and then as usual we pass the client idea so you can pause the video and type this out by hand then we want to get the user value out of the response Json and display the user data in the UI so inside the div let's put in H1 that will render user Dot he was a name we have to set a type of the user here so we get Auto completion unsplash user from our models folder and now this order completes to a username then I put a paragraph below which says first name colon and this will render user.firstname the same for the last name another paragraph and below I want to put a link to the profile of the user on unsplash and since we don't use this link to navigate with in our own website we can use a normal angle tag instead of the next link we set the href of this link to an expression with curly braces and here we put a string we want a link to https colon slash slash unsplash.com this time without the API in front of it slash and then we wanna append user.username this will bring us to the unsplash profile of this user and the text of the link will say unsplash profile so let's try this out I saved this we are still in development mode and let's go to the static page where we should see an image and a profile link that we added earlier this leads us to this newer route we created slash users slash and the username and there's the profile and this link here brings us to the unsplash profile but this is not so important now what happens if we try to open the profile page for a user that doesn't exist so I just add some random characters here then we don't see any data because by default fetch doesn't throw an error for a 400 or 500 response if this would throw an error then we would see the error page instead but both cases are not great we don't want to see the error page or an empty page we want to get to the notified page instead right if we take a look into the log we can see that we actually get a four or four response from the unsplash API for this request because the user doesn't exist but this 404 response doesn't cost next JS to automatically redirect to the not found page but we can do this manually we can go below const response entry can check if response dot status which contains the status code is equal to 404 which means not found then we want to redirect to our note found page and by our not found page I mean this not minus font TSX file we set up earlier we want to redirect here in the old Pages directory we did this with a special return value from get static props or get server side props here in the new app director here we simply have to cut this not found function which again is an import from next slash navigation this will bring us to the not found page so let's try this out again let's save this and we get to the not found page because this user doesn't exist but the previous user does exist but we also want to learn how we can generate metadata from this response right so in the UIA we only have the username but instead of putting the username into the page title I want to put the full name of the user into the page title but we only get these values from the response from the apis we have to wait for them whereas in the topics page we just used the params value and generate metadata which we get immediately and because this is part of the URL so what we have to do we have to export the same generate metadata function again but this time we make it async so export anything function generate metadata and again make sure the spelling is correct and again we can receive the zampa runs as we receive in the page up here again the function has to return metadata but since this is an async function now we have to wrap this into a promise because async functions return promises then here we want to return a metadata object and we want to change the title but again I want to set the title from the values we get back from the response but we have our response down here in the page how can we get these values in the generate metadata the answer is quite simple we just make the exact same fetch request up here to the same URL now you might be wondering wait isn't this wasteful because we make the fetch request trials but next.js actually automatically de-duplicates this requests meaning that even though we make this fetch request here trials it will only be executed once and the fetch card that's executed second will automatically use the values of the first fetch call this is handled by next.js but instead of writing the same not found logic and the same URL trials I want to extract this into a separate function just for organization we can do this right in here async function and let's call it get user which will take the username as a string and make the request to the API so I cut out these three lines here put them in here but instead of creating a cons user I just want to return the response Json and to get proper Auto completion we set the type of the function return value again it has to be a promise because this is an async function and in here will be an unsplash user then we use this function down here we create a const user Carl await dot get user and pass the username to it and since we added this return type here this user is now of type unsplash user then we can copy this line and use it up here instead of repeating the URL and then we handle 404 responses for both cases and again this is automatically deduplicated and now we can set the title from the data we get from the user from the API so we can set this for example to a user.first name plus then we add the space and user dot last name but sometimes the first name doesn't exist then I don't want to have the space here so I actually change this into a little bit more complicated expression but don't get scared by this it basically does the same what we did a moment ago just without the unnecessary space so here we have an array that contains the first name and the last name this part here figures out elements that are not defined so if there is no first name then we only use the last name and vice versa and then it joins these two values and adds a space between them if there is no first name and no last name at all then we fall back to the username and then we have our minus next.js image gallery you don't have to do this you can also use the simple version that I showed you a moment ago this is up to you so let's save this and try it out and now we see the full name of the user in the title of the page but I want to have the minus next.js image gallery in there in any case so I wrap this part here into a pair of parentheses and now it should be part of the title okay nice now if you are not using the fetch function here and you use something like axios for example or different way of fetching your data then these cards are not automatically deduplicated this is only the case for the native fetch function but you can do this manually for this we have a special function available in react let's say get user uses axios instead of Fetch and is not automatic clear the duplicated then we can create a const car get user cached but again the name is up to you and cut this cache function which is an import from react so this is coming from react itself and in here we can pass our get user function up there so now if we call get user cached instead of get user in both places then this will also be the duplicated but again this is only necessary if you don't use fetch so I'm gonna put a comment here as a reminder which will say use cache if you are not using the native fetch and again you can decide on this page if you want to revalidate this for every request or if you want to Cache the request which is the case right now but you already know how this works you can add the revalidate field set it to zero or a number for incremental static regeneration or use the no catch or no store options on the fetch car lastly I want to put an alert down here again inside the div again we import it from our own bootstrap folder add slash components slash bootstrap and then again I add some text here this profile page uses generate metadata to set the page title dynamically from the API response this is what we have done here in the old Pages directory we set this metadata in the heads tag directly in our patch component and this is now completely replaced by generate metadata and in the next section of this tutorial we will learn how to do a client-side fetching and for this we will have to set up an API route Handler in xjs so we did the back end end point and afterwards we will deploy our project so make sure to watch this tutorial all the way to the end okay so all the data fetching we have done in this project so far was server side meaning that we executed our API requests inside server components and then return the ready HTML with the data already inside it either dynamically when we access the page or statically when we have built the project but sometimes you still need good old client-side fetching which means that we first get an empty HTML page back and then we execute some JavaScript that fetches data from an API and then shows it in the UI but instead of fetching server side this happens in the browser of the user this is useful if you want to fetch some data dynamically and wait for the response without blocking the UI by waiting for the page to refresh but it's not as optimal because it requires a client component which means that we send more JavaScript code to the user and it's also not as great for SEO because again search engine crawlers first see at this empty page number Celestia are still some situations where you want to use client-side fetching so we'll learn how to do this here as well for this we want to create a search page where we have an input field where we can type in a keyword and search for images for this keyword since we are not doing server set rendering on this page I don't put it in the SSR folder instead I want to create a new folder inside app CSR for client-side rendering and again we put the name between parentheses to not make this part of the actual URL we want the URL to start with Slash search right so we put a search folder inside CSR and into the search folder we put a page.tsx to make this page available in here as usual we export a default function called page this time it doesn't have to be async because we are not fetching any data in here instead we fetch the data client side and I also want to export metadata here export cons metadata and I want to set the title to a search minus and then again next JS 13.4 image gallery like on the other pages now in order to execute our search client side we will need to use State and use effect and this can only be used inside the client component right so let's try to make this a client component with the use client directive and for now return an empty UI here like this but when we navigate to a slash surge we can open the page but we don't see our metadata title here this is because metadata actually has to be exported from a server component not a client component if we remove use client the should show up in the title and there it is but the use client directive RS has to be at the top of the file right but we only want to make this part down here a client component this means we have to put this into a separate file so inside the search folder we create a new file and we can give this any name we want because now this is technically just a normal component I'm going to call this search page.tsx and here we export a default function with the same name search page and let's return just a diff with some text for now search we can make this a client component to use client features in here and then we can return those from our server component here so here we want to render the search page and now we see our text here so now the server component here is a wrapper for our client component and again this is necessary because the US client directive always has to be at the rabbitop but we can't use it here because we need a server component to declare metadata this is how you put a client component inside a server component and you can also fetch data here in the server component and pass it as props to the client component this is also possible now let's go into the search page component and first of all I want to put in input form in here inside the div for this we can use this bootstrap form from react bootstrap and again we can import this directly from react bootstrap because we are in a client component anyway so we don't have to use the re-exported version we set the unsubmit prop to handle the submit which is the function that will receive the actual input value so above the return statement we put an async function with the same name handle submit and this will receive a value which is usually called e short for event and this will be of type form event which is a react import and then we add a pair of angle brackets like this and set the type to a HTML form element now our form here will be very simple with just one input field so we handle it all manually via the storm element if you have more complex forms then you should use the react hook form Library instead which makes it easier to work with more complicated forms with more input fields and reuse react talk form in my paid next.js course again if you want to check this out the link is in the video description let's finish our form down here so we go between the opening and the closing tag and in here we put a form dot Group which again is coming from react bootstrap we set the class name to mb-3 which adds a bit of margin to the bottom of this input field entry set to control idea to a search minus input the control ID is needed for accessibility it connects to example the label of the input field with the input field itself so that when we click the label the input field is selected but this is handled automatically for us by react bootstrap if we just set this control ID in here we want to put a form.label which is a search query this is just a text with the above the input field and we add the actual input field below reform dot control the input field needs a name so we can get the value out of it later and we colored just curbio or search query or whatever you want and let's also set a placeholder text that will be shown while the input field is emptier I write ego cats hotdogs dot dot not hot gods hot dogs this is just there so the user gets an idea on what they can type in and then we close this form control and there's our input field and this is the label and when we click the label the input field is selected this is handled by this control ID here just nice to know then below the form group but still inside the form tag we put a bootstrap button we set the type to submit so that when we click this button it will automatically submit the form that this button is in again we add some margin to the bottom with mb3 and the text of the button with their search so when we click this button this form will be submitted and handle submit will be executed so now we want to get our input out of our form right out of this form event first of all we have to cut either prevent default because otherwise the page will refresh when we submit the form this is the automatic HTML Behavior but usually you don't want to do this because you want to submit the values via JavaScript then we need to get the input values so our query out of this form event again when we do this manually this is a bit more verbose and complicated react talk form makes this easier but for just one input field this is fine we need to create a form data which we initialize with newer form data and in here we pass Em which is this form event dots Target and for typescript we have to cast this with the S keyword to HTML form element all this does is it takes our input field here and wraps it into form data because out of form data we can now get our query cons degree equals form data dot get and then we have to pass the key of the value as a string and that's the name we set down here so we want to get this value out of the form data but the type of this is not string it's from data entry value or null so we want to turn this into a string with the safe call Operator so question mark and then we also want to trim this value which means that we remove any white spaces in the front or the end of the string because we don't want to have them as part of the search query as we know the query is a string or undefined if we didn't enter anything so for now let's just show a dialog on the screen that shows these values so we see that this actually works so we check if query if query has a value so if we type something in then we want to show an alert dialog with this query if the user didn't type anything in then we will not do anything at all I think there's no error message necessary because it's clear that if we try to search with an empty input field it will just do nothing so let's try this out let's end our docs and we see it in the alert dialog so the input field works but of course instead of just showing this dialog we want to make a request to the unsplash API with the search query now the problem is we are on the front end here inside the browser because this is a client component this means we can't use our credentials here because they would be leaked to the browser right and someone could find them if they inspect the source code as I explained earlier unless we prefix our environment variables with next underscore public they will not be exposed to the front end even if we try so let's try this out let's try to show process.nf dot unsplash access key and allow dialog when we click this we get undefined but this is good because we don't accidentally want to expose the skill to the client so when you fetch data client-side like this and you need API access keys that should be kept secret then you have to Route this over your own backend server because again the backend server can execute this and use the key without exposing it to the client so you could either set up your own separate backend like an Express server for example but as I already explained next.js has API routes by default where you can build your backend directly in next JS so let's create such an API route where we can use our access keyn and make our search request so we put these API rods also in the app folder and in here I create an API folder which means that the URL will start with Slash API you actually don't have to do this but this is a convention because you usually want to put your route handlers behind the slash API endpoint because those are not Pages those are server endpoints that just return them Json so we want to make this request on localhost 3000 slash API slash search so I add a search folder in here and then in here we don't put a page.tsx we put a route dot TSX because this is an API route not a page so again the name is important you have to call this route.tsx not something else because otherwise this will not be recognized as an API route Handler okay and here we export an async function which we can get in our uppercase and to the sket function we pass a request object like this this request object doesn't have any import because this is available in JavaScript or node.js by default now in the old Pages directory we had a single Handler function and in this Handler function we had to check the method of the request this way we could distinguish between a get request or a post request and so on but now in this newer app route handlers we have different functions for these different HTTP methods so we have an export async function get we can also export async functional post patch delete and so on for this other HTTP methods and in here we can handle get requests to this route right so we will pass the search query from the search page as a search param so the UI will look like this slash API search then question mark query and then the actual search query so we want to get this value out of the URL in here for this we created const that we de-structure we assign it to a newer URL again this does need an import statement and in here we pass request dot URL request is the value that we get up here and inside the curly braces we should Now find the search params which are the search params in the URL then we want to get the query value out of there so we create a construe entry assign it to search params.get and pass query as a string this value of course can be null because maybe it is search program is missing is to below let's check if query is undefined we want to return a response we use next response this time which is an import from next slash server and next response is just normal response value that we also have available but next response extends this with some convenience functions and similarly there's also a next request which is the same as this request type up here just with some utility functions added to it on this next response we can call.json to create a Json response parentheses and here we put a audio this was the error column no query provided this is just a response we send back if we try to access this endpoint without sending a search query to it and after a comma we can add some configuration here I want to set the status to a 400 which means bad request because this is an invalid request without a search query and then below I want to make the fetch request to unsplash so we create a cons response equates away.fetch this time I want to make this request to the search endpoint here which doesn't return random images it Returns the same images for the Zim search request the return type still contains an array of results but this time we have this wrapper around it so we have to create a new type for this let's go into our unsplash image type that we already have and add this report type below so we export another interface which we call unsplash search response again the name is up to you we ignore all the values except for the results which is the array we actually care about we don't care about these other values and the results is simply an array of unsplashed images and that's it then we go back into our route Handler make this fetch request and repair the backtick string and remake the request to https colon slash slash api.unsplash.com the same as before now the end point is slash search slash photos so we add this here the search query is passed as a search param so we add a question mark write query equals and here we add the query that we send to our backend right and then again ambus enzyme client underscore idea entry set this to our usual process.nf Dot unsplash access key and again this is executed server side so it's safe to use our API credentials here and then we will send this data back to the front end right to the client so we want to get the results out of here so we pass a weight response.json we set the type of this object here to our unsplash search response so that we get Auto completion now in here we can find our results I mean you can also remove this but then resize yourself type any this is just a bit better for typescript and then we want to return this so again we call return next response dot Json but instead of an error like up here we simply send the results back to the front end and this is our API route Handler this is a little absorber endpoint directly inside our next JS project but again you don't have to use this API route handlers as your backend in your next JS project you can just as well connect it to an Express backend for example and in fact this is what we do in my paid next.js course because in my opinion for larger projects a separate backend is often more convenient but for a smaller projects this API route handlers are great okay let's go back into our search page here now we actually want to fetch this data now when you fetch data client-side in a react app you have to put it into a state so at the top we create a const where scrap records the first value is search results this is the state where we will store our search results in and then we need a zeta function set search results if you have no idea what this is then you have to check out my main beginner course again because they're explainers we assign this to use State we want to initialize this with a value of null because when we open this page we don't have any search results yet but we want to tell type script that we expect an array of unsplash images here right but it doesn't know at this type because we just set the default value to another so after your state we add a pair of angle brackets and here we can set the type of this explicitly we want to set this to unsplash image array scrap brackets or Naya which is the initial value so we make a vertical bar and add Naya as the second type so now search results is always of Type unsplash image array or null then we need the state for the loading indicator that will be shown while the request is running so we create another state search results loading search results loading in camera case we initialize this with use State faults and since false is a Boolean the Boolean type is automatically inferred by a typescript and we don't have to set this explicitly then we duplicate this line and we change this one here to a search results loading is error and set search results loading as error as the name implies this state will be set or true if something went wrong with our fetch request and we want to show an error message instead now in a small project like this it's fine to manage these states for the loading State and the array and so on ourselves but in production apps you should use a library like SWR for client-side fetching which adds a lot of feature like automatic caching of these client-side responses automatic race condition prevention deduplication and so on so it does a lot of the stuff that next.js does server side just client-side for client-side fetching here for Simplicity we will not use SWR but again we use this in my own paid next.js course and I also have a separate SWR tutorial here on YouTube where we learn all of this just if you want to check this out then instead of showing an alerts dialog here when we submit the form we want to fetch the data and manage our states so when we submit a new search query first of all we will set existing search results tonight so that our result list gets empty again because instead we want to show the progress below we will also set the error back to false because if there was an error message for the last request and we send a new one then we want to remove the error message entries that search results loading to true which will then show the progress panel then we want to make a fetch request to our endpoint that we just set up so const response equals a weight fetch we want to make this to a slash API where we put our route Handler slash search which is the name of the folder here and then remember we have to send the search query as a URL search param so we add question mark query equals and then we appends the query that we entered into the input field and again this detour over our own back-end route is necessary because we can't put any API credentials into our client code we can only do this on our own backend so the actual request to the unsplash API has to happen on our server then we want to get the Articles value out of the response remember here we are return the search results which is an array of unsplash images So Below response we create a const images which will be of type and splash image array and reassign this to a response.json as usual with an await in front of it and then we can simply set our search results state to these images array and we can display them in our UI now since this is an asynchronous request and this can throw an error we want to wrap all of this into a try catch block so we put this into the dry block in the catch block we want to lock the error which we do with console.error and we pass the arrow here entry one is that search results loading as error to true so that we can show an error message in the UI and in the finally block no matter if the request was successful or not we want to set a search results loading back to false to hide the loading spinner okay that's it for the fetching part and now we want to put this into our UI as well so below our input form I want to put another div with the class names dflex to make this reflex box column to have all elements below each other and whenever we put in here I want to align in the center horizontal layer with align item Center in here I want to put the loading spinner and the error messages so we put a block of curly braces in here we check search results loading to Ampersand science again I explained this in my learn beginner course this is just react syntax if search results loading is true we wanna render a react spinner with the animation border and again we can use react bootstrap components in here because this is a client component if there is an error message so below we check search results loading as error if this is true we want to show some text in a paragraph that says something Rand wrong please try again and if we got a response back from the server successfully but there are no results and there then we also want to show a message so as long as we don't have a response the response is set to another right but if we get an empty response this will not be none anymore this will be an empty array So Below we can check search results then we use the save call Operator because this can be null if the length of this array is equal to zero then we want to render another text that says nothing found trial a different query and then below we want to render the actual search results right so I put this outside of the stuff in a block we first check if the search result is not null anymore again we do this with this ampers enzyme if this is the case we want to map the search results in here so we add an empty fragment which looks like this because now we can put another block of curly braces in here this wouldn't work without these empty fragment elements and in here we want to take our search results and map them into images similar to how we did it on the topics page just at this time we only do it when we actually have a response from the server zor here we call search results dot map again we get each image passed in the snap call again we wrap the return value and the parentheses and then we want to turn each of them into a next image the srz as usual is image Dot urls.raw again we hard code the width and height to 250 pixels just like we did it on the topics page we set the alt to image.description again and again we have to define a keyer because this is an array again we set this to image dot URLs dot Raw and then I want to use the same class name as we used on the topics page for our images this is contained inside the topic page module now of course we could put the style outside of the app folder into a Styles folder and use it in both places but in this source code here I want to make it very clear that we can co-locate dcss files with each page so instead I'm going to copy paste this CSS module and also paste it in the search folder and just rename it to a search page dot module.css but we keep the same class in here so now in the search page we import this CSS module Imports diodes from dot slash search page module.css and then down here we use this class on the image class name Styles dot image which again is the class that's contained in the CSS module then we close this image tag with a slash and a closing anchor bracket and the line is here properly one more thing before we try this out I also want to disable this button while we are currently loading a response so that we can't click it twice in a row so we set the disabled prop of the button tool search results loading so let's try this out now I can type something in here for example hamburger when we click this the button should be disabled we should see our progress banner and then we should see a list of results so this seems to work and this data is fetch client side this is fetch with JavaScript using state and I shouldn't have searched for hamburgers because this looks way too delicious I think I have to get a hamburger today anyway as usual I want to put an alert message in here that just describes what is happening on this page so that you have a reminder later this page fetches data client-side in order to not leak API credentials the request is sent to an xjs route Handler that's our backend Handler that runs on the server this route Handler then fetches the data from the unsplash API and returns it to the client just one more thing I want to add another entry to our navbar I want to put the not enough link behind our drop down like this which will bring us to a slash search and it was a search right so this is how this menu item now looks now you learned all the different fetching and caching strategies in the newer nextges 13 app router so now you are equipped to build your own modern xjs websites but there's one more thing left that you don't want to skip here we want to deploy this whole project and we will not only deploy it we will also add a social media image so a rectangular image that will be shown when we paste the link to our website for example on Twitter or Facebook okay so when you build a website you usually want to have a social media preview image on there which looks like this basically you post a link to your website you'll see the title and the description that we already set up in the metadata tag but you also want to have an image right just so that the links look good for this I created this social media preview image here again this is very big because I zoomed in the actual size is smaller but this doesn't matter and we want to use this image for the social media preview now if you downloaded the starting point project in the beginning then this image will already be inside the project otherwise you can download it from the GitHub repository in the video description and then using this in the next JS app router is very simple we just have to put it inside the app folder so we download this image here from GitHub and then we can just drag and drop this image here into our app folder now here comes the magic if this image has this exact name open graph minus image.png then xjs will automatically use it as the social media preview image in the old Pages directory in xjs we had to set this up manually in the heads tag by passing the URL of the OG image which we usually would put into the public folder but in the new app router this has been simplified we just need an image with this exact name the same is the case for the fav icon here you can just put a five icon.ico file directly into your app folder and next.js automatically uses it as the fav icon the little icon that we can see up here you can also replace this for a different path icon and there are different generators available for this online just search for fav eigen generator and you can create this little icons here from any graphic you want okay before we deploy this project I just want to add some text to the home page instead of this placeholder div I copy paste this in here you don't have to add this if you don't want to but you can copy paste this whole layout from the GitHub link and we have to import the alert from our components folder add components slash bootstrap should be correct and in here should be our alert I just added this so that the front page looks a bit better and there's some explanation about this project here and then deploying this project to the cell is very easy you want to publish this in a GitHub repository this can be a private GitHub repository and you can easily do this in BS code over the sidebar here Source control there you can initialize the GitHub repository and push your project there so I push this whole project to GitHub and then we go to the zell.com here you want to create an account with the same GitHub account that your project is on if you already have a bezel account that's not connected to your GitHub account you can also go to the settings and update the login connections to connect it to your GitHub account yeah then we go into our dashboard and here we can add a new project and this is very simple this will show you all the projects on your GitHub account also the private ones here we have our next JS image gallery we can import this we can give this project a name and keep it as it is it automatically recognizes that this is an xjs project we keep the root directory as it is we don't have to change anything here but we want to set an environment variable right because we need our unsplash key here so we use the same key name and paste this value here unsplash underscore access underscore here and here we put the value of the key click on ADD and then we can deploy the project with one click and to hop your account on bezel is real and you can also deploy your project for free now we have to wait a little bit this will take less than one minute probably it builds the project just like it did when we are executed npm run build it fetches the data that we want to cache statically and generates all the pages you can actually see the login here and after this has finished we get some nice confetti and it says congratulations your project is deployed and we actually have a preview URL where we can open this website this is a verzel URL but it's nice to try this out and you can actually reach this URL over the Internet it has https and everything it needs and other people can use this and now our social media image should also work so let's copy the URL and let's put it into the social share preview here which is a website that you can use to check how your website looks on social media so we paste this the cellul here and then we should see you our social media preview image and there it is this here is the metadata title that we set and this is the description we can also try going to a slash static which would have a different title right because we are overriders and there's this static fetching next.js image gallery nice now let's just check if our website still works so here we should get our static image by will Rust a nice monkey and when we refresh the page we see the same image again let's go to the profile page here we see our Dynamic data with the first name and the last name and the reason why this page opens so fast even though we are fetching data here is because next.js actually goes ahead and refetches these links if they appear on the page this is just another nice optimization that you get out of the box with next.js okay some dude hanging in a tree whatever if we refresh this page we should get a new image and incremental aesthetic regeneration and the other pages should work as well so we get a new image refresh refresh same image same image and when we wait for 15 seconds we get a new image the topic Pages work as well those are pre-rendered really cool and search let's search for monkey again and they are cute little monkeys and the cool thing about deploying your next JS project to bezel is that continuous deployment is automatically set up meaning that when we make changes to our project and push these changes to the main branch on GitHub then bezel will automatically go ahead and redeploy these changes so you don't have to do this manually you just have to push your changes to the main branch of your project I hope you enjoyed this free next JS course if you did please leave a like on this video And subscribe to the channel if you haven't yet because I'm planning to create more next JS projects in the future and maybe some other Technologies as well also again I have an advanced next.js course that you can check out this one is paid but there we build a much bigger project with more advanced features you can find the course on the codinginflow.com nextjs I will also put this link in the video description below and I also started sending regular web development tips to my newsletter I send about one email every one to two weeks and there I put some tips for example I summarized my findings between the lecture as Pages directory and the app directory in my last newsletter I would be very happy if you joined this newsletter you can find it under coding and flow.com newsletter and again I will put the link into the video description as well and then I wish you a nice rest of the day as usual Happy coding take care
Info
Channel: Coding in Flow
Views: 23,041
Rating: undefined out of 5
Keywords: next.js tutorial, next js tutorial, next.js 13, next.js 13.4, next.js 13 tutorial, next.js 13 app directory, nextjs 13, next js 13, next js 13 app, next js 13 app directory, next js app router, next js 13 app router, next js tutorial typescript, nextjs tutorial, next js tutorial 2023, next js tutorial for beginners, next.js caching, react server components explained, server components nextjs, incremental static regeneration, next js 13 bootstrap, next js 13 axios
Id: fqfer6xMp2A
Channel Id: undefined
Length: 173min 1sec (10381 seconds)
Published: Sun May 28 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.