Next.js Crash Course for Beginners 2021 - Learn NextJS from Scratch in this 100% Free Tutorial!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi my name is max and in this course i will teach you next js an amazing framework for react.js and that can be strange because react already is a library so why do we need a framework for it i will of course explain that and in this course we're also going to build a complete project with next.js and we're going to learn all the key features that make up next.js how it pre-renders pages how that helps us with search engine optimization how we implement data fetching how we work with api routes and many many other important features and therefore let's start with the most important question first what exactly is next.js and why do we need it so what is next js and why could learning next js be a good idea and why could next js in general be helpful to us as a react developer if we visit nextjs.org the official next js website we learn that next js is the react framework for production okay so that sounds like a good argument we all want to build production apps right so next.js is certainly helpful then but wait a second what exactly does this mean so next js calls itself a react framework for production and that name makes a lot of sense because next.js offers a lot of features that make building large scale ready react apps easier but i personally also like to call next js a full stack framework for react.js and it's the full stack part which i want to highlight here but i will come back to that let's first of all focus on the framework part isn't react js itself already a framework or a library well indeed it is react is labeled a javascript library for building user interfaces and that means that it's a third-party package which you can add to your front-end projects so it's all about client-side javascript code in the end and you can use react there to build interactive user interfaces and it's a library that makes building complex user interfaces way easier than it would be with just javascript i get separate courses and videos on react where i explain why react is awesome so i'll not focus on this here so react already is such a library and it's called a library because in its core it's really only focusing on that user interface part on components state props if you want to build large scale react projects you typically also need to add extra libraries for routing maybe libraries that help you with authentication and things like that now next.js is labeled a framework and a framework that builds up on react now the difference between a framework and a library in the end is that a framework is bigger it has more features than a library it's focusing on more things instead of just a single thing and it's also giving you clear rules a clear guidance on how you should write your code how you should structure your files and so on and all these are things which next js does as you're going to learn throughout this course but it's also a framework building up on another library already on react because it enhances react you could say it makes building large scale react apps easier and that's the part where we're back on this for production part here next js has the goal to make the life easier for you as a react developer and it builds up on react it enhances react by adding many core features which you have to add to react apps on your own otherwise things like routing but also many other things and i'll come back to that in just a second and we're going to dive into the key features added by next js but next js simply adds a lot of features to your react app they then are there out of the box once you start using next.js and it therefore ensures that you don't have to reinvent the wheel as often you don't have to add as many third-party libraries to solve common problems which you need in bigger apps and which you typically need to solve when building real production react apps and that's why next.js is called a framework because it has a lot of features clear rules why it's a framework for react because it builds up on react it enhances react it uses react you still write react code you still build react components but it's a framework for production because it adds all those missing features which you typically do need to add to react apps to really prepare them for production and to solve common problems and with that let's now take a closer look at the actual features added by nexjs so that we understand where it helps us exactly and why using it is a great idea and makes our life easier so let's have a look at the next.js key features and benefits and whilst we go through them it will also become clearer why i like to call next.js a full stack framework as well i would say the most important key feature next js adds is the built-in server-side rendering support now in case it's not clear what server-side rendering means server-side rendering is all about preparing the content of a page on the server instead of on the client if you take a standard react application built with just react then if you inspect the source code of a loaded react page you will notice that the page is actually pretty empty right from the start you only have a basic html skeleton there and then some entry point some div with an id root typically into which the react app is loaded and rendered but all of that rendering is done by react and since react is a client-side javascript library all that rendering happens on the client so in the browsers of your users it's not happening on the server and as a result the actual html code which is sent from the server to the client when a user visits your page is pretty empty now that is not necessarily a big problem it depends on what you're building but it can be a problem because for example if your page also fetches some data from a server that should be displayed like a list of meetups as we're doing it here then the user might initially see some loading state a flickering page for a fraction of a second whilst the request is on its way fetching the data because data fetching only begins once the javascript code executed on the client and then we still have to wait for the response of that outgoing request simply because the page which we requested did not yet contain that data now again that is not necessarily a problem but of course it might not be the user experience you want to offer now it can also be a problem if search engine optimization matters to you now this does not matter for all pages if you have a administration dashboard which is only reached by logging in then search engine optimization does not matter there because search engines will never see that dashboard it's highly user specific and you need to log in anyways but if you have a public facing page with a lot of content that should be found through search engines then of course search engine optimization does matter so for example here where we got this list of meetups we see those meetups as a user but the search engine crawlers will actually only see that initially empty html page which we're getting from a server so that content is not picked up by search engine crawlers and that can be a problem and that's where server-side rendering could help us if that page would be pre-rendered on the server if that data fetching somehow could be done on the server when the request hits that server and then the finished page would be served to our users and to the search engine crawlers then users would not have that flickering loading state and search engines would see our page content and that's the problem server-side rendering solves it allows us to pre-render react pages react components on a server now react js actually has built-in features that allow you to add server-side rendering but it can be tricky to get that right and it requires extra setup from your side with next js that becomes way easier because next js has built-in server-side rendering it automatically pre-renders your pages and that means that with next.js if you build a standard next js app without any extra setup from your site if you visit such a page it was pre-rendered on the server by default out of the box and that means that it's great for a search engine optimization because search engines see what our users see and our users also have a better initial load experience because they don't have that initial flickering if we inspect the source code of a next.js page so if a page in a next.js app then we see that there it's not just an empty html skeleton but instead all the content is already there in that html page which we got back from the server now it is worth noting that with next.js after this initial load after this initial request we still get a standard react app running in the browser a standard single page application even subsequent navigation actions by the user so when the user then browses our page and navigates around those actions are all handled by react in the browser to have this fast interactive user experience which we typically want to offer with react which was one of the reasons why you would use react typically so we still get that but for the initial load we have that pre-rendered page and that in the end means that client-side and server-side code is kind of blended together with next.js and of course in this course you are going to learn how things are blending together how you can write code that runs on the server and how you can write code that runs on the client you are of course going to learn all about that and this is therefore one of the major features that makes up next js this built-in server-side rendering which on its own probably would already be a strong benefit or a strong reason for why you might want to use next js for building your react projects instead of just react.js but it's not the only key feature another very nice feature added by next js is file based routing now what does this mean in traditional react you don't even have a router and just to be clear routing means that we give the user the illusion of having multiple pages when we navigate around and we load different pages then that's the job of our router typically we use react router for that this router basically watches the url and when it changes it basically prevents the browser default of sending a request to some backend server and instead renders different content on the page with react a different component in the end that's what routing is we change what's visible on the screen based on the url without sending an extra request to a server because we stay in that single page application which we typically build with react now that's routing and typically with react routing is set up in code that code could look something like this depending on the version of react router you're using now this works and it's not bad not wrong react router is a great package but it is extra code which you have to write and then often you end up storing your components that act as pages in a separate folder which kind of replicates your route setup in code so if you have three pages set up as pages in code you have three page components in that pages component folder makes sense i guess now since that's the case next js gets rid of that in code route definition instead with next js you define pages and routes with files and folders you have a special pages folder in next js apps which has to be named pages and then your structure in that folder defines the routes and paths your page supports and of course we're also going to learn how that works in this course now that simply allows us to get rid of that extra code and hence we have to write less code we have less work and it's a highly understandable concept because it's very close to how we all started with web development when you're getting started with just html and css and some basic javascript maybe then you build basic websites by adding multiple html files and the names of these files or the folders in which they sit define how you can navigate between these files how you can link these files together and next.js basically allows us to go back to this very basic yet understandable concept of routing and next.js still supports all the features we might want like nested routes or dynamic routes with dynamic parameters and all of that and we're going to see that in this course of course now next.js has more amazing features but the last key feature which i want to point out here is the feature which is most important for me labeling next.js a full stack framework because next.js also makes it easy for us as a developer to add back-end code to our react project so to build a full stack react project where we don't just have the client-side code maybe with server-side pre-rendering but where we also have standalone back-end code that for example works with the file system or reaches out to a database with next js it's very easy to add our own backend api into our react project using node.js code so we can easily add such code to our next react apps when using nexjs and that allows us to add code for storing data to a database or two files getting data from there adding authentication and all of that that's easy to add with next.js we can stay in one project we have to know some node.js code for that arguably but we would have to know that anyways when we build our own backend and then we don't have to build a standalone rest api project but instead we can work on one project our next project and add all the client side code our react user interface and also blend in our backend api code that's why next js is amazing and these are all the core features i wanted to point out here and which we're of course going to learn about in-depth in this course and even more than that so now that we know what next js is and now that we at least have a first idea of why we might want to use next.js let's get started with it and let's create a first next js project for this we just need to run one simple command in the end this command here but to run this command we need to have nodejs installed now we're not going to write any node.js code at least not right now we will write some basic code later but we'll not write it right now but node.js ships together with the node package manager which is an extra tool which is the de facto standard tool for installing and managing libraries in javascript projects and we will use that tool to create the next project and that created next project under the hood will also need node.js to execute for example for that built-in server-side rendering that uses node.js under the hood and for all those reasons we need to install nodejs and for that you can simply visit nodejs.org and from that page you can install the latest version of node.js whatever that version is when you're viewing that just install the latest version simply click on there and download node.js it is available for all major operating systems and then walk through that installer once that download finished now once you have node.js installed you are ready to run this command and therefore we can now go to the terminal to your regular command prompt which is built into your operating system and there you can cd and navigate into the folder where you want to create your next project and then simply run this command npx create dash next dash app run this command by hitting enter and this will now create a new next project in that folder where you ran that command now you might be prompted to confirm that you're installing extra packages and hence i will confirm this here and now this will temporarily install the create next app tool and then start creating that project now for this we first of all need to give this project a name and i'll just use next js dash course here as a name but you can of course pick any name you want hit enter and now this project will be created here and it will set up a base folder for that project and install all the core dependencies this project will need now once it's done you can run the commands shown here to start your development server but i will not yet do that here instead i now opened this project in visual studio code the ide the editor i'm going to use in this course now you don't have to use visual studio code it is a great ide for web development though it's completely free and it's amazing but you can use whatever your favorite web development ide is if you do want to use the same editor as i do here though you can visit code.visualstudio.com and from there you can download visual studio code it is available for all major operating systems simply download the installer and walk through it and once you have downloaded and installed it you can open that next.js course folder which we created with the command here in the terminal with visual studio code now here i'm using the dark theme you can change this under preferences color theme here i am using the dark plus theme and i also adjusted the appearance you can do that under view appearance and simply adjust it as you want and for example show or hide the status bar i'm hiding it but that is something you can configure however you want now regarding extensions that's a great feature of visual studio code you can install extensions there and the only extension that i'm using here and that i recommend that you install is the prettier extension you can simply search for prettier here and that's the extension that will help you with code formatting so with automatically transforming your code to look cleaner and to be more formatted and structured once you installed that extension you just need to make sure that you go to your keyboard shortcuts and there search for format document and make sure that you have that shortcut set up because that's a shortcut which i will press all the time which will then auto format my code and use prettier and to make sure that i do use prettier under preferences settings in your user or workspace so project specific settings you can also search for format and make sure that under default formatter you do pick prettier here here it is so with that all set up you will have the same setup as i do and that is the setup i will use in this course that is the setup we will use throughout all the lectures and it is the setup which we'll now use to dig a bit deeper into this project we just created so we did create that next js project here in the terminal with npx create next app and that gave us a folder which looks like this which has this kind of content attached you also find that starting project in case it changes over time or looks slightly different because the starting template was changed for example so attached you find that exact project snapshot which i have here if you do download the attached snapshot though there is one extra step you need to go through you need to open the terminal and you can use the one built into visual studio code which is your default terminal your default command prompt which ships with your operating system just already integrated into visual studio code and conveniently also already navigated into this project folder so any commands you run here will execute in the context of your project folder and here you then need to run npm install if you use that attached snapshot because that will then install all the dependencies of this project as defined here in package.json and store them and their dependencies in the node modules folder so that's also a folder in which will never work the three important folders for us here are pages public and styles though pages is by far the most important one styles as you might guess holds some style files we can ignore that for now we'll work on that soon and public simply holds public resources our page might use something like images for example now one thing you might see here in public though is that unlike in a regular react app which you for example created with create react app with that extra tool that there in a standard react app you have a index html file in the public folder here in the next js app you don't have that and the reason for this is that next js has this built-in pre-rendering and whilst it gives you a single page application that single page is dynamically pre-rendered when a request reaches the server so that you do return an initial page with content that is what i talked about earlier in this course as well this server-side rendering and the pre-rendering of pages and hence for us the pages folder will be the most important folder because that is where we will set up that file based routing and that is there for the folder which is important for us to define the different pages that should make up our application here now let's get started with writing some next js code here and for this i'll shrink the terminal a little bit and in this pages folder we can ignore this underscore app.js file for the moment we can delete the api folder in there and in the styles folder we can also delete the whole module css file we can keep the global css file if we want though now we got this index.js file and in this file we in the end just have a standard react component but to make this even clearer let's delete this file as well so that the only remaining file in the pages folder is the underscore app.js file and now let's say to get started with nexus we want to build a simple website with three kinds of pages a starting page let's say then a news page with a list of news and then a page for the news details so when we click on a news item and we're taken to the full page for that specific news item and if we wanted to create a structure like this in next.js in the pages folder here we would create three files the index.js file will be our root page so if a request reaches our domain slash nothing just index.js will be loaded that is in line with standard websites if i may call it like this where we also have index html files which are typically served as root pages if a request just targets slash nothing after the domain and here it's index.js which will be served if a request reaches just our domain slash nothing then we might also have a news.js file for requests that reach our domain slash news and that's important with the exception of the index name which is a special name which is served whenever we have a request to just slash nothing the file name will be used as a path name so newsjs the content in here the react component in here would be served for requests to our domain slash news for example so not news.js but just news then the news.js file would be served and i'll comment this out to leave that in here index.js would be served for just ourdomain.com nothing and i'll come back to the page for a single news item later for the moment these are the two pages we have and now what goes in those page files i mentioned it before our standard react component the react component that should be loaded for that specific page so here in index.js we can create a component just as we know it typically as a function and we could name this home page the component name is up to you now you must export this component so that next js is able to find it so to say and then in this component function you return jsxcode just as you're used to you return your jsx code for example a h1 tag where we say the home page that could be a very simple first page of course we're going to add more meaningful content in a second now we can copy this to news.js and add it here as a side note if you're wondering why we don't have any import statement like this at the top where we import react from react next js projects support this modern react setup where you can omit this import and it's added behind the scenes so to say and with that here in the news.js file we would have the let's say news page component and of course also export the news page and here we could say the news page and if we do that if we add these two pages then in the terminal in this integrated terminal here which is already navigated into this project folder we can start the development server with npm and run dev and that development server is given to us by that next js project setup so with npm run dev we start this development server here you see the url where you can visit your page and therefore if i now visit localhost 3000 i see the home page and if we instead would visit localhost 3000 slash news we see the news page and now what's interesting is that the content is just some dummy content but if we view the page source here of that loaded page then we see that in there we don't just have an empty skeleton but if we look a bit closer we find the actual page content in here and that is an important difference to a standard react app where the page is not pre-rendered on the server this html code which we see here is the html code sent back by the server and since it contains that content here that means that the entire page was pre-rendered and that's why the content ends up in here and the advantage is that we don't have any flickering on the page whilst we're waiting for it and in addition search engines would also see that content here they see what our users see and that of course can be a great advantage and this is how we can get started with this file based routing and as you see by looking at the page source in addition to that file based routing we also already use that built-in server-side rendering feature without any extra setup because it works out of the box with that let's now dig a bit deeper and let's see what else we can do here so now we know about this concept of using files in the pages folder for creating routes which then load these different components that live in these files and we also see that this server-side pre-rendering works out of the box now let's dig a bit deeper into that file-based routing system though for example there is an important alternative you should be aware of when it comes to organizing your files and folders we got this index.js file and that loads the root page for slash nothing because it's the index.js file directly in the pages folder now for the news page slash news we get the news.js file we always have an alternative to using such a named file name so a file named differently than index.js we could also create a new sub folder in the pages folder move news.js in there and then rename it to index.js using that special index.js file name again now this page would still be loaded by visiting ourdomain.com news because we're in the news folder and that's important folders which you create in your pages folder also act as path segments and it's totally up to you whether you want to go with news.js in the root pages folder or index.js in the news folder now it does matter though as soon as you start creating nested paths and that's what i want to do now if we want to have a path that is something like news slash something important where something important is the identifier of the specific news item you want to load then you need to create a file in such a subfolder because otherwise you can't create such a nested path after all we have two segments here and if we just create files directly in the pages folder we're limited to one segment the file name so therefore if we want to have such a nested path so more than one segment we need to create a subfolder and then we can also create the root page for that path with index.js and then create the something important.js file as a sibling file to index.js so now we have two different pages that start with slash news slash news slash nothing loads the component in the index.js file slash news slash something important will load the component we create in here now of course here again we could alternatively also create another nested subfolder something important with the index.js file in there that would again be the alternative to using such a named file name in the news folder but i hope you get the idea by now now with that i could copy this code from index.js in the news folder and bring it into the something important page here and then name this detail page maybe because that should be the page holding the details for a specific news item and this page would now be loaded for slash news slash something important and hence if we save everything and we visit slash news we see the news page and if i visit slash news slash something important then we see the detail page so that's how this works but there is still another important concept which we haven't touched on yet creating the detail page like this works until we realize that we probably would have more than one news item on our news site it would be very realistic that index.js in the news folder should output a list of news items and then we can click those individual items and we're then taken to the detail pages with the concrete content for the news item we selected so we use the same page over and over again for different news items for different content we would probably fetch the concrete content from some database when a user visits this detail page and then display it on the screen so it's the same component technically but with different content and that's of course a totally realistic i would even say very common scenario so hard coding the identifier like something dash important like this in the file name is not very realistic instead we want to create a so-called dynamic page where the path segment the concrete value in the path can be dynamic so that it's not just slash news slash something important but also slash something else or slash this course is great whatever so that this would be the identifier of a news item and we have a lot of different identifiers and we add new use all the time but we always load the same page no matter what the concrete value here is but then inside of the page we simply have access to that value in the path so that we can fetch the proper data and that is something we can implement with dynamic paths for that we change the file name here to a different file name and we use a special syntax which will be understood by next js we use square brackets here in the file name in front of the extension if you have square brackets in your file name like this this tells next js that this will be a dynamic page so that it should be loaded for different values in your path and then you can add an identifier between those square brackets where the identifier name is totally up to you something like news id for example like this but this again is up to you but you need those square brackets this then tells next.js that this page will be loaded for different values so for example for something important after slash news but also for any other identifier and then in a next step i will show you how you can get access to the concrete value entered here and how you can use that but let's get there step by step if we now save this again if i load this page for slash news slash discourse is great i see the detail page but i also see it for something else or anything else we enter after slash news so that is how we can add such a dynamic path here and that is another key feature of next js it's a feature that allows us to build truly dynamic and flexible websites with next js but how can we now extract the entered path value inside of the component so that we can for example then fetch the correct news item from a database let's say when a user visits this page to extract the concrete value entered in the url when this page is loaded next js gives us a special hook which we can use a special react hook which we can use in functional components it also has an alternative for class-based components a higher order component you can wrap around your component and i do discuss this in my full next js course but we can ignore that here here instead we import from next to be precise from next slash router which is a sub package of the next package which exposes routing specific functionality and here we get the use router hook it's a regular react hook just not one built into react but a custom hook built by the next team we can now call this hook inside of the detail page simply like this if we do that we get access to our router object and on that router object we then got certain pieces of data and certain methods which we can call now for example we get methods for programmatic navigation but we don't need this here so we can ignore this for now but we also get access to the values encoded in the url so to the concrete values of these dynamic path segments and getting access is easy on this router object we got this query property which gives us access to a nested object and on that query object we then have the identifier which we chose between the square brackets as a property name so in my case news id because that's what i entered here as a file name between the square brackets and that will then hold the concrete value in the url for this dynamic segment for which this page was visited so if we now just console log this for the moment to see what's in there if i save that and go back and open the developer tools if we reload we see undefined first and then something else now we see two logs here because that's how use router works it runs immediately when the page is first rendered and at this point it doesn't yet know what's in the url but then once we have that information the component renders again and we got that concrete value that is just how that hook works so the second time it executes the second time this component is evaluated we got something else which is the concrete url value i entered here and if i have this course is great then we would see this here being locked and that's how we can get access to the concrete data encoded in the url now why is this helpful well we could for example use this now to get our news id like this and then if we had a database if we had some backend api from which we can fetch our news we could send a request to the backend api here to fetch the news item with news id that's what we could do here i will not do it here because we'll soon dive into data fetching and data storage and we'll see different approaches we can use there with next.js so we are going to take a look at that in detail in a couple of minutes but we could do this here if we had such a backend api now we don't have it here because that's just a simple dummy app to get started with the file based routing system but that is how it would work and that's how we can build dynamic pages which work for different pieces of data and then can do different things based on different pieces of data here we could fetch different news items from a database based on the different ids for which we visit this page now whilst we're not going to proceed on this detail page for the moment whilst we're not going to dive into data fetching for the moment i want to come back to this index.js file in the news folder and talk about navigation because currently i of course always enter urls in the url bar manually and that of course is not how users use our website instead we have links on our website that allow users to navigate around hence here on this index.js file in the news page so on the slash news page we typically don't just want to say the news page but we might also want to display a list of news items which are then clickable and to do that i'll wrap this here in a fragment which i import from react so that we can have adjacent jsx elements and a render unordered list here and in that unordered list we could have a well a list of dummy news items for example the next.js is a great framework article and then also the something else article whatever so we have two news items here and these should now be clickable and then lead to the news id page with different ids different concrete values encoded in the url now when we want to build a link we typically do this by using the anchor tag we can create an anchor element and wrap our text with that and then here we can encode the url to which we want to go so in this case if we want to stay on this server we could say we're going to slash news slash and then next js is a great framework if that would be the identifier of this news item and of course this list could also be generated dynamically by mapping some array of data into jsx elements i'm just hard coding it here because for the moment i want to focus on the navigation feature so that is how we do construct a link in regular html and if we save this it also will work if i go back to the slash news page here we actually don't see that it's a link because in the global css file i basically disabled the default styling that would show you that it's a link but we can click it and if i do click it i am taken to that detail page for that specific value so that is working but this is only the second best way of navigating around in a next.js app it works but watch this refresh icon here when i click this link it briefly turns to a cross and then goes back to the refresh icon this always signals that the browser sends a new request and gets back a new html page and that all works but it has a disadvantage it means that we don't have a single page application here it means instead that we're always sending a new request to the backend to fetch a new html page whenever the user navigates around and that's not our goal here it's great that we have those pre-rendered pages so that when a user initially visits our site some content is there right from the start and it's also great for search engines but if a user is on the page already and then navigates around on it we want to stay in that single page application because that allows us to preserve state across pages and give the user a better a more reactive experience a better user experience that after all is one of the reasons for using react that we want to build an interactive ui where we never send a request for a new html page but where we instead update what's on the screen with javascript with react in the end and we're not doing this here when we create a link like this instead we load a brand new page we would lose any state we might be storing any redux state or context state all of that would be lost because we load a new page and we simply don't have a single page application here therefore to stay in that single page application we need to create the link differently we need to utilize a special component offered by next to be precise offered by next slash link that's another sub package which is responsible for linking and from there we can import link actually as a default export so importing the default export like this this imports the link component from next link and that's a special component which we can use in our jsx code to build links using it is simple you simply use it instead of the anchor tag here so i replace a with link we leave the ref attribute the ref prop because link expects a ref prop and that then sets the the target destination off that link it will also then by default render an anchor element so all that will still work our styling will still apply yet if i save and reload if i now click this and you watch the refresh icon you see that now this never changes to a cross now we instantly go to the second page and now we go there without fetching a new html page instead we are on a single page application and the visible content on the screen is actually just re-rendered by react and that's great because that allows us to combine the best of both worlds we have this highly interactive and reactive single page application here where we can manage and store state across pages and yet if a user would visit this page as an initial page by just entering this url and hitting enter we would also be able to return the finished html page here so search engines would also see that finished page if they directly visit it but if we were on the website already and we just clicked the link we stay on that single page app we stay inside of that single page app because link this special link component renders an anchor tag but it watches clicks on those anchor tags and if you click there it prevents the browser default of sending a request and getting a new html page instead it will load the to be loaded component for you and change the url so that it looks like you changed the page whilst in reality you stay in that single page application and hence for site internal links in an xjs application you want to use the link component instead of the anchor tag component because with that you get the best of both worlds now that's it for the very basics of next js and especially the file-based routing system how you can create multiple pages including dynamic pages and navigate around now next.js also has a lot to offer when it comes to pre-rendering these pages and when it comes to fetching data for pages and that's therefore the next content block we're going to dive in in this course section but for that we're going to leave this dummy news project which was only there for learning the core basics about file based routing and we're going to switch to a different project instead and for this i got a brand new project and this project is about the the same idea it's the same kind of project as we had in the react crash course tutorial but you don't need to go through that module first instead attach to find a starting project which i did create with that npx create next app command again just a bit cleaned up and with some components which i pre-built for you simply because these are standard react components nothing next js specific in there yet we're going to work on them a bit throughout this course but at the moment they're just basic react components and since you already know react i don't want it to bore you by again writing such basic react components instead here we want to focus on the next features and the many cool features next js adds and hence this starting project already has a couple of components which we will use on the other hand the pages folder is empty so that we can again practice this file based routing and add some pages for this project and the styles folder also just has some basic styles here and therefore we're basically starting from scratch here with a brand new next.js project and we're going to build this meetup application here which again is kind of similar to what we built in this react tutorial already but there also are some differences the application we're going to build is all about having some meetup and we got a page that allows us to create new meetups and those meetups will then be sent to some backend and will be stored in some database that is logic we're going to add throughout this course and we then have a page where we fetch and display a list of meetups and that's of course also something we're going to build together and we then can also visit the detail page of a given meetup to fetch and display the details for that specific meetup and that will be a dynamic page where different meetup identifiers are encoded in the url and therefore we're going to practice what we briefly touched on already file based routing and we're going to add a bunch of new features where next js helps us related to data fetching but also related to blending backend and front-end code and sending requests to an api which we will build together in this next project and therefore we got plenty of exciting topics to cover let's dive in now to dive in i want to start with a couple of pages here and for this here i also got my terminal open first of all we need to install all dependencies though with npm install and then we can use npm run dev and that will start the development server but of course at the moment i got no pages and hence we should add some pages and for this demo application for this project which we're building here we will need three pages a starting page which shows a list of all meetups then the new meetup page which allows us to add a new meetup and then the meetup detail page which allows us to show the details for a selected meetup and hence here in the pages folder i'll start with the starting page with index.js directly in the pages folder because you learned that index is this special file name which will be loaded for just slash nothing in the given subfolder and here we're not in a sub folder at all so index.js will be loaded for ourdomain.com nothing but then we got more pages for example a page for adding a new meetup and hence we could add a new meetup js file which then would be loaded for our domain slash new meetup and you did learn over the last minutes that we also have an alternative here we could also create a new meetup folder instead of the file move the file in there and then rename it to index.js and that would then be loaded in exactly the same way it's up to you which approach you prefer you need that sub folder approach if you need nested routes but we will not have any nested routes here so in this case it's really up to you and i will go for this subfolder approach here but again it's your choice and then we also need this detail page which we load if a specific meetup was clicked and we want to view the details of that meetup and for this we need a dynamic page because of course we'll have multiple meetups with different ids and the id should be part of the url and then when we load the page we want to use that id to fetch and display the appropriate data and we also learned how this worked we can create a dynamic page with square brackets and then dot js and then simply use any identifier name of our choice between the square brackets for example meetup id and here we could also use the subfolder approach it also is available for dynamic pages we could also create a folder named meetup id between square brackets and move that file in there and then name it index.js and that also works that's something we haven't seen before and that's why i'm showing it to you here because it is also important to be aware of the fact that you can also have dynamic folder names here and then create dynamic nested pages if you need them or like in this case one single dynamic page and then with that we get the page structure we want with those three pages and hence we can now get started working on those pages we can fill those components with some live and then also step by step add data fetching and learn how next js helps us with that so for filling those pages with life i will start with that starting page so with index.js in the pages folder with this index.js file in there we can add our component for example the homepage component and of course also export that that's always important and then we want to return the jsx code that defines this component and that therefore defines what should show up on the page and here what should show up in the end is our meetup list component and that's a component that wants a meetups prop here which holds a list of meetups which we then map into a list of jsx elements where every meetup needs to have an id an image a title and an address and hence when we use meetup list in our page component we need to make sure that we do provide that meetups prop to it it's also worth noting that meetup list like meetup item and so on is a regular react component it is however stored in a components folder not in the pages folder now that folder name is up to you the only reserved name in the end is the pages folder name you can name your other folders however you want i named it components though because i do store react components in there but the important difference to the page components is that those components stored in there will not be loaded as pages automatically instead we can simply use them in the jsx code of other components including page components so we can include the meetup list component on our main page here on the homepage simply by going to the homepage component and importing meetup list there from going up one level components meetups meetup list so i import this component from this file and then we can use it here and hence here we can for example output meetup list like this and then set this meetups prop which this component expects and for the moment we can then construct some dummy meetups here later we'll be able to create and store our own meetups in a database for the moment let's use some dummy meetups and that actually should be an array an array of meetup items where every item has an id for example m1 for the first meetup where every meetup then has a title like a first meetup where every meetup then has an image and for this year i'm using an image from wikipedia which is not taken by me but which instead was taken by thomas wolfe to whom i therefore want to give you credits so this image is taken by him and i'll just grab that image here grab the url to that image because we're not going to implement file upload here and use that here as an image url now every meetup should then also have an address because that's another piece of data which we extract in the meetup meetup list component here so we want to have that address field here as well and i'll set this to some address 5 1 2 3 4 5 some city and we can also add a description even though we don't need that yet but i will add it here a description with this is a first meetup and now we can of course replicate this so duplicate this meetup and give the second one an idea of m2 and then name it a second meetup and this is a second meetup and maybe change the address and use a different image as well if you want to i'll stick to the same one and then we can pass this dummy meetups array into this meetups prop of the meetup list component and that's all standard react there is nothing next js specific about that the only next js specific part here is that we're in a special component which is special because it's in such a page of file other than that it's a regular react component and if we now save that if we save this and restart our development server here because it crashed because i had no page content initially if we visit localhost 3000 we should see this on the screen this is not the finished look but this shows that it works and that our first page is loaded successfully and we're using another react component in that page a component which is not a page component that is also worth pointing out and with that we got this page in place let's now also work on that new meetup page and let's make sure we render some content here as well so for this new meetup component we again create a function here a component function like the new meetup page function and of course as before we need to export this so that next.js is able to find this and then we can render our content here now our content in this case should be the new meetup forum component which i prepared in advance which renders a form with some controls with some styles attached using css modules here for styling i'll come back to that in a second that is supported by next js out of the box which is really convenient and then here we get that data we extract that data the user entered with help of refs which is a built in react feature has nothing to do with next js and then we basically call a function which we expect to get on the on add meetup prop and to that function we then pass the collected meetup data so this object with all the collected data and hence now in this new meetup index.js file here we can use that component and we can import new meetup form from going up two levels to leave the pages folder diving into the components folder meetups and then new meetup form and then we can return new meetup form this component like this if we want to now as i just mentioned in this component we do expect that there will be a on add meetup prop which holds a function that we can call and hence we might want to prepare this function here as well we can add our add meetup handler function or however you want to name it and then pass a pointer at this function to the on add meetup prop a pointer and not the result of executing it so no parentheses here because this function should be executed eventually from inside that component when the form is submitted as it turns out here we then get our entered meetup data and we can for example for the moment simply log this to the console and with that out of the way if we go back again we can visit localhost 3000 slash new meetup and we see this form again not the final styling a bit too wide but we see the form and if i open the developer tools here and i enter test and test or here we actually need a url so i will just quickly grab that url which i set up for my dummy data this url i'll grab that and use this here test address and this is a test if we enter this data and we click add meetup we see this object locked to the console so handling form submission works obviously we're not doing anything with that data at this point we're not navigating away and we are going to do all these things later but this again just shows us how we can use pages and also mix regular react components into those pages and with that that's a great start but now we're already facing a couple of issues here we got a lot of missing functionality of course and for example we also have no way for navigating between pages and we have no general layout around our pages every page takes up the entire width we got no header above them and that is probably something we want to change now i did prepare some components here in the layout folder in the components folder that give our pages a general layout and also a main navigation bar which holds some some links some list items with links we just need to use that now this layout component is built such that we can wrap it around other components so that we can wrap it around other content that should be framed by that layout because layout this component uses props children to take what's between the opening and closing layout tags and wrap this component around that content that means that we can for example go to the starting page so index.js in the pages folder and we can wrap meetup list with layout now for this we also need to import layout of course so we import layout from going up components layout layout we can add this import and once this import was added we can wrap layout around meetup list like this and if we do that and save this we get an error that link is not defined now we get this error because in that main navigation component i'm using the link component but i'm not importing it deliberately because i wanted to do this together with you again we learned about this link component and we import it from next slash link and that allows us to create those links however the to prop then should be changed to ref because the link component offered by next js wants this ref prop where we define the destination of that link but with that changed and with that link import added if we now save everything and reload we got this nice navigation bar at the top here and we got a white border around that for that go into your global styles and here in body set margin to zero that's something i forgot for the starting project but if we add margin 0 to body in the global css file then this white border is gone and now we got this frame here and now we can also click all meetups to go to this starting page and click add new meetup to go to this page on this page we are of course still missing the layout though we only have it on the starting page now we want to have it on this new meetup page as well and therefore of course we can also wrap layout around our content on the new meetup page to add the layout here as well but you will probably see that this becomes cumbersome the more pages our application has if we have an application with dozens or maybe hundreds of pages wrapping our general layout around all the page contents so going into all the page components to then wrap layout around the content that becomes cumbersome and that's now where this underscore app.js file becomes important this is a special file which exists in this pages folder out of the box and which you could create on your own as well if it doesn't exist and which should contain content like this this is kind of your root component this my app component which is defined in there and that is just a regular react component in the end this special component acts as the root component next js will render it receives props and uses object destructuring here to pull information out of the props and the information it pulls out there is a component prop and a page props prop these props are passed into this my app component automatically by next js since next js is the thing using that specific component and component is a prop that holds the actual page content that should be rendered so it will be different whenever we switch a page and page props are specific props our pages might be getting and at the moment our pages are not getting any props at all because at the moment we have no source that would provide such props but that is something we're going to change but with that we now know that component here in this underscore app.js file will in the end be the actual page content of our different pages and it will change whenever we navigate from page a to page b now since that's the case we can utilize this underscore app.js file and simply wrap this component here with our layout or with whichever wrapper you have and we then don't have to do it inside of our different page files so we can remove the layout wrapper from index.js here from our home page we can remove that and go back to just returning the meetup list and remove the layout import here and instead go to underscore app.js and then here we import layout from going up one level diving into components layout and then pointing at the layout file and we now wrap this component here with the layout component and that means that our different page contents will be wrapped with this layout component and hence if we now save all files with all those changes now on the new meetup page we also got this layout applied we got the navigation bar we got the extra styling which ensures that the page content does not take the entire width and hence now on all the pages we got this layout and we don't need to wrap it around the different page contents inside of the different page files and of course that therefore is the way more maintainable and convenient approach of applying general components to our application so whenever you have some component or some setting that affects all your pages you can utilize this underscore app.js file to easily add that without diving into dozens of files individually now we got that layout in place before we work on the actual data fetching and sending data to a backend let's work on that detail page we got that show details button here but it's not doing anything right now now the goal of course is to load this meetup id page this dynamic page whenever we click on a single meetup item to be precise when we click on that show details button and therefore we first of all need a link now for this here on meetup item on this meetup item component we want to create a link here and of course we could do this with the link component and this would be the correct way of doing that since this would render an anchor tag but to show you how you could navigate programmatically something we will also need later again when we submit a form and navigate away to show you this alternative i will stick to a button here even though i will say that a link would technically be a bit better but we'll stick to this button and instead i want to create a function here a function which will then navigate us away the show details handler that could be the function name and now we connect this button with the on click prop to this function and in the function we now want to navigate programmatically and we can navigate programmatically by using this use router hook which we saw earlier already so we can import use router again use router from next slash router and we can then call use router here in the component not in the show details handler it's a react hook and therefore the rules of hooks apply and we should only use react hooks directly at the root level of a component function and hence here we call use router get access to that router object and it's then this router object which we can use in the show details handler to navigate programmatically because this router object does not just have the query property which gives us access to all that data that might be part of the url for a dynamic page for example but here we also have methods for navigating programmatically for example the push method this pushes a new page onto the stack of pages and it's the equivalent of using the link component if you don't want a link but instead navigate programmatically push therefore also takes a path to which you want to navigate and here that should be our meetup id because we have this meetup id page here now the meetup id is something we get via props because when we render that meetup list we pass the id prop into the meetup item and therefore instead of this meetup item we can now construct a dynamic path here by using props id so this will lead us to slash and then the specific id of this meetup item again here programmatically we could also render a link and construct the link path dynamically as an alternative but with that if we now save this and we reload if we click show details we get an error because we have no content for this page but actually we see the url was changed correctly and the only missing thing indeed now is the content on this meetup detail page and that's therefore what we're going to add next so for this meetup detail page i'll add a new functional component inside of that meetup id page the meetup details component and i'll then export this as a default whoops like this not meetup list like this and then here we return the content for the meetup details page now here it's of course up to you how you want to display the details for a given item i will output a fragment which we need to import from react so that we can have multiple adjacent jsx elements and i'll then start by outputting the the image of that meetup item with some source and some alt text now of course later we will actually get the concrete data for a specific meetup item here at the moment we don't really have any meetup data source we have this dummy array in the root index.js file but it's only available in there and whilst we could export this constant and then also use it in the meetup detail page i will not do this here because we're soon going to connect a real backend anyways and therefore for the moment i'll just hard code some data in here and i'll grab that data from the dummy data though so from this dummy meetups array and i'll copy the image link here and use that as a source and the alt text could be uh first meet up like this then below that i will add a h1 tag where i say ah first meet up and then below that a paragraph with the meetup description we can also add a address element here which is a default html element where we have the address like that that could be how we output the meetup details for the moment with some dummy data and if i add this here in the meetup details component if we reload this meetup details page this is what we see and that's um okay but of course not the final style which i'd like to have i'd like to center all the text actually and i would also like to shrink the image a little bit now for that i haven't prepared any styles so we can just quickly add some styles together here and for this i'll actually add a brand new component in the components meetups folder which i'll name meetup detail like this and you don't have to create this component i just like to keep my page component files pretty lean and outsource as much js xcode as possible into standalone components but that is not something you have to do nonetheless i will do it here and i'll copy that fragment from the meetup details page component here and add it to the meetup detail signal component and create that meetup detail component here and of course also export meetup detail here and return that jsxcode here then like this and actually accept props already and expect that i get this data through props now so that the data will be fetched in the page component later and will then be passed into this component which is then responsible for actually presenting the content so here we then have props dot image here for alt we could use props dot title what we then also use here for the h1 tag props dot title and here for the address that would be props dot address and here we have the description props dot description and um on the meetup details page component we can now output this meetup detail component we just worked on and for this of course import this meetup detail component up there and now we just need to pass that data which we expect in that component through props into that meetup detail component so here we can then add the image prop and then use our dummy image link or our dummy image content here for the moment set the title prop first meetup could be the title set the address prop to some street five some city and last but not least set the description prop to this is a first meetup and then we can get rid of the fragment and that jsx content in a page component and just use the meetup detail component here now why am i doing that again just to keep the jsx code lean here and now also for styling reasons we could have also imported a css file in the page component this would work it is a regular component after all but i like to keep my pages folder lean and only have the page js files in there now for the other components on the other hand it is quite common that we pair a javascript file with a css file and again we could have done that in the pages folder as well but i want to keep that folder leaner here for the components folder it is more common to include these css files and hence here i'll now also add a meetup detail.module.css file the dot module.css is important by the way we already used it all the time here silently so to say because i provided all these components to you but this actually unlocks a feature called css modules it's a feature which you might know from standard react it allows you to scope css class styles to a react component and it is supported out of the box in next js projects if you name a css file like this endingwith.module.css and you then import it into your javascript file in a certain way which i'll show you in a second then the css styles defined in the css file will be scoped to this component at least if you use css classes as selectors now that special way of importing can be seen in the other javascript files it looks like this we import classes or however you want to name it from the css file and that's a special way of importing which will be picked up by next.js and behind the scenes it will then transform the css classes so that the class names are unique per component and that ensures that your styles can't spill over to other components that's why i also wanted to show you this approach here so now we can import classes from dot slash meetup detail dot module.css like this and now classes is a javascript object in the end where any css classes you define in your css file will be available as properties on this object and if you access them the values will be the transformed css files which are guaranteed to be unique and that allows you to use the same css class names in different components without clashing with the styles and now we could replace fragment here with section and a gifted section a class name of classes dot detail let's say like this and if we do that we can now add a detail css class here in the meetup detail.module css file and the styles we define in there will then be applied to this section because it gets this transformed detail class under the hood and that is a nice feature to have which is why i also wanted to show it to you now with that we can for example select the image which is inside of that element with the detail class so this image we can select this and then change its look change its style for example give it a width of 100 percent which ensures that it stays in the in the box that is reserved for this um page by the layout component we can also select the overall detail class again so the entire section with that class on it and set text align to center so that all the text elements are centered and that could now be our detail page of course you can tweak it you can add more styles you can make sure that it looks the way you want it to look i don't want to turn this into a css course i just wanted to show you this css modules feature and show you this approach which you don't have to use but which i like to use that i keep my page component files relatively lean especially regarding the jsx code and i instead use embeddable standard react components for the actual jsx code and like in this case for the styling and with that we have our detail page in place and now we got all these pages here which we need now with that we can work towards replacing that dummy data source our dummy array here in the root index.js file with a real backend with a real data source now at the moment we are using this dummy meetups array for rendering our list of meetups and on the meetup detail page we just have some hard-coded dummy data and that's not realistic in reality we would have a back-end some database which holds that data now let's simulate that we do and later we'll actually have one but first of all let's simulate that we do have one and in the home page component in this root index.js file let's not pass dummy meetups into the meetups prop like this but instead let's change this component to behave the way it would behave if we would reach out to a backend and how would we typically do this in react well if we want to send a http request once this page is rendered we would typically use the user fact hook to control this so we would import user fact from react and then execute user fact here and have an empty dependencies array probably which means that this effect function runs whenever the component is first rendered but never thereafter and then in here we could fetch our data and we could manage some state for this component with the use state hook which we therefore also need to import from react and then here we could manage our list of meetups let's say the loaded meetups and we have our set loaded meetups state updating function and in usefact we would send a http request and fetch data and then once that's done it would be an asynchronous task of course but once that's done we would call set loaded meetups like this and set the meetups that we fetched from a server as the meetups for this component and for the moment let's just simulate that we fetched the dummy meetups of course they are available right from the start here but let's assume we just fetched them from a server so some promise completed here and we got back the response and now i set my dummy meetups as the loaded meetups and here in the jsx code we pass the loaded meetups so our state into meetup list if we do all of that if we visit the starting page with all the meetups we don't see any difference there when i reload all the meetups are there right from the start because we never really send a http request but technically there is a difference because it is important to note that usefact works such that it executes this function after important after the component function was executed so that means that the first time this homepage component is rendered loaded meetups will be an empty array then this effect function will execute it will then update the state and then this component function will execute again because the state changed and it will then re-render the list with the actual data but we'll have two component render cycles and in the first render cycle the first time this component renders the loaded meetup state will be this initial state this empty array now why am i emphasizing this because if we would fetch this from a back end our users might see a loading spinner briefly which could or could not be the user experience we want to offer but in addition even here where we don't really send a request and where the response in quotes arrives basically instantly even in this case because of these two render cycles we have a problem with search engine optimization if i view the page source you will notice that in there the actual meetup data is missing i got my unordered list here and this unordered list is empty so the items which we see on the screen here these items are missing in the html content in the html page we fetched from the server and they are missing because they are only rendered in the second component execution cycle but the pre-rendered html page generated by next js automatically does not wait for this second cycle it always takes the result of the first render cycle and returns that as the pre-rendered html code and there this data is missing now of course here with the dummy data it is redundant to do it like this but as i said we are basically just simulating that we do fetch this data from our server and then we'll face the problem that next.js does not wait for that data to be fetched to then return the fully pre-rendered page but it returns the result of the first component render cycle and that might be a pretty empty page and that now was a lengthy explanation of the problem we're facing here but it is an important problem and it is important to understand this problem properly but thankfully next.js also has solutions to this problem it has more core features built into next.js that help us with precisely this problem that we want to pre-render a page with data but with data for which we have to wait and we need to tell next.js once we're done waiting and therefore that's now what we're going to explore next how we can fetch data for pre-rendering next js has this built-in page pre-rendering but this built-in process has a flaw if you want to call it like this as i showed you a couple of seconds ago the page that is pre-rendered has basically the snapshot after the first component render cycle as its content and that might be missing crucial data so if we visit some route if some request is sent to some route to this page then there we return that pre-rendered page but we might be missing data here so whilst this is theoretically good for a ceo for a search engine optimization it might not always be but after this html page was received react will actually take over the page is hydrated as this process is called which means that now react will turn this into a single page application and take over control and then this use effect function might be executed data might be fetched and the page might be updated in the browser not on the server not on the pre-rendered page but instead after this page was received in the browser and therefore we then have a fully interactive page or app with all the data we need but if we wanna pre-render a page with data so that this initially returned html code already contains the data we need to fine-tune this built-in pre-rendering process and we need to configure it and for this next.js gives us two forms of pre-rendering which we can use for controlling how the pages should be rendered it has something which is called static generation and it has an alternative which is called server-side rendering and the two might sound similar but they run or the code runs at different points of time as you will learn over the next minutes now we're going to start with static generation because that is the approach which you typically should use but how does it work when using static generation page component is pre-rendered when you build your application when you build the next project so when you build it for production and that's important with static generation by default your page is not pre-rendered on the fly on the server when a request reaches the server but instead it is pre-rendered when you as a developer build your site for production and that means that after it was deployed that pre-rendered page does not change at least not by default if you then updated the data and you know that the pre-rendered page needs to change you need to start that build process again and redeploy again but that might sound worse than it actually is because for a lot of applications pages don't change all the time page content doesn't change all the time and if it should change frequently there are alternatives which i will also show you in a couple of minutes but for the moment let's start with this static generation now as i mentioned by default next.js prepares your pages it by default generates your pages already statically and it by default does that during the build process but if you need to wait for data if you need to add data fetching to a page component you can do so by exporting a special function from inside your page component file and that's important this now only works in your page component files not in other component files only in component files inside of the pages folder in there you can export a function a function called get static props and it has to be called get static props this is a reserved name so to say next.js will look for a function with that name and if it finds it it executes this function during this pre-rendering process so it will then not directly call your component function and use the returned jsx snapshot as html content but it will first of all call getstatic props before it calls the component function and get static props has this name because indeed its job is to prepare props for this page and these props could then contain the data this page needs and that's useful because get static props is allowed to be asynchronous you can return a promise there and then and that's the key thing next js will wait for this promise to resolve which means it waits until your data is loaded and then you return the props for this component function and with that you're able to load data before this component function is executed so that this component can be rendered with the required data now here in get static props you can also execute any code that would normally only run on a server you could access a file system here or securely connect to a database because any code you write in here will never end up on the client side and it will never execute on the client side simply because this code is executed during the build process not on the server and especially not on the clients of your visitors so the code in here will never reach the machines of your visitors it will never execute on their machines now here in getstatic props you can do whatever you want for example fetch data from an api or from a database or read data from some files in the file system like we do it in my full next js course for example but then once you're done with whatever you did to get the data you need you need to return an object here in get static props you always need to return an object here now in this object you can configure various things but most importantly you typically set a props property here and it has to be named props and that then holds another object which will be the props object you receive in your component function here in this page component function this now receives a props object and the object will be the object you set as props here in get static props and there we could have our meetups key in there the structure of this props object is totally up to you which holds our dummy meetups with that those dummy meetups would be loaded and prepared in get static props and then they would be set as props for this page component therefore in this page component we no longer need to manage state we no longer need use effect and we can therefore get rid of those imports here because now we get the data through props and our meetups for the meetup list component are props dot meetups dot meetups because i'm adding a meetups prop down there and that's how we can move the data fetching away from the client to the server side or to be precise to the during the build process side if i now save everything if we reload our page we still see our meetups here but if i now view the page source we see that we no longer have an empty unordered list instead we have an unordered list which has list items with the images and the title and so on so now this is pre-rendered and it now contains the full html code and that's of course also great for search engines then because now data is not fetched in a second component render cycle on the client but initially before this page is pre-rendered during the build process and that's a great plus and one of the main features of next js this data fetching for pre-rendering and getstatic props will be a function you use a lot when working with next.js as you also see in my full course now to fully understand get static props and also see what we can do with it let's quit the dev server for now and run npm run build this is the build command which you need to run before you deploy your next.js site now we are not going to deploy here but running it is still helpful and interesting if we run npm run build here to build that production build to create that production build we see some output here and in this output we see what it did and that it generated some static pages for example four pages to be precise and we see which pages it generated and what we see here is that it generated the root page for slash nothing the dynamic page for a slash meetup id a 404 page which it actually generates for us automatically by default in case we enter a invalid url and the new meetup page and then we got these icons here next to the pages a filled dot and three empty dots if we scroll down we see a legend here and we learned that a filled dot is a statically generated site that's what ssg stands for static site generation which was automatically generated as html and json which is then used for pre-fetching data once the page turned into a single page application the empty dot stands for static generation that's almost the same the only difference is that here we got no initial props so we have no initial data that was fetched and indeed only for the root page we are fetching data because that is the page where we added get static props and that's why we have the filled dot here now we will work on some other pages later to be precise we will work on the meetup id page soon but for example the new meetup page does not need any data fetching there we in the end only render our form and we don't need any data here we don't fetch any data from a server and therefore the new meetup page will always stay a static page with no content so that is fine but we will turn the meetup id page into a ssg page later but for the moment we see that only the starting page the root page is such a statically generated site now with that let's start the development server again and let's think about potential problems we could be facing when using getstatic props and one pretty big problem which we could face in some websites depending on what we're doing is that the data here could be outdated this page as i mentioned is generated during the build process so thereafter we deploy it if we then add more meetups to our database this pre-generated page would not know about them and if we don't add any client-side data fetching we would always just see the outdated meetups here and this could of course be a problem now we can always rebuild our site and redeploy when our data changes and for some websites like personal blogs this is a great alternative because there data doesn't change too frequently but if data does change more frequently there is an extra property which we can add to this returned object and that's the revalidate property when we add this property to the object returned by get static props we unlock a feature called incremental static generation revalidate wants a number let's say 10 and this number is the number of seconds next js will wait until it regenerates this page for an incoming request that means that with revalidate set to some number this page will not just be generated during the build process it will be generated there but not just but it will also be generated every couple of seconds on the server at least if there are requests for this page so that means that this page with revalidate set to 10 would be regenerated on the server at least every 10 seconds if there are requests coming in for this page and then these regenerated pages would replace the old pre-generated pages and with that you would ensure that your data is never older than 10 seconds and therefore the number of seconds you want to use here depends on your data update frequency if your data changes once every hour then setting this to 3600 might be great if it changes all the time one second might be better but whatever you set this number to you will ensure that this page will occasionally be re-pre-generated on the server after deployment so that you don't have to redeploy and rebuild all the time just because some data changed it doesn't really matter to us here especially not as long as we're just using this dummy array but it is an important feature you should know about and that is how you can set it so get static props is a very useful function which you can export in your page components to ensure that your pre-rendered pages contain data you might need to wait for now with revalidate you can ensure that this page is also updated regularly after deployment but sometimes even a regular update is not enough sometimes you really want to regenerate this page for every incoming request so you want to pre-generate the page dynamically on the fly after deployment on the server not during the build process and not every couple of seconds but for every request and if that's your goal then there is an alternative to get static props now i will comment out get static props because it is the better choice here and i want to use it later again but i want to show you this alternative as well and that would be another function which you can export a function that can also be async if you want to and that's the get server side props function just like get static props that is a reserved name which next js will be looking for and the difference to get static props is that this function will now not run during the build process but instead always on the server after deployment now you will still return an object here an object with a props property because after all this function still is about getting the props for this page component and you can still then fetch data from an api here or from the file system whatever you want to do any code you write in here will always run on the server never in the client so you can run server side code in here you can also perform operations that use credentials that should not be exposed to your users because this code only runs on the server and then ultimately you return your props object so here an object with a meetups key which holds my dummy meetups for example now you can't set revalidate here because it doesn't make any sense here this getserversideprops function runs for every incoming request anyways so there is no need to revalidate every x seconds now what you can do in here is you can work with a with a parameter which you'll receive the context parameter you actually also get this in get static props but i will come back to it there later you do get it here in get service at props as well and there in this context argument in this context parameter you also get access to the request object under the rec key and the response object that will be sent back and if you work with node.js and express before this might look kind of familiar to you there you also get request and response objects in your middleware to then work with those and especially having access to the concrete request object can be helpful for example when you are working with authentication and you need to check some session cookie or anything like this this is something which i show in my full next js course it's a little too advanced here but you do have access to the incoming request and all its headers and the request body if you need to and that then might give you extra data or information which you need for the code that executes in get server side props ultimately you then don't return a response by working on that response object here but instead you return this object with the props key which holds the props for this page component function so that is how you then can use get server-side props for preparing that data for your page and if we do use get server-side props here if we save everything if i reload the starting page you see it works just as before and if we view the page source we also see all the data in there again the unordered list with all the list items that works exactly as we learned it but now their page is really pre-generated for every incoming request now which one of the two should you use is get server-side props better or get static props get server-side props might sound better because it's guaranteed to run for every request but that actually can be a disadvantage because that means that you need to wait for your page to be generated on every incoming request now if you don't have data that changes all the time and with that i really mean that it changes multiple times every second and if you don't need access to the request object let's say for authentication getstaticprops is actually better because there you pre-generate a html file that file can then be stored and served by a cdn and that simply is faster than regenerating and fetching that data for every incoming request so your page will be faster when working with getstatic props because then it can be cached and reused instead of regenerated all the time hence you should really only use get server side props if you need access to that concrete request object because you don't have access to request and response in get static props or if you really have data that changes multiple times every second and therefore even revalidate won't help you then get server-side props is a great choice now here for our meetup list though it's not a great choice because that is not data which changes frequently and here i also don't need to work with the incoming request and therefore i will comment get server side props out again and comment gets static props in because with that we can take advantage of the caching and we're not pre-generating the page multiple times unnecessarily now that was a lot of talking about get static props and get server set props but these are two key concepts two key functions built into next.js which you need all the time as you see in my full course for example when we work on that full blog project we use those functions everywhere they are super important and hence let's also use them for the meetup detail page now for the new meetup page as explained earlier we don't need them because here we don't need any data and therefore there is no need to add get static props it's really only there to fetch data for the pre-generated page if that page needs any data and therefore we don't need it here but on the meetup detail page of course we do have data that is needed for the moment hard-coded data but that will change and hence here on meetup details we also want to use get static props or get server-side props now which one is better it depends on how often your data changes and if you need access to the request object and here it's probably fair to assume that the meetup data does not change very often indeed this app doesn't even have a feature for changing the meetup data we can only add meetups but even if it would have a change feature it would probably not be the case that a meetup changes multiple times every second and therefore for the meetup details i would argue that again get static props is better than get server-side props so here we export getstatic props and we can turn it into a async function if we want to use async await and then here we could fetch the data for a single meetup and then we can of course return this object with the props and here we could have our meetup data prop or however you want to name it which could again be a nested object where we then have this data here so where we have that image so we have image set to the string where we have the the id if we need it m1 where we have the title first meetup here where we have the address and that's this address and where we then also have the description here this description that could be the props data which we send to this component function here we'll actually have a slight problem keep in mind that this is a dynamic page so when we reach out to an api to fetch the data for a single meetup we need a way of identifying that meetup we need its id for example now the id thankfully is encoded in the url and therefore we did learn that we can use that use router hook to get access to this router object and then use the query property there that's what we did earlier in this course but the problem with that is that the use router hook can only be used in the component function not in get static props that's not a function where you can use react hooks so we can't get the meetup id from the url with help of use router in here but we also don't need to because you might remember this context parameter which i mentioned i showed it to you on get server side props but i mentioned that it also actually exists on get static props now when we accept it on get static props context will not hold request and response but it will for example have a params key so there will be context.params and that will be an object where our identifiers between the square brackets will be properties and the values will be the actual values encoded in the url so our meetup id for example could be accessed with context.parents.meetup id meetup id because that's the identifier i have between the square brackets and that would then be the concrete meetup id for which we're displaying this meetup i can console.log this here inside of getstaticprops so that we can see that this really works and then it's this meetup id which we could set as id here if we want to expose it to the component function with that if we save this and visit the detail page of a single meetup we get an error though getstatic paths is required now what's this error about getstatic paths is another function next js understands just like get static props and get server side props and get static paths is a function you need to export in a page component file if it's a dynamic page like we have it here and you're using get static props not if you're using get server side props and not if you're using neither get static nor get server set props but it is needed if you do use get static props so in that case you need to export another function here in this page component file and that's the get static paths function and this can also be a async function so that you can use async await in there now what's the deal with get static paths though to understand it let's again think about the fact that with get static props a page is pre-generated during the build process now what does this mean this means that of course next.js needs to pre-generate all versions of this dynamic page in advance for all the supported ids because since this is dynamic next.js needs to know for which id values it should pre-generate the page because how would it pre-generate this page otherwise we get the id from the from the url here great but keep in mind that this is not pre-generated when a user visits this page with a specific value in the url but during the build process so here we need to pre-generate it for all the urls for all the meetup id values users might be entering at runtime and if they enter an id for which we didn't pre-generate a page they will see a 404 error but because that is how it works we need to add get static paths which has the job of returning an object where we describe all the dynamic segment values so all the meetup ids in this case for which this page should be pre-generated now for this this object needs to have a paths key which is an array and in that array you must have multiple objects one object per version of this dynamic page where this object has a parents key that's a must-have which then itself again is an object with all the key value pairs that might lead to your dynamic page so if you have multiple dynamic segments then you would have multiple keys in this nested object here we only have meetup id as a single dynamic segment and hence here in this params object we would add a meetup id key and then enter the concrete value for meetup id for which this page should be pre-generated and if we have multiple possible values like in this case where i have m1 and m2 we would return a paths array with two objects inside of it where the other one uses m2 as a meetup id now in reality you would of course not hard code this as a developer but you would also fetch your supported ids from a database or from an api and generate this array dynamically and we are also going to do that later but for the moment let's hard code it with that if you save that file with get static paths added with this code and with get static props still being in there with that if you now reload we don't get this error anymore instead we get this error regarding the fallback key instead of get static paths and that's another piece of configuration which you need to add in this returned object next to your paths key the fallback key this key tells nextjs whether your paths array contains all supported parameter values or just some of them if you set fallback to false you say that your paths contains all supported meetup id values that means that if the user enters anything that's not supported here for example m3 he or she would see a 404 error if you set fallback to true on the other hand next.js would try to generate a page for this meetup id dynamically on the server for the incoming request fallback is a nice feature because it allows you to pre-generate some of your pages for specific meetup id values for example the pages which are visited most frequently and then pre-generate the missing ones dynamically when requests for them are coming in here however i'll set fallback to false to indicate that i defined all supported paws here now if you want to learn more about fallback and so on i do cover that in greater detail in my full course but the general concept is that we can simply define some paths instead of all paths if we for example have hundreds of pages and we don't want to pre-generate all of them but maybe just our most popular pages and therefore with fallback added now if we save this again and reload now we successfully load the page for this first meetup if i go to m2 that also works but if i enter m3 i get the default 404 page here because i had fallback set to false and m3 is not one of the supported parameters here that's how this works and get static paths therefore is another important function which you need in dynamic pages to tell next chairs for which dynamic parameter values this page should be pre-generated and then again get static props executes for every page so for every meetup id value allows you to fetch data for that meetup and allows you to return props for that meetup and as a side note here where i lock the meetup id we do see that here in this terminal we don't see it in the browser developer tools here the console is empty because i mentioned that this is code the code inside of getstaticprops which runs during build time and when running in the development server it does run for every incoming request but only on the developer server side so we only see it in the terminal of this developer server then and not in the browser that's how getstatic props works for dynamic pages and that's how getstatic paths works and why it is required so now we covered get static props and get static paths and get server-side props and i hope it's clear what these functions do and why they exist they allow us to fetch data for pre-rendering those pages so that we pre-render the pages with the data instead of without the data they might need now up to this point we're only working with dummy data though which is not actually fetched from anywhere instead we have this dummy array or in the case of the meetup id page here actually hard-coded data in that return statement and that's of course not realistic at all instead we do have this add new meetup page here which would allow us to enter data for a new meetup and hence we're now going to finish this app by adding a real backend with a real database where the data will be stored and from which we then fetch it and this then also allows me to show you the last major next js feature which is added by next to your react apps next.js makes it easy for us to build an api a backend api together with our front-end react app in the same project for this we can use another key next js feature called api routes api routes are special routes special pages if you want to call it like this which don't return html code but which are instead about accepting incoming http requests also post patch put delete requests whatever you need with json data attached to them and which then might do whatever you need to do for example store data in a database and then return json data so you could say api routes allow you to build your own api endpoints as part of this next project and they will then be served by the same server as your next app now to add api routes you add a special folder in your pages folder and that's a folder named api and just as the pages folder has to be named pages this folder has to be named api and it has to be in the pages folder then next js will pick up any javascript files stored in there and turn those files into api routes so into endpoints that can be targeted by requests and that should receive json and return json now in this api folder you can then again add javascript files where the file names will act as path segments in the url for example a new meetup js file again now here in the api folder now in those javascript files here you then don't create a react component function these api routes are not about defining rendering or returning react components instead in there we will define functions which contains server side code because api routes will only run on the server never on the client the code in them will never be exposed to the client so we can also use credentials in api routes without compromising them and those functions are then simply triggered whenever a request is sent to this route so to slash api slash new meetup here this would be the url of this file and if a request is sent to this url it will trigger the function which we have to define in this file now often this function is named handler but the name is up to you the important thing is that it's exported so we export this handler function here and this function will receive a request and a response object you might notice from node.js and express.js the request object contains data about the incoming request the response object will be needed for sending back a response now from that request object we can get things like the headers or the request body and also the request method through the method property here this allows us to find out which kind of request was sent and we could for example check if we are receiving a post request here so if the request method is post and we only execute the code in this if check if it is an incoming post request for other kinds of requests we don't do anything so that would ensure that only post requests to this route would actually trigger this code in here then here we can get our data by accessing rec.body the body field is another built-in field which contains the body of the incoming request the data of the incoming request and then we can do whatever we need to do now this here will be the end point for creating a new meetup and therefore it's probably fair to expect that this data which we get contains a title a meetup image an address and a description field after all it's our page our project and our api so we can expect whichever data we need we will then just have to make sure that we send the correct data when we do send a request to this api route later but for the moment i do indeed expect that we get some data out of this data so out of this request body and i'll use object destructuring here and i expect to get a title a image field an address field and a description field so these are the four fields which i expect to get on the incoming request body and then we can store them in a database for example and that's what we're going to do now now as a database i will use mongodb here and to be precise i'll use their cloud offering mongodb atlas which is a fully managed cloud-based mongodb database with which we can get started for free all you need to do is click try free this will then get you to mongodb atlas in the end and create an account for free here so just enter some data about yourself and then get started for free if you do all of that after logging in you'll end up on a page where you can create a new cluster you might also automatically end up in that create a cluster wizard and here you can generally leave all the settings as they are just make sure that you always pick the free tier settings unless you want to pay so for example you can go with aws and the default region here and leave all the other default settings as well especially make sure that you're using the m0 sandbox here i can't select this here because i already do have a cluster created based on that sandbox but if you don't have a cluster yet you should be able to select m0 sandbox and that is the cluster tier you should use then and then just leave all the other default settings and create your cluster again i already have one based on that m0 sandbox here and therefore you eventually should also have one now that's the cluster the mongodb database cluster which we'll use to connect to to then create our database in there and to store our data in there now in order to be able to connect to this cluster there are two things you also have to do here in this mongodb atlas console under network access you have to add your local ip here by clicking on add ip address and then selecting current ip so that your local computer is able to send requests to mongodb and under database access you need to create at least one user with any username of your choice who has to have read and write access to the database like this user here does so that this is a user with which we can connect to this cluster later and once you did all of that on clusters you can click on connect and then connect your application to learn how you can connect to this cluster and here we now actually need to use the nodejs mongodb driver to write code here in our api route that does send queries to this mongodb atlas cluster for this we need to quit the development server and install an extra package with npm install the mongodb package this is the official mongodb driver which makes sending queries to mongodb easy once you installed it you can start the development server again and now this mongodb driver allows us to connect to this cluster and then insert data or fetch data from there for this in this api route file we can import something from mongodb and that something is the client object this is our object which allows us to connect we can execute this code here we can use client and call the connect method here now the connect method wants this connection string which we have here so you should copy that string and then pass this as a parameter here to the connect method now there you need to plug in the username and password of your user so that user who has read and write access which you created and i'll quickly do this without the angle brackets like this now i will have changed my password when you're viewing this so you don't need to try to connect to my cluster you also should replace my first database with any database name of your choice for example meetups but that is up to you now when you do that connect will establish a connection and this is code which you never never want to run on the client side because you would expose your credentials to your visitors which is a security problem but here in this api route it's no problem because as i mentioned before the code defined in here will never end up on the client side so this is a secure place to store credentials now connect does return a promise and hence we can turn our handler function into a async function to use a weight this is possible and supported by next js and then this will give us a connected client eventually now on that client object we can call the db method to get hold of that database to which we're connecting here by the way if that database doesn't exist yet it will be created on the fly and then on this database we can get access to our meetups collection now mongodb is a nosql database that works with collections full of documents collections would be kind of your tables in a sql database and documents would be your entries in those tables so you have collections which hold multiple documents and a single meetup would be a single document the overall collection then holds multiple meetups multiple meetup documents and you get hold of a collection by using your database and then the collection method and the collection can have any name of your choice just as the database if it doesn't exist yet it will be generated on the fly and it could be named meetups as well so it can have the same name as the database but you can also use different names here and now that we got hold of the meetups collection on that collection here we can call insert one which is one of the built-in query commands for inserting one new document into this collection and now the great thing about mongodb is that a document is just a object in the end a javascript object and that now could be an object with title image address and description and since that's the case since that would make a lot of sense we can also just directly insert data so this full data object into our database and hence of course we don't even need to use destructuring here now we would insert this data object into the database now this also is an async operation insert 1 returns a promise and hence we can await this here as well to get back the result of this operation result will be an object with for example the automatically generated id we can console.log result here if you want to now we can also add error handling here to handle the case that connecting failed or inserting failed and i do this in the full course but here let's keep this focused and concise and let's simply assume that it will work you can simply use try catch to wrap this to add error handling if you want to now i want to call client close then to close the database connection once we're done and then we need to use this response object to send back a response because we're getting a request we're then storing data in the database ultimately we also need to send back a response then and we do this with this response object now this works similar to what you might be used to from node express you have a status method which you can call on response to set a http status code of the response which will be returned for example a 201 status code to indicate that something was inserted successfully you can then chain a json call here to prepare the json data that will be added to the outgoing response and here we could for example add a message key where we say meetup inserted but of course it's totally up to you which kind of response you want to return with that however we have a basic api route which will insert meetups into our database and therefore in the next step we can now send a request to this api route from the front end when this form here is submitted so that we actually do trigger this api route and we use that code here sending a request to the api route works just as sending a request to any api to any back and works in react in our new meetup forum component we call on add meetup on props to pass our collected data there and in the end therefore we need to go to the component that uses new meetup form to work with that data and that is our new meetup page there we have this add meetup handler which gets this collected data and therefore it's here where we now want to send a request to our api route and we can send a request just as we know it for example with the built-in fetch function or with a third-party package like axios now here i'll use the fetch function and i want to use async await so i will turn this into async function and await the response here and then we need to insert the url to which we want to send a request now often that is some domain dot com and then some path if it's an external api but here it's of course an internal api which will be hosted by the same server as is being used for serving this page and therefore we just can construct a absolute path here to send a request to the same server but a different path on that server and the path is slash api because it's this special api folder and then the file name so slash meetup and new meetup without the file extension and if you named this javascript file differently here you need to use a different name here as well this will now send a request to this new meetup.js file in the api folder and it will then trigger this function next js will trigger this function for us when a request reaches this path we actually do need to send a post request because we're not doing anything for different kinds of requests and hence here we need to use this second argument which we can pass to fetch to configure this request and for example we can set the method key to post here we then should also add the body the data attached to this request and that has to be a javascript object which carries the data which we want to store in our database a title a image an address and a description field now here entered meetup data which we're getting from new meetup form does have those fields already it has a title image address and description field and since that's the case in the end we can simply pass entered meetup data as a body however not like this but instead we need to convert it to json which we can do with the built in json stringify method then we can also add some headers to make it clear that we're sending json data by adding the content type header and setting this to application json and with that our request is configured and will be sent eventually we then get a response and we can then also get data from that response if we want to just like this as we always do it for responses we get from the fetch function and then we can work with that data but here i'm not interested in it so we'll just log that data if we do all of that if we save all the files and if we ensured that mongodb whitelisted our local ip and that the credentials for connecting to the database are correct if we did all of that we should be able to go back to our forum here and reload open the dev tools and then enter our data here like a first meetup and then i will again grab this url which i picked before and insert this here as an image and then some address some street five some city and this is a first meetup as a description and if i now click add meetup we see this response eventually which is looking good because meetup inserted is the message we're sending back from the api route and if we go to mongodb to our cluster and click on collections there we should then actually also see a meetups database and you might not see the other databases here because i created more databases in this cluster but you should see a meetups database with a meetups collection and in there you should see one meetup with the data you just added and an automatically generated id and that's our api route in action and how we can send a request to it now of course we now probably want to navigate away after we added a meetup and therefore back in the new meetup page here so not the api route but the front-end facing page after we got our response here we might want to navigate away programmatically and we learned how that worked we can use the use router hook and import it from next router therefore to get access to that router object and once we got that here after logging maybe we can navigate away with the push method or here maybe also with the replace method to make sure we can't go back with the back button if you want to ensure that that's not possible here i don't want to do that and hence i'll just push this and then go back to just slash nothing so to the starting page let's say and then with that if we save this and i then enter a second meet up here and the image link again second street two this is the second street if we do all of that click add meet up you see eventually we're navigated away and of course we could also show a loading spinner and do all of that but that's then all just client-side standard react nothing next js specific about it the next js specific part was this api route and as you see that route is now working just fine so it's great that we're now storing meetups here in our collection but of course we're not using those stored meetups if we go to all meetups i still display my dummy meetups the same for the details page here we would now want to fetch data from mongodb as well and of course we could now create new api routes we could create a api route called meetups and in there we add this handler function we connect to mongodb and we then write code that fetches all the meetups and then on the starting page in get static props here we could simply use fetch and indeed next js adds a feature that you can use fetch on server side code as well normally you can only use it in the browser but in next projects you can use fetch in server side code snippets as well and we could then use fetch therefore to send a request to slash api meetups fetch all the meetups and then populate our props with those meetups we could do that but it would be a bit cumbersome sending a request to our own api endpoint here is a bit redundant keep in mind that i mentioned that the code you add here in get static props just as in get server-side props and get static paths will only run on the server or during build time but never in the client so the code in here will also not be exposed to the client so therefore here if you want to fetch all meetups we can directly write the code for doing so here inside of getstatic props or in a helper function which we then execute here so we don't need to send a request to our own api route we can immediately execute the code just here which then avoids this extra unnecessary request which would be sent otherwise so therefore here we can again import client from mongodb and then connect to it here now when you import something here in a page component file and that something is then only used in get server side props or get static props the imported package will not be part of the client-side bundle so you can import code here which will then only be executed on the server and next the js will detect this and not include it in your client-side bundle which is good both for bundle size considerations as well as for security so you can import both server side and client-side code here and depending on where you use it it will be included in different bundles which are independent from each other that's a nice smart feature built into next js and therefore with client imported here we can use it in get static props to again connect and now we can go to the api route and get rid of meetups.js there by the way and in new meetup.js we can now in the end copy this code for establishing the connection getting access to the database and getting access to a collection here we could therefore also refactor this and outsource it into a separate function to avoid copying this but here to be very explicit about which code you can execute where i will copy it and paste it here into get static props with that we do connect here and then once we did connect and once we did reach out to the meetups collection we can use the meetups collection to call the find method there and find will by default find all the documents in that collection it's an async task returning a promise which we can await here because i'm using the async keyword here and then ultimately will there forget our meetups here to be precise we should call to array here after find so that we get back an array of documents then we have this array of meetups and the meetups here which i set in my props could now be the meetups which i'm fetching from mongodb we can then also of course close the connection again once we're done fetching data from mongodb before we return and if we do that and reload this all meetups page we get this error this error is related to the auto-generated id as you can see it's not a string it's this strange object id thing and that turns out to be a more complex object which can't be returned as data just like this therefore what we actually need to do here is the meetups which we're getting from the database we want to map this array so that we transform every meetup a little bit and then we return an object here for every meetup where we have a title which is meetup.title where we have an address which is meetup dot address where we have an image which is meetup.image and where we have our description maybe though we actually don't need this here so we can avoid description for this component because we're not outputting the description anyways on this all meetups page but we do also add an id field not underscore id but just id like this because i'm using just id like this in my front end components and we set this equal to meetup.underscoreid to string and this will then convert this object to a string which is usable and if we convert our data like this and save everything you will see that if we reload the starting page this works and we see our meetups again but that's now actually a list of meetups based on the meetup data we have in our mongodb database not our dummy meetups anymore and i can prove this if i remove my dummy meetups array here if i remove this array entirely from this index.js file everything will still work fine if we reload this starting page so now we are pre-rendering this page with data that's actually coming from a database and all this code will execute whenever this page is pre-generated so not for every incoming request because it's not get server-side props but get static props but therefore during the build process and when we revalidate then this page will be pre-rendered and this code will run again so now we all execute server side code in get static props and i can't emphasize enough that this is a standard way of doing it this code will not end up in the client-side bundle your credentials will not be exposed the bundle will not be bloated this code will execute when this page is pre-generated now for the meetup detail page we also want to fetch data from the database now for a specific meetup that was selected but also for determining which paths should be generated so which meetup ids should be supported because after all we do only have a limited list of meetups with specific ids here so we want to regenerate all the paths for all those ids which we have here and therefore we will again need to connect to mongodb so for this from index.js i will again copy this connection code and again you could refactor therefore if you wanted to avoid duplication and it will import client here from mongodb like this in the meetup id index.js file and then here we can start with getstatic pops in there i want to connect to my database and get access to the meetups collection and then now here i want to get all the meetup data so for this i get my meetups by again awaiting dot meetupscollection.find find gives me access to all the meetups now actually here i'm only interested in the ids and therefore we can tweak find and pass an empty object as a first argument here we could define our filter criteria if we want to not find all documents but filter for certain field values but i do want to find all here hence we use an empty object which means give me all the objects i have no filter criteria but then we can pass a second argument where we can define which fields should be extracted for every document and by default all the fields will be returned so all the field values title image and so on but if we're only interested in the id we can also add underscore id here and set this to 1 which means only include the id but no other field values and with that we're only fetching the ids so we fetch the document objects but they each will only contain the id nothing else now again we should call two array here to convert this to a javascript array of objects and now we got our meetups here and now we can generate the paths dynamically instead of hard coding this array we can use meetups here and then map every meetup item which is a document with an id into an object because paths should be an array of objects where every object has this params key just as we have it down there and then we have a nested object in there where we define our meetup id values and the values for meetup id should now be our ids here so here we can then access meetup so this parameter which map gives us automatically dot underscore id to string like that and now get rid of this array here with that we're generating our array of paths dynamically and as a result if i now save this if we reload the starting page if we click on show details we're taken to the page for this specific object for this specific meetup and you see this cryptic id here which is this auto-generated id mongodb generated for us so that's working but we're not yet fetching the data dynamically here i want to do that as well for this first of all i'll close the connection here it isn't a bad idea to do that once we're done and then i'll copy this code from getstaticpofs and add it here after we got the meetup id instead of logging the id i'll again connect and get access to the collection again we could outsource this into a function if we wanted to and then here i want to get access to a single meetup not to all the meetups just a single meetup so i want to get access to my selected meetup here and we do this by using the meetups collection and then using the find one method find one finds one single document and to find one we need to pass an object where we define how to filter how to search for that document on this object you can pass your field names like title image address or description as keys and then the values for which you want to search as values so we could pass title of first meetup as a key value pair into this object here to find this first meetup where the title is a first meetup now here we don't want to search by title but instead by id so i want to make sure that underscore id the automatically added and generated id field has a value of meetup id so this meetup id which we extract from the params up there this then finds us this single meetup this returns a promise because it's an asynchronous task and hence we should await this and make sure that we added async in front of the function whoops and with that we got the selected meetup eventually and now it's the selected meetup which i return here as meetup data like this and if we do that and save everything if i reload this meetup here it should load successfully and it should display all the data now at the moment the data i'm showing here however is still hard coded in the jsx code and now it's finally time to use our props data here so the actual fetch data in the jsx code as well for this we're exposing the meetup data prop to the component and hence here we should accept props and use that data here so that for image i'm passing in props dot image and for the title we pass in props dot title and so on same for the address that's props dot address and for description it's props dot description and actually not props dot but props dot meetup data dot because we have that meetupdataprop this prop which holds the meetup item the meetup object so we need to drill into that meetupdata object first before we can access image title address and description now once we did all of that there's one other thing we need to do though which i just noticed here for find one i'm looking for an id which is equal to the id i'm getting out of my url but that of course will be a string keep in mind that in mongodb actually our ids are these strange object id things to ensure that we can correctly look for a specific id we need to convert it from string to such a object id thing and for this from mongodb you should import object id like this with a lowercase d at the end and wrap your string with that so down here wrap object id around meetup id and this will convert this string into such a object id object and once that is done we also want to go to selected meetup and make sure that there we convert this id this underscore id field back to a string because otherwise we'll get that serialization error we saw before so for this i'll set meetup data actually to an object where i do add an id field which is equal to selectedmeetup.underscoreid.tostring and where i then add all the other data like selected meetup.title then the address which is selected meetup.address then the image which is selected meetup.image and then also last but not least the description which is selected meetup dot description and with all that done if we now save this if you reload a single meetup page you see the data for that single meetup and that works for all the meetups now and now these meetup detail pages are pre-rendered on the server dynamically with our code being active and with our code establishing that database connection and fetching the data from there now with all our pages finished and with all that data being fetched and used and with us being able to add a new meetup here with that we added all the functionality that i wanted to add to this demo project and with that we also used all those core next js features file based routing api routes and of course also page pre-rendering with data fetching for example with get static props now that this app is finished what's missing well we wanna deploy it we don't just wanna have it here locally on our local machine with that development server but instead we wanna deploy it put it onto a remote machine so that users from all over the world can visit our application now therefore we are going to deploy it but before we do that there is one thing we should also do one thing you should double check for any kind of next js project you're building or for any kind of web project in general and that's metadata which you might want to add to your pages the content is there on our pages we do have the content visible on the screen and that's the most important part of course but at this point we haven't added any metadata if we inspect the rendered html code the head section is relatively empty we do have some meta tags here but we are missing the description meta tag which would be important for search engines i'm talking about the description meta tag which allows you to set descriptions which for example show up on google search here and we're also missing a page title which is why here in the tab title we only see the address as a title and if our pages would show up as search results later we also want a title like in this case here a catamine for my own website so setting such meta tags adding such head elements that is something we definitely also want to do when we build a site and that is something which we want to do here as well and adding such head elements to our pages is thankfully very simple with next js let's start on the index.js page so the home page there we definitely want to set some title and we definitely also want to add a description and to do that we can import a special component offered by next js the head component imported from next slash head this is a component which allows you to add head elements to the head section of your page how do you use it you simply add it to your returned jsx code so here next to the meetup list i want to add the head element the head component and since adjacent jsx code is not allowed i will use the react fragment imported from react here is the import imported from react i'll use fragment to wrap head and meet up list and now inside of these head tags here between the opening and closing head component tag there you can now insert your head elements so all the html elements which you can add in the head section you can add them here like for example the title and then we could give this page a title of react meetups or whatever title we want to have here and actually make sure that this is returned like this if we then save this and we visit our starting page you will notice that now here in the tab title we see that title which i set here and of course we also see this in the page source code there we'll be able to find the title in the head section here it is and we also see that if we open the dev tools and inspect the rendered elements here here's our title as well so that's how we can add a title and that's how we can also add this meta tag which holds the description which will be picked up by search engines like google browse a huge list of highly active react meetups that could be our meta description for this page and that would be the text which shows up when our page shows up as a result on a search engine for example so with that added we now added some metadata some head data to this starting page and we can do this on all the pages on the new meetup page for example i don't just want to return the new meetup form but also add the fragment here import it from react of course and then between the fragment opening and closing tags have our adjacent jsx code to have the head section there and the new meetup form head is of course a component which we also need to import now so import hat from next head like this and now here we can set a title as well like add a new meetup and we can also update the description and change this to add your own meetups create amazing networking opportunities like this so now this is added here as well and hence if we visit the add new meetup page we see our title here and of course in the dev tools we also see this description meta tag here in the head section now last but not least we also want to set a title and show a description if we view a single meetup and therefore we should also go to this single meetup id page and also wrap this into a fragment here and add this head component and bring the meetup detail into this fragment as well and then of course make sure that you import fragment from react and import head from next slash hat like this and then here between the opening and closing head tags we can also add a title and of course here the title will not be a static hard coded title as it is on the other pages where it's always the same title but instead here for a single loaded meetup item on that meetup details page here i actually want to use the title of that meetup as a title for this page so that different meetups have different titles on their pages and hence different meetups showing up on a search engine would show up with different titles and descriptions there as well and making this title dynamic instead of static is super simple after all we are in our regular returned jsxcode snippet block so we can use all the standard react features here and for example output the result of a dynamic expression with curly braces and then output props.meetupdata.title as a title here and then add this meta tag here for the description whoops description and a content of some content and then here make the content dynamic and output props dot meetup meetupdata.description for example or whatever you want to output as a description and therefore we can set a hard-coded description as we do it on the add a new meetup page for example but we can also set a dynamic value as we're doing it here and with that if we save this and reload this page this single meetup page we see that title here in the tab and if we inspect this here in the head section we also see the title and we see this description with the actual meetup description text and now with that we really prepared our page for deployment our website for deployment because with that we make sure that search engines get all that extra metadata and we also show our users some nice titles here as well and with that let's now deploy this site now when it comes to deploying next js apps there are different hosting providers you can use and there are different ways of configuring your project as well you can for example use environment variables for example to hold things like your database credentials i'll not dive into that here i do in my full next js course though but for this example here we'll just keep the credentials stored here in this code and from a security perspective this is fine by the way because this code will never end up on the client it just might be unconvenient to use one and the same database and one and the same user for development and for production but for this demo this does not matter so i'll stick to this approach here and regarding the hosting provider i will use wersel worsel is a great hosting provider for next js applications because reversal actually is a hosting provider by the same team that develop next js so it's really embracing next js and optimized for next js if you want to put it like this and deploying next js applications to worsel is thankfully also extremely simple now what you'll need to do to start deploying is sign up with a git repository provider because with worsel you will directly link your github repository which holds your source code for example to worsel and they will then get your source code from that repository and deploy it for you therefore you need to use github gitlab or bitbucket which are git repository providers to put your code there before you can deploy it with worsel now here i will use github which arguably is the biggest and most popular git repository provider and i already did log in with my account here once you did create an account and log in it's free you can create a new repository and you can give this repository any name you want like next js course demo or anything like this you can also give it a description and then choose whether it should be public or private if it's public everyone can see it everyone can see your code if it's private only people you grant access to can view it and i'll go with private here but either of the options can be correct it simply depends on which kind of project it is if it's an open source project it will probably be public so i'll go with private and create my repository once that is created you need to push your code here now for that you need to install git on your local system and you can get git from git dash scm.com it's available for all operating systems you can download the installer from there and simply walk through it to install git on your system and once you installed git on your local system you can create a so-called commit in your project a code snapshot you could say and then push that commit that repository as a whole actually to github to move your code with your code history to github now i won't turn this course into a git course if you want to learn more about git and github we got a standalone course on that which you can take here i will assume that you have those git basics and that you have get installed now and if you have it installed you can then go back into your local project into your project folder and create a code snapshot a commit as it's called you do this by running git add dot and you can run this if you got git installed and then git commit and then some message of your choice for example ready for deployment though typically you want to add commit messages that describe what you changed but with that i now created such a snapshot such a commit and now we're ready for deployment now that means that now we need to push our code to github for this we can grab this url here which will point to the repository we created and in our local project folder run git remote add origin and paste that url in here now depending on whether you worked with git and github before or not you might want to add your github username here in front of github.com if you did work with github before and push before you probably don't need to do that but if you never pushed anything to github adding this will ensure that you're prompted for your password and that you have a chance of entering your credentials because of course you'll need to authenticate yourselves in order to successfully push to this repository you can't just start pushing to some random repositories which you don't own so therefore here i will now add this origin here and then run git push dash dash all and this will now push our code here now you might be prompted for your password here and you can then enter your github password or use a token for authentication for this to generate such a token you need to go to your github settings and then there go to developer settings personal access tokens and generate a new token here once you confirm this with your password you can add some node here like next js deployment or a more general purpose and then under scopes select repo delete repo and admin repo hook here and then generate a token and now you'll need to copy that token here which is showing up here and enter this as a password when you're prompted for it once you did all of that and you pushed successfully you should see your code in this repository which you just created in the main branch and now we can link this repository to reversal to start deploying now before we do that let me talk about building for production and what versa actually does mersl is a hosting provider which you can not just use for next.js you can also use them for other projects but which definitely is optimized for nexjs so whilst you can host other things there as well and it might be optimized for those other types of projects as well it is definitely optimized for next.js and that means that you can just connect versal to your github repository and versa will build and then deploy and start your project for you so you don't need to run any build command on your own versa will do that for you nonetheless i want to show you what reversal does and therefore i'm back in our local code here and there in package.json we see a couple of scripts which are commands we can execute in this project we worked a lot with the dev script to start this development server and that is the script which we used during local development but we can also run the build script to build our project for production so to optimize all our code minify it and so on and you want to run this if you do deploy it on another host which does not build the project for you so we don't need to do it with versa but you might need to do it for other hosting providers and then once you run this command this will give you a dot next folder which contains some of these optimized files for example this dot next folder will also contain all those pre-generated page files those html files for your pages like the starting page here or the individual meetup detail pages so this is what npm run build will do for you and versa will execute this command on our behalf on their servers so we don't need to do that but if you would host your project on another server which you manage yourself for example you need to run npm run build and thereafter with npm start you can start a production server so now again we have a running server but this is now the production server which you could start on a remote machine which you administer yourself to run the server for your next application and that server therefore should of course stay up and running on that machine to which you deployed your application as long as you want to expose it to the world i will quit it here though now all of that will be done by reversal and the offer let's now go back to worsel and continue with github here and now here we'll need to link github to reversal now you are then prompted to give versus certain permissions give it access to your repositories and i'll do that here and once you did that you can select that repository which we created a couple of minutes ago here and connect it to versal so i'll click import here on that repository now we'll select this personal account here you might be prompted to create an account here and there you want to choose the personal one which is free to use or free to get started definitely check out their pricing pages to learn more about the different options you have there and with that we now can configure how our code should be pulled and how the project should be built and all the defaults here typically should work for you it detected that it's a next.js project the default build and output settings work for us and we could override environment variables here if we would be using any but we aren't and hence we can just click deploy now to ensure that it really works we'll also need to go to mongodb atlas and change something here there under network access you will need to make sure that you allow access from anywhere this ensures that the versa servers on which our application will run will be able to connect to mongodb otherwise this will fail and our data can't be loaded and stored so we need to grant this access we still of course use our credentials for actually establishing the connection but we need to open up that global access to allow wursle and its servers and our code running on their servers to connect to mongodb now it can take a while until this operation is done so let's wait for this and once it's done here we actually see an error that connection failed because i just changed it after starting the deploy but we can simply hit deploy again and start a new deploy which should now succeed because now we did open up mongodb for outside access so let's now wait whether that now starts up successfully here it definitely built our site successfully here that's good and that is looking good now we can click visit and we see our site up and running on versus servers here we can also try adding a meetup here test street five this is a test and see whether that works and it does it might not show up immediately on this page because this page is statically generated and then only revalidated once every second for incoming requests and then it needs to be pre-generated again so even after one second it might not show up immediately but eventually we see our new meetup here and we can't visit it here though we get a 404 error here and that's actually an expected error at this point what's the problem here the problem here is that on the single meetup page we do specify which meetup pages should be pre-generated and we only set this at build time and never thereafter and since we set fallback to false we also ensure that any requests to meetups for which no page was pre-generated before will fail now that worked as long as we didn't add a new meetup and it worked during development because there the get static paths function ran for every incoming request but it now fails after deployment now fixing it is quite simple though thankfully we can set fallback to true or even better to blocking when you set fallback to true or to blocking you're telling next js that the list of paths which you're specifying here might not be exhaustive there might be more valid pages and therefore when fallback is set to true or to blocking next js will not respond with a 404 page if it can't find the page immediately instead with fallback set to true or blocking it will then generate that page on the month and thereafter cache it so it will pre-generate it when needed now the difference between true and blocking then is that with true it would immediately return an empty page and then pull down the dynamically generated content once that's done so you need to handle that case that the page does not have the data yet with blocking the user will not see anything until the page was pre-generated and the finished page will be served and that's the approach i will use here since it doesn't require any other extra work from our site so if we change fallback to blocking we'll not face this problem anymore now we just need to redeploy this and for this all we have to do is create a new code snapshot with git add and then with git commit where we say fixed fallback or something like this and then simply push our branch again push our repository back onto github and the great thing is that next js will actually watch this main branch to which we pushed and whenever it detects a change there it will automatically start building and redeploying as you can see here it's building already again so that's very convenient if you want to update your page and redeploy all you have to do is create a new commit and push it to your connected github repository and that will then automatically trigger a redeployment and whilst it's redeploying your old page will stay up and running but once it's done the new page will take over and hence now this meetup exists here and if we add another meet up here with this image and our test address and some test text if we do this now our change should also be in effect and if we now reload the starting page a couple of times to revalidate it if we now visit this meetup it's created on the fly and this also works and that is also something which i wanted to show you especially combined with that redeployment feature which is also something you should know now there is of course more you can do you can connect a custom domain here and you can also configure more in your project there are more features which you can add as well but i mentioned this before already there are simply more things which you could add this tutorial however had the goal of giving you an overview of the most important features and therefore we're now finished with that and now that is it for this tutorial that's it for this summary about next js now next.js has more to offer there are more configuration options for getstatic props and what you can return there there also are ways of optimizing images with the built-in next image component you can also easily add authentication and add users sign up and log in and log out and manage sessions with next.js all of that is possible it's very powerful and all these are things we're going to take a look at in my full next course this course here this tutorial had the goal of summarizing the core next js features and had the goal of introducing you to next.js and i hope it's now clear what next.js is and why using it might be interesting how it can simplify building complex react apps how you can work with pages here including dynamic pages how pages are pre-rendered and how you can fetch data for pre-rendering with get static props or get server side props that for dynamic pages you also need get static paths to tell next js which specific instances of this dynamic page should be pre-rendered and how you can run your own server-side code in there like here where we are connecting to a database you also learned about api routes so that it's not just about fetching data all the time but that you can include your own rest api as part of this react project and you can add your server site code here your own api code to which you then can send requests from inside your client-side application like we're doing it here for storing a new meetup and that's next.js a super powerful framework for react which adds many nice features which can really make your life easier and which can help you solve problems which you're actually facing in a lot of react projects
Info
Channel: Academind
Views: 233,190
Rating: undefined out of 5
Keywords: nextjs, next.js, nextjs react, learn next.js, next.js full course beginners, nextjs crash course, nextjs full tutorial, nextjs udemy free course, nextjs maximilian, nextjs academind
Id: MFuwkrseXVE
Channel Id: undefined
Length: 194min 16sec (11656 seconds)
Published: Wed May 19 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.