keeping up with the fast paced advancements in Ai and web development is not only necessary but crucial you must stay informed about where the industry is heading and What new technologies are being released in 2013 Facebook introduced react a groundbreaking technology that revolutionized web development and created countless job opportunities fast forward to 2023 and believe it or not the official react documentation now suggests never to use plain react again instead it recommends to build new apps by picking one of the react powered Frameworks popular in the community interestingly the first framework that they recommend is none other than xjs and for that reason I have prepared a special paid resource you can get completely for free the ultimate next.js 13 eBook that covers everything you need to know to become a professional next.js developer this ebook will cover the complete next JS roadmap the essential nextgs Concepts new next 13 features extensive guidance on building scalable projects from scratch and project ideas you can build and deploy to put on your portfolio and get a job this ebook will be the most comprehensive resource we have ever created so it will be a paid premium ebook thankfully the first 1000 people in the waiting list get it completely for free in an upcoming newsletter sign up right now via the link in the description not to miss out if you're wondering whether companies are transitioning to nexjs and whether you should start learning it the answer to both of these questions is a strong yes node.js recently tweeted that they have migrated the node.js website to nexjs for the long term indicating that there is a shift towards using nextgs among companies but that's not all many huge companies such as Netflix Tick Tock twitch Hulu notion Target and even Nike have adopted nexgs to develop their websites the momentum of nextgs is remarkable in upcoming months you can expect to witness an increase in next GS job opportunities like never before therefore this is an ideal moment for you to acquire your next.js skills and show the potential employers that you are prepared and the best way to do that is to build your own modern next 13 full stack application yep you heard that right first we're going to go through the crash course and then immediately after we'll put all of your skills to the test by building this phenomenal application with the popularity of Chachi PT we find yourselves more and more in Need for really specific AI prompts this application allows you to discover and share different prompts so you can search for them create your own prompts delete them check out different people's profiles and much more as I said full stack crud next 13 application that you will build so stay tuned and let's Dive Right In foreign [Music] let me start with a very important first question what does nextgs have that react doesn't in simple words nextgs simplifies the development process and on top of that it optimizes your web applications it does that through its primary features let's explore them one by one first on the list rendering it all begins with the rendering process the primary distinction between reactions and nexgs lies in how they handle rendering you may already know that reactions renders user interface on the client side while nextgs performs server-side rendering however nextgs offers flexibility in rendering options you can choose to render the UI on the client side or the server side according to your needs of course the main question is what is client-side and server-side rendering and which one is better client-side rendering or browser rendering happens on the client's device or the browser when a user requests a web page the server sends a basic HTML document and JavaScript code the browser then downloads and executes the JavaScript code which leads to the rendering of components and finally the display of the website on the other hand server-side rendering involves rendering the web page on the server before transmitting it to the client's device when a user requests a page the server processes the request and renders the components on the server side the server then sends back the fully rendered HTML to the client's browser enabling immediate display this distinction highlights an essential aspect of web development SEO search engine optimization search engine crawlers face difficulties indexing Pages dynamically rendered on the client side as a result the SEO performance of such pages may suffer as search engines may not fully comprehend their content and rank them appropriately by utilizing nextgs this issue is resolved by sending pre-rendered code directly to the client this enables easy crawling and indexing by search engines leading to the improved SEO but now you might wonder why should I prioritize SEO SEO is crucial for optimizing website's visibility and ranking in search engine results by focusing on SEO you can achieve several benefits including increased organic traffic enhanced user experience credibility and trustworthiness and competitive Advantage due to higher search result rankings prioritizing SEO can greatly impact the success of your website and its online presence the second great nextgs feature is routing how do we create Different Page routes in react we have to install an additional package called react router Dom and then create routes in one of the files that's pretty simple right but then how do we create routes in xgs next.js uses a file based routing system which means that the routing is handled by the file system each folder in the app directory becomes a route and the folder name becomes the routes path for example if you have a folder named about in the app directory you can access that page at the forward slash about path isn't that so easy no need for external packages or complex configurations you can create files for the routes you want and immediately open them within your application of course we're going to explore this in much more detail later on once we dive into the build of our own nextgs application another huge nextgs feature is its ability to create full stack applications from nextgs Version 9 developers behind next introduced a new feature called API routes enabling the creation of serverless functions to handle API requests serverless apis in nextgs are a way of creating API endpoints without the need for a traditional server it allows us to build and deploy apis without managing server infrastructure or worrying about scaling your server as the traffic increases with this feature you can create an API endpoint by simply creating a file called route.js in a specific folder within the app directory this file in any route segment of the app directly corresponds to that route API endpoint once again we're going to dive deeper into that once we move to a real project one of the vice presidents of developer experience at versel Lee Robinson mentioned in his blog post that moving from a typical react Express webpack backend to nextgs resulted in removing 20 plus thousand lines of code and 30 plus dependencies while improving hard module reloading from 1.3 seconds to 131 milliseconds which is 10 times less of course in the demo that follows I'm going to show you how to utilize nexgs's full stack capabilities the next feature on our list of awesome nextgs features is automatic code splitting code splitting is a technique that breaks down large bundles of JavaScript code into smaller more manageable chunks that can be loaded as needed that's the key word here when needed this reduces the initial load time of a website and optimizes the user's experience while browsing while we can achieve code splitting in react the process is manual we have to do lots of configuration as your application grows for example we need to use the lazy function from react to dynamically import the about component only when it's needed we also use the suspense component to show a fallback UI when the component is being loaded but in next.js this process is entirely automatic no need for any code it uses automatic code splitting by default to split pages into separate chunks when a user navigates to another page only the code required for that page is loaded resulting in Faster subsequent page navigations so what's the takeaway front-end development has gone through various advancements in areas like linting formatting compiling bundling minifying deploying and many more however to avoid the time spent configuring these tools developers felt a need for a framework that would take care of most of the process automatically leaving them to concentrate on the actual code that's where nextgs comes in automating most of the remaining processes and letting us focus on building the essential business logic of the application and for the end next gs's final advantage it's still just react nextgs is not an entirely new technology it is still fundamentally built on top of react its purpose is to simplify certain tasks allowing developers to concentrate on the core react code nexgs manages a variety of features such as routing code splitting search engine optimization and rendering automatically this automation saves a considerable amount of time reducing the effort required to build a react application from the ground up to put it simply nextgs is an extension of react that streamlines the development process by automating several functions allowing developers to focus on what they do best writing react code in the end it's all react and with that said hopefully you're now hooked for what nextgs has to offer and in the typical JavaScript Mastery style we are now ready to transition from plane Theory to actually building your own simple next.js application with its newest version including all of its primary features think of it as a One-Stop shop for fully understanding and implementing all of these features on your own let's get started now let's set up the project that we'll be working on in this video I'll first provide a practical explanation of all of these features after which we'll immediately begin working on the project to get started you can create a new folder on your desktop and call it something like share underscore prompts because in your app you'll be able to share great prompts that people can use within cha gbt finally open up an empty Visual Studio code window and then drag and drop your empty folder in within your vs code go to view and then terminal this is going to open up an integrated Visual Studio code terminal inside of there you want to type MPX create Dash next Dash app add latest and then type dot slash this will ensure to create your next application within the current repository now you could get a prompt to say hey do you want to install create next app simply press enter to say yes after that it's going to ask you would you like to use typescript on this project let's say no would you like to use eslint in this case we're going to also say no would you like to use Tailwind we're going to say yes we do then it's going to ask you would you like to use the SRC directory in this case we're going to say no and then it's going to ask you would you like to use the experimental app directory with this project in this case we want to say yes because this feature won't be experimental for too long the next JS team has plans to launch it as a stable version in a couple of months so let's say yes hi there Adrian here while I was editing this video next released a new update 14 hours ago next JS 13.4 this version marked the stability for the app router making it completely stable that's gonna include react server components nested routes and layouts simplify data fetching streaming and suspense and built-in SEO all of the features that are included in today's video but I just wanted to say that you will no longer get that question experimental app directory because now it is stable so this is great news keep on going with the video and have a great time and then it's going to ask you what import Alias would you like to configure import aliases are shortcuts that allow you to refer to a module or a file using a custom name instead of its full path this can help simplify and clarify your code especially usually when working with complex file structures so let's simply press enter great and immediately the installation process has begun and the project is now ready as I discussed different features I will revisit this project to demonstrate some parts in action so please follow along first we're gonna do a deep dive into the structure of the next GS application when you explore the files in xjs you will come across the app folder which is the most important folder in our next.js app and then inside of there you will see layout.js page.js and then the globals.css these are the most important files for now the layout JS file is the main entry point of our application and all of the components are wrapped within it as its children as a result any code you write within this file such as a P tag hello world will be displayed on every route page you create this unique file enables you to personalize the behavior of your application by providing a common layout or template for all of the pages any components you include in this file will be shared throughout your entire application if we dive into the next JS documentation on layouts we can see a really simple example that explains what the layout is for it simply takes all the children and then you can play some of the components you want to reuse across all routes in most cases that's going to be your navbar and footer Additionally the layout JS file also allows you to customize the appearance of your HTML document so you can set things like language and you can also modify the metadata for all the pages as well as ADD script tags links or even fonts as it is done in this case in a nutshell if you want to add something that should stay consistent across all routes such as navbar footer or redex toolkit wrapper you should place it in the layout.js file next to the layout we have the page.js file the purpose of the page.js file is that it simply represents the home page route of the application IE it's what you see if you go to localhost 3000 forward slash that is the page you see once you visit in this case it's just a typical boilerplate code and next to the page we have the globals.css that file contains the global CSS styles of the entire application in here you can see that it has been imported within the layout file so that every single route inherits it as you can see in here we have the Tailwind Imports which will help us utilize Tailwind within our application now this page that you can see right here even though it looks like a normal react functional component it is being rendered as something known as a server side component react 18 and next 13 introduced new ways to rendering your components there are two environments where your application code can be rendered the client and the server by default all components created in xjs within the app folder are react server components which means that nextgs leverages server-side rendering to enhance the initial page loading speed resulting in improved SEO and user experience now in case you want to turn that server side component by default into a client-side one you need to add the use client directive to the top of your page to turn it into a client-side component using both the client components and the server components allows us to leverage the benefits of server-side rendering while still utilizing react capabilities for building Dynamic and interactive user interfaces this is an example of a typical server-side component it is a simple component consisting of a navigation bar that has a logo and a search bar it also has some main content with a P tag as you can see there is no use client directive which means that this is a server-side component now as discussed to turn this into a client-side component we need to use client on top whenever you're utilizing state or hooks like use state in react or other client-side Management Solutions it is important to declare the component as a client-side component State Management in react is primarily handled on the client side where the component state is managed and updated within the browser so if you're using any of the react hooks use State use effect or anything similar you need to add the use client on top otherwise you're gonna run into errors now the most logical question you might have for me now is when should I use server components and when should I transform them to client ones thankfully next.jss documentation page answers just that question to simplify the decision between server and client components we recommend using server components default in the app directory until you have a need to use a client component essentially just keep doing what you're doing when you have an error just transform it into a use client component now just below they provide us with a table that explains on when you might want to use server components and when to use client components whenever you're fetching any data like article blog posts or or website data you want to use server-side components whenever you access any back-end resources directly use server side whenever you have any sensed information in the server access tokens API Keys use server-side components and whenever you want to reduce the client-side JavaScript now when should you use client-side components when you have some interactivity or event listeners such as on click or on change in that case make it a client-side whenever you're using use State and lifecycle effects use State use reducer use effect use client side whenever you use some custom hooks that depend on state effects or browser only apis or if you use react class components I hope that this provided you with just a bit of clarity on when you should use server and when client-side components to put it in simple words just let nextgs do its thing out of the box make it server side but then when you want to use some react capabilities like use State use effect or interactivity then simply add that use client string on top it is as simple as that now let's focus on nextgs's routing system all you need to do to implement the routing in nextgs is create a folder corresponding to the desired route within the app folder the name of the folder will serve as the route name for instance let's say that you want to create a forward slash user route simply navigate to the app folder create a new folder called user and then within it simply create a new page.js file within this file you can create a react functional component and this hello user Dev is going to be displayed from localhost 3000 forward slash user it is as simple as that now let's do something more complicated we can delete this user folder and suppose we are developing a Blog application that requires different routes for different functionalities these include displaying all posts in the forward slash post route and then also creating a new post on the forward slash post forward slash new that is something known as nested routing and in reacts GS without nexgs it would look something like this you have to import all of these Pages import react router down create the router and the routes specify the routes that are right on the root route and then you have to create the nested route as well so in this case we have the forward slash posts and then also forward slash posts forward slash new a little complicated isn't it now let's try to create the same structure in next.js all we have to do is Nest folder within each other to achieve this routing let's create a new folder in the app folder called posts there we said we're gonna have a page that displays all posts so we can say page.js render a new react component and then in here we're going to render all of the posts but now what if we want to create a new nested route for creating new posts simply create a new folder within the post folder called new there add a new page.js create a new component and we can say new post it is as simple as that we now have a page that displays all posts and this is going to be rendered at forward slash posts and then we also have the new that's going to be rendered add forward slash posts forward slash new because it is nested within the posts folder I hope this makes sense and as you can see everything is file based meaning that you created the folders and your routing is ready now our posts application kept growing we kept adding new feature and we had the need for something known as Dynamic routing Dynamic routing is like having a flexible system for creating website Pages based on different variables or data instead of manually creating each page for example instead of having just a regular website such as jsmastery.pro forward slash masterclass which is always going to be the same sometimes we're going to need to create Dynamic pages that allow our website to generate these URLs on the Fly depending on what the user wants to visit expanding on the previous example of a Blog application let's say that we want to create a dynamic route to display the details of a blog post using the forward slash posts forward slash post ID pattern this is something that you see incredibly often you might want to have the posts and then blog post one and also blog post 2 3 and so on this is supposed to be dynamic to achieve this in react you would need to do this we have the post shroud the new route as before but now we have the Colin post ID meaning that this is going to render that Dynamic route in the context of nextgs to achieve the same functionality we would take a similar approach of creating a folder but this time we would wrap it inside square brackets that means that we're going to go into posts and within posts we're going to create a new square brackets and then we can call it post ID this means that this is going to be a dynamic ID within the posts folder and then inside of there we can create a regular page.js which we're used to now if we create a functional component inside of this page we're going to have access to that Dynamic post ID variable which means that we'll be able to dynamically render it and show special data once again simpler than it was in react not that long ago I explained how the layout.js file can be used to render Footers or navigation bars in every single page that you have but nexgs has one additional trick up its sleeve we created these new posts routes and the post page what you can do is you can create a new layout dot JS file inside of the subfolders as well in this case posts the purpose of this file is to allow for the sharing of UI components between routes for instance let's say you want to create a new react functional component that's going to have the logic of navigate to Top you know how in most post Pages you want to have that button once you scroll down you want to go back up well let's say that you want to create a component but you want to reuse only on pages that are within the posts folder now you can do that if you put the layout within the posts it's going to be showing the post ID in the new post as well as in all the posts on top of introducing the new layout for each of the subfolders you can now also add a new loader or loading.js file for each one of these subfolders as well the loading is going to look something like this where you can render some kind of a loading skeleton meaning an example of the page while it loads or it can be a general spinner but just you know while this page here is being loaded this loader here is going to show sometimes our websites are not gonna load correctly though so in that case we gotta do some error handling it is essential to handle the errors gracefully by catching them and then presenting meaningful error messages to the client side in nexgs handling errors is also pretty simple similar to the Loading UI file there is a new convention for creating errors the only thing you have to do is create a new error.js the only thing you have to do is create a new error.js file this is going to automatically run when the error happens and it's going to gracefully present the error to the user a typical error file might look something like this you're going to have a use client component because air components must be client components to be able to recognize those errors you can have a use effect maybe to cancel something out or an on click to reset and to bring the user back to where they were before the error and with these couple of special file names we explored most of the new next js13 functionalities You Now understand the structure of a modern xjs application we discussed client and server side components routing and all of these new special files that you can use to your advantage there's just a couple more important Concepts we need to go over before you build your own modern nextgs application one of these important Concepts is data fetching nextgs provides three choices for selecting how to fetch data let's explore all of these one by one first we have server side rendering or SSR by now you should know what this means it means Dynamic server rendered data it is fetched fresh on each request with SSR each request to the server triggers a new rendering cycle and data fetch ensuring that the content is always up to date here is a quick example we have an async function page where we try to fetch some data from the Json placeholder API specifically it is a dynamic page because we get the ID through the params of the page and then with this cash no store it simply means hey don't store it simply call it and then display the title and the body of the fetched post this is going to ensure that it refetches it every single time which means that its server side rendered now to get to our second example which is static site generation the only thing we have to do is remove this cash no store that that means that by default nextgs uses static site generation that means that by default nextgs uses static site generation it will automatically fetch this data right here but it will also cache it this method is ideal for Content that doesn't change frequently such as blog posts documentation or marketing Pages first time it's going to make a Fetch and then it's already going to have the data and it's simply gonna display it the third method called incremental static generation or high Sr for short looks like this instead of messing with the cache we can provide an additional parameter here called Next revalidate 10. it combines the benefits of SSR and SSG for dynamic content in static sites with incremental static generation you can specify certain data to be statically fetched at build time while defining a revalidation time interval this means that the data will be cached but after a specific time frame it's then going to refresh it and you're always going to have new data making this The Best of Both Worlds for the Dynamic content once again we're going to dive deeper into all of these data fetching principles When developing our own xjs application but before being able to develop our application which is going to be a full stack app we of course need to learn how to utilize full stack capabilities within the next.js application and for that we can focus on the serverless route handlers as we discussed earlier nextgs allows applications to be full stack which means running the application both on the front end and on the back end using the same file based routing system nextgs allows us to handle HTTP requests and develop back-end functionality without requiring an external server first of all let's see what do we have to do to make this simple get request route using a regular express.js server we of course have to import all of these dependencies such as Express require them and then create a new app.get route Handler for forward slash API forward slash users we can then fetch or create those users from a specific database and then return them and this is an important part we have to make our application listen on a specific Port because this is a server that always has to be alive to be able to accept incoming requests this example shows you how to create an express.js application Define a route a get route for users and then when a get request is made to this route it executes the code and Returns the users nextgs covers all of the features found in traditional backend servers which includes middleware parsing authentication checks and even serverless functions that simplify the deployment and scaling of API routes before we proceed to the same example route in next.js it's worth noting that there are two different ways to define a round out Handler the first one is to create file based route handlers right within the API folder within the app directory and the second approach is to create a direct route Handler within the app directory itself but there's a caveat with this approach you have to create a special route dot JS file that's going to act as a backend API route but if you want to create a route that's going to start with Slash like our page does these two cannot interfere in the same fashion if you wanted to create an API route for forward slash posts you wouldn't be able to have a route within the posts next to the page because next.js won't know does this have to be a regular front-end page or a backend API route it's going to clash between forward slash posts that's going to render a regular page and forward slash posts that should be an API route so in this case you won't be able to do something like this where we have the app users and then you cannot have the page users with the route users which is unfortunate while this is an excellent feature that enables us to have both the routes and the pages really close to each other I still recommend the first approach of creating the API routes meaning don't create routes right within the app folder rather to keep our code clean and understandable keep all the backend related logic and API endpoints within the API folder this separation makes it clear that right here is the back end of your application and everything else in the app is the front end so the process of creating a simple posts API route would look like this we have a regular API folder inside of which we can create a users folder and there we might want to do a route.js this is now going to act as an API backend route as the error layout loading in the page route.js is also a special file name and just for that reason it allows us to create those back-end routes out of the box next.js supports the following HTTP methods get post put patch delete head and options essentially everything that you need to create an HTTP method inside of the route.js file the process is incredibly straightforward you simply need to write a get function and begin implementing your backend logic within it export async function get and then you return the response as if you're returning it from the regular Express server in the same way and in the same file you can also use all other HTTP verbs now let's return to that simple express.js endpoint that I previously showed you to create the endpoint with the same functionality in nexgs the only thing you have to do is this export async function get you get the users and then you return them isn't that convenient there is no need to set up any extra additional Express configuration just concentrate on what you need to get from specific endpoint think about the business logic and next.js will handle all the other details to witness this specific API in browser what do you think where do we need to go keep in mind it is within app API users route so that's going to look like this HTTP colon forward slash forward slash localhost 3000 forward slash API forward slash users and we have a route that is it a simple straightforward and intuitive as it can be congrats on coming this far of this next GS crash course there's just one more thing you need to learn before you're ready to create your own modern xjs application in which you're going to utilize all of these Concepts together and that is how to improve the SEO of your nextgs applications recently nexjs has also introduced their new metadata API and provided us with two new ways of managing metadata static and dynamic to modify the metadata in a static way you'll have to do something like this you're going to have a regular page the only thing you have to do this is really cool is from the file in which you export that specific page or a route you also now can export a special object called metadata and the only thing you do is say export const metadata and then you provided a title the output is going to be the head element that's going to contain the title of home now to bump that up a notch we can also make use of dynamic metadata that's going to look something like this you're going to have an export async function called generate metadata that's going to get the dynamic parameters of a specific page for example a product ID based on the product ID we can then make a call to the get product function and then as the title of the page we can now return a dynamic title that is equal to the title of that specific product the output is going to be your unique product name this is going to of course improve SEO tremendously and with that we can conclude this next GS crash course but with JavaScript Mastery the end of the crash course is just the beginning of where the real learning Starts Now that you understand the next JS structure client and server components routing layout loading errors data fetching and API endpoints in nextgs you are ready to implement all of them in the application that you will build in this video so without any further Ado let's dive into the project the project you'll build today is called primetopia it is an open source AI prompting tool for modern world that helps you discover create and share creative prompts as you're aware we're using chat GPT more and more every single day so wouldn't it be great to have a list of all the phenomenal prompts that you can immediately pass on to charge EBT this is exactly what we're gonna do an app where you can discover and share AI powered prompts first we can log in using next auth and Google authentication once you're in you can immediately start browsing all of the best prompts the application allows you to search for tags usernames and prompt content too so let's say you want to find something about web development you can search web and there we go you have all the web related prompts also you can search for some tags like coding and it's going to give you access to all the prompts that have that tag in them finally you can search for usernames so if you know that a specific users shares their favorite prompts like JavaScript Mastery you can search for that and be able to immediately dive into their profile from every single card you can immediately copy it to clipboard or if you're the Creator you'll be able to edit a specific prompt as well as deleted essentially primtopia is going to allow you to build a full stack next.js13 crud application so without any further Ado let's Dive Right In to get started with building your own next 13 modern application we're going to start as we always do on the JavaScript Mastery YouTube channel from bare Beginnings by creating a new empty folder on our desktop let's call it pumtapia for prompts of course just a funny name there let's go ahead and drag and drop it into an empty Visual Studio code window once you've done that you can go ahead and zoom it in and go to view and then terminal now we can run the same command we ran before for spinning up our crash course demo application that's going to be MPX create Dash next Dash app at latest and then dot slash to create it in the current repository you can press Y and then enter and then we can enter a couple of prompts we won't be using typescript we won't be using eslint we will be using Tailwind we don't want to create an SRC directory and we can just press enter for the default import alias and there we go it's installing the dependencies and we have our initial application structure just as we had it before now that our base dependencies have been installed we can go ahead and install a couple of additional ones that we're going to use to make this project come to life we can do that by running npm install and then the first one is bcrypt which we're going to use to Hash passwords then we're going to have mongodb for our database and Mongoose which is going to help manage it and finally we have next Dash auth finally you can press enter and the dependencies will get installed after they've been installed you can go ahead and right click the application folder yes the most important folder in our app and completely delete it we're going to start from complete scratch so go ahead and right click in the root of the directory and then create a new app folder with nothing in it next to the app folder we can immediately start by creating the rest of the file and folder structure of our application so not inside it rather in the root directory create a new folder called components this is going to be for our reusable components then we can create a new one called models this is going to be for mongodb Mongoose database models you can delete the current public folder because I'm gonna provide you with a new one really soon so let's recreate it by creating a new folder called public for now let's keep it empty below that we're going to have styles again an empty folder and then finally utils for utility functions we'll be using throughout our application finally one last file is going to be a DOT EnV file our environment variables inside of which we can store secure keys and that is it finally before we start building out our project I compiled a list of assets icons and style this project will use to make the development of the parts that really matter in this app easier so to get started with getting those assets you can click the GitHub gist link down below and you can copy detailwind.config dot JS file it looks like this and you can simply override the existing one that's going to give you access to some font families and colors after that in that same GitHub just file below you can find the new globals.css file so copy the contents of the globals.css create a new file within the styles and simply paste it here you'll see that we just have some useful styling utility functions and some setup of the main div as well as the Imports for the tailwind and for the fonts finally below the GitHub just link there's going to be a link to a downloadable zipped folder that's going to contain all of our assets so simply download it unzip it and then paste it within the public folder it should look something like this public acids icons and then images great that is it it means that we are ready to dive into the app directory and figure out how to start developing our application of course what a better way to start than simply creating a new file within the app called page.jsx it is that new unique file that's going to render our home page we can run refce inside of there to create a react Arrow function and if this didn't work for you there's this cool extension called es7 plus react react native Redux Snippets so just download it and it's going to allow you to immediately spin up react components great with that said in nextgs we no longer need to specify the react import so we can delete that and we can rename this to home great and before we go ahead and spin up our application we need that second really important file that we mentioned during your crash course that's going to be the layout.jsx file inside of there we can also run rafce to create a react function we don't need to import react but what we can import is ADD Styles forward slash globals.css as you can see we don't have to mention the entire path we just have to say add Styles and then reference the Styles within this is going to import the CSS to our entire application also we can immediately change the metadata of our application by saying export const metadata is equal to an object with a title equal to from Tapia and the description equal to this cover and share AI prompts great finally we can wrap everything in an HTML tag to which we can provide a link tag it's going to be in English we can provide a body tag and within that body we can have two different tags the first one is going to be a div with a class name equal to Main and within it we're going to have a self-closing div that's going to have a class name equal to gradient this is just going to change the background finally we're going to have the actual main part of our application that's going to have the class name equal to app and then within it we want to render all the children as we said the layout is going to be wrapped around everything and sticking with the rules of naming react components we can rename this with a capital starting letter something like root layout and of course don't forget to export it wonderful now that we have our layout and our page.jsx which is the actual home of our Prim topi application we can now open up the terminal by going to view and then terminal and we can run npm run Dev this is going to start the server on localhost 3000 so simply control click it and it'll open showing you that it cannot resolve the add styles for slash globals.css no worries we can easily fix that by going to jsconfig.json and then removing this forward slash here this means simply take it from the root route and take everything so once you fix that we can go back to the layout and I also noticed that we're never importing children from anywhere so we're getting them through props so we can simply say children here and if we make that change to the JS config so it looks like this and if we get the children from props right here you can see that we have this home right here and this great looking background wonderful that means that we are ready to start developing the project so to make it easier to develop let's simply drag and drop our browser to the right side and keep our code to the left side there we go we are ready to continue implementing the home page to get started with our home component we can first wrap everything in an HTML5 semantic section tag that section is going to have a class name equal to W Dash full for full width Flex Center as well as Flex Dash coal so the elements fall one below another inside of here we're using something known as Tailwind Tailwind allows you to quickly add Styles simply by writing utility classes for most Parts it's going to be easy to understand what a specific class is supposed to do but if you're unsure of what a specific class means simply go to tailwindcss.com and search for it type w Dash full in this case and you can immediately see that that's going to change the width there we go if you'd like me to create a full crash course on Tailwind comment down below and let me know great with that said we can proceed with creating an H1 a main heading within our section in there we can say something like discover and share if we save it we can see it right here but let's also give it a class name equal to head underscore text and text Dash Center this is already going to make it look so much better and whenever you see underscores that means that this is coming from our own styling within globals.css so if we search for head underscore text you can see all the styles that are going to be applied right here great below are discover and share still inside of the H1 we can create a Break Tag and that Break Tag is going to have a class name equal to Max Dash MD hidden we're going to hide it on large devices but we want to break the content on smaller devices So Below we want to create a span that's going to say AI powered prompts there we go discover and share AI powered prompts of course I misspelled it here and then we can give it a class name equal to Orange underscore gradient and text Center this is looking so much better below that H1 tag we can also add a P tag and there we can say something like primetopia is an open source AI prompting tool for modern world to discover create and share creative prompts great of course we can also give it a class name that's going to say desc description as well as text Dash Center there we go looking much better now immediately below the speed tag later on we're gonna have our feed component for now we haven't yet created it so I'm simply gonna leave a comment right here and we can move on to build the navigation bar of our website so first we want to go to components and create that navbar component as a matter of fact while we're creating that component let's create the file structure for all of the components we'll be using throughout this project so we're going to have something known as a feed dot jsx where we're going to show all the prompts and inside of there we can run rafc e let's create another one called form.jsx and again we can run rafce the third component on our list is going to be our nav.jsx inside of which we can also create a base functional component the next component is going to be the profile.jsx inside of which we can create a new empty function finally we're going to have something known as a prompt card.jsx and the last one on our list is going to be known as a provider.jsx and we can run rafce great now we have provided a way for us to use all of these components from within our code so while we're here let's immediately utilize the feed component inside of our home page and we can do that by importing it at the top so we can simply say import feed from add components forward slash feed next.js makes it so easy to know the path and finally we can call a self-closing feed component right here which is going to just render the word feed that's okay for now as we said now we can move on to the layout jsx inside of which we'll be calling our navigation bar the reason why we're calling the navigation bar from within here is because we want to reuse it across all our Pages which is exactly what the layout jsx is for so inside of here let's import nav from add components forward slash nav and we're going to also import something known as the provider coming from ad components forward slash provider which we're going to use later on for now the only thing we have to do is we have to go above children and then create a self-closing nav component it should appear right here which means that we are ready to control click it go into it and start implementing our navigation bar within our navigation bar we can import something known as a link coming from next forward slash link this is going to allow us to move to the other pages of our application we can also import the image tag coming from next forward slash image which is going to automatically optimize the images for us later on in this file we'll be also using some hooks from react so let's go ahead and import them right away by saying import use State as well as use effect coming from of course react even though we're writing next GS we're still interacting with all of the react functional components and hux finally we're going to import a couple of things coming from next Dash auth forward slash react we want to import sign in sign out use session and get providers these great utility functions are going to make the sign in and the sign up flow incredibly simple finally we are ready to start creating the jsx or the structure of our navigation bar we can get started by turning this Dev into a semantic nav tag and giving it a class name equal to flex Dash between W Dash full margin bottom of 16 or MB 16 for short and PT 3 for padding top inside of there we can create our first link that link is going to have an href just to forward slash meaning the root route and we can give it a class name equal to flex gap-2 and flex Dash Center within it we can show the logo of our application we're going to use the built-in next.js image tag we can make itself closed and give it a source equal to forward slash assets forward slash images forward slash logo dot SVG if we save it you can see fail to compile and immediately we get into that discussion that we had at the start of our crash course you are importing a component that needs use effect it only works in a client component but none of its parents are marked with use client so they are server components by default maybe you should try marking one of these components as use client and that is exactly what we need to do so at the top as we discussed earlier whenever you're using some client-based functionalities such as hooks in this case you need to add a directive called use client and save it immediately that's going to fix our issue but now we have another one saying that the image with Source also needs a width property so let's continue styling our image by giving it an ALT tag equal to primetopia logo a width equal to 30 pixels height equal to 30 pixels and a class name equal to object Dash contain if we save this you can see our great logo appear on top and again I wanted us to get this error saying that we need to use client to show you that it's really that simple whenever you use some client-side functionality next.js is going to let you know hey please mark this component as use client and that's exactly what we did here in the future When developing more next GS applications you will immediately know to add this at the top because you'll be using some states later down the line great now we can continue by below our image adding a P tag that's going to have a class name equal to logo underscore text and it's going to say primetopia now if we expand our browser just a bit you can see it appear here but on smaller devices we don't see it wonderful now below this link we can start by creating the mobile navigation since it's a mobile navigation the div that's going to wrap it is going to have a class name that's going to say on small devices it's going to be Flex meaning visible but usually it's going to be hidden now within here we need to know whether a user is currently logged in or not to know which buttons do we have to show so for now just to Mark the state of a user being logged in or not we can create a new variable const is user logged in and for now we're going to set that to true now we can use this variable right here is user logged in a ternary operator if they are we can display a div and if they're not we can just return an empty react fragment for now great so now since we are logged in at least right now well we don't have any users what we can do is give a class name to this div such as Flex Gap Dash 3 and on medium devices cap Dash 5 and since we are logged in we have a link button to create a new post so we can say create post href is going to be equal to create Dash prompt and class name is going to be black underscore BTN if we save that you should be able to see a button appear on the top right but you'll only be able to see it on desktop devices there we go so inside of here when I said that this is a mobile navigation this is a desktop navigation first and then later on we're going to focus on the mobile navigation so why is it on small devices Flex well because the small devices actually start from this endpoint right here so if we are extra small it's going to be hidden but for everything larger than small we're going to be able to see create post great now below this link we can create a button that button is going to be of a type is equal to button it's going to have an on click which is going to render the sign out function it's going to have a class name equal to outline underscore BTN and it's going to Simply say sign out there we go so we can create a post or sign out and then below that button we can create another link that's going to have an href equal to forward slash profile and it can render an image that image later on is going to render a source of a real user image for now we can simply render images profile.svg let's give it a width equal to I found 37 pixels to work the best height of 37 pixels class name equal to rounded Dash full and I'll tag off profile and it looks like we don't have this profile icon right here let's see if there is something else we can use maybe let's use just our logo right now for the placeholder before we get our real user images so that's going to be images logo.svg there we go later on this is going to be a real user photo from Google Now what happens if we are not logged in Well for now if we switch it nothing's going to happen inside of here we're going to have a button to sign in and to be able to do that using next auth we have to have access to something known as providers so right here at the top we are importing get providers but we're not yet initializing them so what we can do is say const providers set providers is equal to use State and at the start it's going to be set to null so it's going to look like this now how do we set those providers using nextgs is we create a new use effect hook that has a callback function and only runs at the start then we create a function called const set providers which is equal to an async function and there we say const response is equal to a weight get providers so we're calling it from here next auth react once we get the response we can simply set providers to our state equal to response of course our sub provider's function is not getting called anywhere so we simply have to call the set providers here that's going to allow us to sign in using Google and next auth so how do we do it well here we have to open up a new Dynamic block of code and check if we have access to providers so providers and end if we do have access to Providers then we can do the following object dot values to which we pass the providers and then we map over it we get each individual provider as a result of the map and we return a button for each provider so right here a button I know this is a bit confusing but essentially this is allowing us to have all the different providers and show the buttons for the sign up right here of course in our case we'll be using only one provider that's going to be Google auth so we can give this button a type equal to button a key equal to provider.name and then on click property equal to a callback function or we call the sign in and pass in the provider dot ID and of course we can give it a class name equal to Black underscore BTN and make it say sign in if we now save this we cannot see it because even though we're trying to fetch the providers they're not actually there we're going to do this later on once we fully set up the next auth but for now we can just turn this back to the is user logged in is equal to true there we go now of course if we go to the mobile view you're going to be able to notice that this disappears which means that we can scroll all the way down below our desktop navigation and we can create mobile navigation doing that is going to be similar to doing the desktop one we can start by creating a div giving it a class name saying on small devices it's going to be hidden usually it's going to be flex and it's going to be relative here we can again check is user logged in if they are we can render a div that's going to have a class name equal to flex and then we can render the profile icon for now we can copy the previous profile image that we had this time without the link so that's going to be image that's going to have the source equal to assets images logo.svg at least for now later on we're going to also give it an on click property to make it open up the drop down for the mobile navigation bar and we of course also have to settle with the second part of the ternary operator so what's going to happen if we're not logged in in that case we can render absolutely the same thing we rendered here that's going to be a react fragment with the providers and the sign in button so simply paste it right here now we still have two additional errors first it's complaining that our on click is empty so we can provide it with an empty callback function and then we have an extra pair of parentheses right here so if we fix all of that we are good to go but now we have to make this button open up a menu to be able to do that we need a new use State we can create that state by saying use State snippet let's call it toggle drop down set toggle drop down and at the start it's going to be set to false we can scroll all the way down and on click we want to set the toggle drop down to the opposite of its current value when you're changing state in react it is not recommended to Simply say set toggle drop down and then the opposite of the current state it's never a good idea to change react State using the previous version of that same state as that can lead to unexpected Behavior so what we do instead is open up a new callback function within that state where we get the previous state called prev and then we update it by saying not prev there we go so now that's going to set the variable to True based on that variable right below this image we can open a new Dynamic block where we can say if toggle drop down is true meaning toggle drop down and end in that case we can render a div that's going to have a class name equal to drop down inside of there we can render a link that's going to have an href equal to forward slash profile class name equal to drop down underscore link and an on click property that's going to then reset the drop down to false so set toggle drop down is false and there we can simply say my profile now if we save that and click on this icon you can see my profile here now let's add a couple more links we're going to add a link to create a new prompt so we can duplicate this link below pointed to create Dash prompt and we're going to leave the on click to false so it resets the navigation that can say create prompt and finally we're going to have one additional thing which is going to be a button this button is going to be of a type is equal to button it's going to have an on click property equal to a callback function where we set the toggle drop down to false once again and we also want to sign out there we go and the button is going to of course say sign out we can also give it some class names such as margin top 5 to divide it from the content W Dash full and black underscore BTN if we now save this and go back to previous page we can click this menu and you can see my profile create prompt and sign out that is great as a matter of fact that is it when it comes to our navigation bar the mobile nav bar looks and behaves great and also on our desktop this looks great of course it doesn't make sense to have the logo on two sides so the next meaningful step in improving your application could be to make the authentication work so we can truly authenticate users in using Google next auth and then we'll be able to show their profile photo so let me collapse this right here close all of the currently opened files and navigate to one of the components we have created called provider inside of here we're gonna import something known as a session provider coming from next Dash auth forward slash react then we want to be able to get the children and the current session through props and this is going to be a higher order component meaning we're going to wrap other components with it which means that as a return statement we have to use that session provider but then within it we have to render the children and finally the session is going to be set to session in this case we are using the browser's capabilities so we do have to use the client directive on top there we go now in the crash course we mentioned where all the providers go the Redux toolkit query the usually used files and functionalities they all go within the layout component because that way they'll be used everywhere across the app so we can go to the layout we already imported the provider and we can simply wrap everything within our body with the provider component and we can end it right here below our main there we go this is great we're one step closer to implementing authentication but next auth doesn't just use the front-end files within the app for authentication it uses the next GS API backend endpoints as well so immediately this is going to be an amazing opportunity to dive into the API folder within the app so let's create a new folder called API and within it we can create a new folder called auth within the add folder we can create a new folder that's within the square brackets next auth this is the currently accepted best practice and within there we can create a new route.js file so it's an API route with an API auth Dynamic next auth and then we have the route within here we can set up our providers such as Google authentication as I said a wonderful opportunity to dive head first into the use of nextgs API routes or back-end endpoints alongside using the front-end side as well nextgs allows you to do both so bear with me we're gonna have this set up in no time to get started with authentication we can import next auth coming from next Dash auth alongside the next auth we'll also need to import the Google provider coming from next Dash auth forward slash providers forward slash Google there we go now to handle our authentication we can create a Handler const Handler is equal to next auth which we call as a function and then provide the options object within the options object we first need to have a providers array inside of which we can specify our Google provider which we call as a function and provide an additional options object in here we need to have a client ID which is going to be equal to an empty string for now as well as a client secret which we can also leave as an empty string finally we'll have to have some functions so next to this array or below it we're going to have an async session function which is going to get the session as its first and only parameter and right below it we're going to also have the async sine in function which is going to get the profile right here within the parameters finally at the end we can export Handler as get as well as Handler as post this is not something we'll usually do usually we're going to do everything as either a get or a post but for next authentication this is how we have to do it and how it's explained in the official documentation now let's go to the Google's console and let's get our credentials first go to console.cloud.google.com I'm going to make this much bigger so we can see it better from here we need to create a new project so click on the project name or new project on top left and create a new project let's call it primetopia there we go and we can click create as you can see it is being created as we speak so let's give it a second and it's gonna be done there we go let's go ahead and select it it's going to be shown on top left open up the navigation menu go to apis and services and then oauth consent screen click create enter the app name in this case frontopia and your email finally we can add the authorized domain that's going to be localhost 3000 and let's start it with http if you want to you can enter your logo we can scroll down and you can again enter your developer email I'm gonna do JavaScript Mastery and click save and continue finally let's go to credentials create credentials oauth client ID choose the application type as web add the authorized JavaScript origin of localhost 3000 or http colon forward slash forward slash localhost 3000 and then add the authorized redirect URI as well we can do the same localhost 3001. and click create this process can take about five minutes but we can immediately see our client ID and client secret right here so let's go ahead and copy them and go to that dot EnV file we created before first you can paste the Google underscore ID is equal to and then the Google client Secret is equal to to the secret that we have right here I just closed it but hopefully we can get back to it there we go copy it and paste it here of course don't use my credentials create your own within the console.cloud.google.com great with that said we should be able to reload our application just to be sure that the environmental variables got updated and then we can utilize those client ID and client secret variables right within our Handler we can do that by saying process.env dot Google underscore ID as well as process.env that Google client Secret great just to be sure these variables are being passed properly we can counter log an object containing the same exact thing to see if we indeed are getting them so now if we go back collapse this open up the console and reload the page you can see that we don't get anything but inside of here we do keep getting them and we get them every couple of seconds which is not good so for now I'm gonna stop our client from running in our terminal and then we can make sure that we only call this when it is necessary but a good thing to know is that the client ID and the client secret are there we at least know that we're getting our client ID and the client secret which means that we can proceed with the development of our next auth route so let's focus on creating this session and sign in functions first to be able to get the user session we of course have to sign the user in so what we can do is we can create a new try and catch block now keep in mind every nexgs route is something known as a serverless route which means that this is a Lambda function that opens up only when it gets cold so every time it gets cold it needs to spin up the server and make a connection to the database that is great because we don't have to keep our server running constantly but we do have to actually make a connection to the database so for that reason we're going to go to our utils and within there create a new file called database.js which we're going to use to connect or hook it up to our database from within here we can import Mongoose coming from Mongoose we can also create a variable that is connected is equal to false at the start this will allow us to track the connection status finally we can export const connect to DB which is going to be an asynchronous function and inside of here we can create a connection to the database of course first let's set up the Mongoose that set strict query this simply sets the Mongoose options if we don't do this we're going to get warnings in the console so I always recommend setting strict query to true after that we can check if we are currently connected so if is connected in that case we can console log DB is already connected and we can return out of this function to stop it from running if we are not already connected we can open up a new try and catch block and we can try to establish The Connection by saying a weight Mongoose dot connect and then in here we have to enter the URI of our mongodb Atlas instance or the URI of our actual database that's going to be stored inside of the process.env dot mongodb underscore URI and then we have to provide the options object within the options object we have to enter the DB name which is going to be something like share prompt and we can pass additional options such as use new URL parser set to true and use unified topology set to true and if this executes correctly we can set the is connected variable to true and we can say console log mongodb connected finally if we have an error we can simply console.log that specific error now of course we don't yet have the mongodb URI or the database we want to connect to to be able to save those users so what we can do is head to the mongodb atlas which is an online cloud storage to create your database so let's do that right away you can head to mongodb.com forward slash Atlas and click try free sign up with Google or simply sign in once you're in you should be able to see something that looks like this if you don't already have a cluster created you can go ahead and click create move from dedicated to shared and then click create cluster it's completely free once you create your cluster go to database access and ensure that you know the password to your account if you don't know it simply edit the password right here once you know the password to your account also go to network access click add IP address and you can add your current IP address but there should also be a button to add zero zero zero zero which is going to include all IP addresses which means that this is going to be accessible from anywhere in the world which is what you want to do great now that you know your password we can go back to database click connect and then click drivers there you can copy your mongodb URI once you have it go back to your application go to your dot EnV and create a variable called mongodb underscore URI and make it equal to to this query of course ensure to change the password to the password that you have under your specific user once you've done that you can go back and we are done with the connection to the mongodb database which means that we can go back to Route and we can make use of that function we just created we can do that by scrolling to the top and importing connect to DB within the curly braces from add utils forward slash database and now right here in the sign in the only thing we have to do is say await connect to the B and call it as a function now there are two things we'll have to do here or two checks we'll have to make the first one is check if a user already exists and the second check is if not create a new user and save it to the database finally once we successfully sign in we can return true or if we don't sign in successfully we can simply console log the error and then we can return false since we don't already have any users we'll have to create a function to create one and add it to the database that we just connected to great so to be able to do that we first need to create something known as a model based on which the document of the user will be created so that's going to happen in the models directory inside of which we can create a new file called user.js inside of here we can import a schema a model as well as models plural and that's going to come from Mongoose which is helping us interact with the mongodb database so let's go ahead and create the schema by saying const user schema is equal to new schema we're going to call it as a function and pass in the options object there we want to make sure that the user has an email so email is going to be of a type is equal to string unique is going to be set to an array where the first element is true and then the actual message if it fails so if it's not unique we're going to say email already exists same thing for required it has to be required and if this fails we're going to say email is required now we can repeat the procedure for the username it's going to be of a type string it's going to be required as well so required true and then username is required and finally we're going to add a match meaning it has to match a specific regular expression so down in the description below in the GitHub gist you'll be able to find the piece of code for the match this is a regular expression that says that the username is invalid it should contain 8 to 20 alphanumeric letters and B unique finally below the username we're going to have the image that's going to be of a type is equal to string and that is it that is our user now usually if we're working with a regular Express backend we would say something like const user is equal to model user and we pass in the user schema and finally export default user we would do this if we were working with a regular always on always running back-end server but in nextgs it's a bit different we said that the route is only going to be created and running for the time when it is getting cold so there is one check we have to make the models object is provided by the Mongoose library and stores all the registered models we're referring to this thing right here so it stores all the models that have been previously registered if a model named user already exists in the models object it assigns that existing model to the user variable this is going to prevent us from redefining the model and ensure that the existing model is reused so essentially alongside just creating a new model we can say first look into the models.user see if it's there and only if it's not there then create a new model that's because this route gets called every time and the connection is established every single time from scratch so we have to make this additional check great now we have the model for our user so we can go back to the route and we can import it at the top by saying import user with a capital u from add models forward slash user finally going down we can check if a user already exists by saying const user exists is equal to a weight user dot find one and we'll try to find it by email so we can say email is equal to profile dot email finally if a user does not exist we can check if not user exists in that case we want to await user dot create and we want to create a user by passing in the email which is equal to profile.email the username which is equal to profile dot name dot replace a space with no space so essentially we want to make sure that it has no spaces and we also want to ensure that it is lowercased so we can say two lower case and finally we're going to pass the image equal to profile dot picture and this is going to allow us to create a new user if one does not already exist great so now we have the sign in function which automatically also creates a new user in the database finally we want to be able to get the data about that user every single time to keep an existing and running session so what we can do is say const session user is equal to a weight user dot find one where email is equal to session.user dot email so we're getting the current one from the session and we want to update its ID by saying session that user.id is equal to sessionuser dot underscore ID dot to string which we call as a function and then return that session so we are updating it making sure that we always know which user is currently online and with that we're done with the route that's going to handle our entire authentication process if you're still unsure of why we did specific things in the way that we did them such as creating this Handler next auth importing these things or even exporting them in the way that we did definitely ensure to check out the next auth documentation just go to next Dash auth.js.org go to getting started and in here you can see the entire procedure for everything we did from installing next auth adding the API route and then all the other functions and things that we did as well inside of here if you go a bit deeper you can see how to create the next jsr callbacks such as the session one we created right now but you can also see that we need to configure specific callback URLs and later on we'll need a specific variable for deploying to production the documentation says that we need a couple of different environment variables for this to work so go back to the dot EnV and create three new variables next auth underscore URL which you can set to http colon forward slash forward slash localhost 3000 next auth underscore URL underscore internal which you can also set to localhost 3000 and then the next auth secret later on in production we'll be able to Simply change those and make the authentication work with our deployed link the last thing is the next odd underscore secret so what is this random string well if we go to the options part where they talk about secret they said that this is a random string used to Hash tokens so how to create it simply go to your terminal and type open SSL in there with a Rand base6432 if you're on Windows you most likely won't have this already installed so you can simply copy the command and then go to the following website I found the openssl terminal where you can simply paste this value press enter and it's going to give you a string which you can then copy and paste in your environment variables great with that said we are ready to test out how our authentication works now to test it out let's open up the terminal clear it and run npm run Dev now that we have all the newest environment variables and the new code it's going to run it on localhost 3000 as soon as we run it we get an error saying the top level of weight experiment is not enabled set experiments dot top level await to true to enable it so to be able to do that go to files next dot config and down in the description in the GitHub gist that you visited before you can find the code for the entire next dot config.js so simply override it there you'll be able to find some experimental features Servo components external packages for Mongoose and the top level of weight which we need to make this work finally before trying to run it one more time let's go back to models user.js and then inside of here I noticed that instead of new schema we should have run new and then schema like this so this is just one typo that I noticed that we can fix and we are now ready to run our application so let's go ahead and run npm run Dev for hopefully one final time to see what are we gonna have server is running on localhost 3000 and it compiled successfully great open up the menu and for now we're just mocking the state of not being signed in so let's go to our nav and here at the top we can now pull the real data from the session instead of simply saying is user logged in we can use this next on hook use session to be able to get the current user data so let's do just that the only thing we have to do is say const inside of curly braces data and we can rename it to session is equal to use session based on this information whenever we use some fake data such as here is user logged in we can now say session question mark dot user so we're checking if a user exists and we also have this down below or rather above on our desktop navigation bar right here session question mark dot user immediately the app should figure out that we're not currently logged in and it should allow us to do so I can see that we are missing a mobile navigation bar which is not good if I expanded we're missing the entire thing all together so let's figure out why is it not showing first let's go ahead and just alert session question mark dot user to be able to know what do we have in there so just alert so we don't have to open up the console and it says undefined which is as it should be because right now we don't have the user so we know that this is going to be false so we won't be able to create a post or sign out but we should be able to go here and sign in so let's also go ahead and alert the providers object because if we have it then we should be able to sign in so right here I'm gonna alert the provider's object and we can see it is null which is not good so let's figure out why are we not getting our providers the providers themselves are coming from here get providers and we have set providers where we set the response but it looks like it's not being used and that's because I called this function in the same way I called our use set state so we definitely have to change that I'm gonna rename this function to something like set up providers and then here we can just use the regular set providers sorry for the confusion there as you can see naming these functions is incredibly important that now gives us access to our providers which means that we get our sign in button on the top so let's go ahead and click it and we can see access blocked this app's request is invalid and that's not a problem because we can see a meaningful error right here it says error 400 redirect URI mismatch and if we dive deeper into the next odd documentation we can see that there is a get post API auth callback and then provider State this is something we have to add to the Callback of the Google Cloud console so let's go ahead and copy this specific URL go back to the API console go to web client under oauth to client IDs and then if you scroll down you can see authorized redirect Uris simply click add URI add HTTP colon forward slash forward slash localhost 3000 API auth callback and then not provider but rather it's going to be Google and you can click save again whenever you're using a framework the difference between a framework and a library is that the framework makes things a lot easier for you but you have to follow its rules so it's important to know what you're doing by reading the documentation of these great tools that are at our disposal now if we go back and try to sign in one more time now it works and you can see all your Google accounts appear choose an account to continue to primtopia I'm going to choose JavaScript mastery and just like that I think we're logged in because we have my profile and create prompt but now they're finally logged in let's get rid of this logo and show a real profile icon we can do that if we go to our navigation bar and here under images right now we have assets images logo but we can replace that with a real icon so that's going to be coming from the session question mark that user dot image if we save that you can see JavaScript Mastery or in this case your own Google icon which means that we are successfully logged in and if I'm not mistaken we also have to change this on desktop so let's try to find it there we go link to the profile that's going to be session question mark.user dot image if we save that our mobile is looking great and if we expanded we can see it on the desktop too that means that we have successfully set up the next API authentication route that allows us to create an account using Google so we have successfully combined the front-end part of nextgs the backend part as well and hopefully we hooked it up to the database as well of course we're yet to check that part so let's go to our database visit our cluster and then go to collections we named our database share prompt but in here I just have my old application called booking that means that neither our database nor the user That was supposed to be in it were created so let's go back to application and figure out why that is the case I didn't even see any console messages right here whether we are connected or not it is almost as if the connect to DB function was not getting cold at all and if it were not getting cold then that means that this block of code was not executed and it looks like I made a tiny mistake when working with next odd Handler you have providers and then you have something known as callbacks this right here was supposed to be an object containing the callbacks and then the async function session and sign in were supposed to go within it so I'm gonna copy them and put them right within the callbacks like this we have providers comma callbacks and then we have a callback called sign in so now it should actually get executed so let's go ahead and test it out by signing out one more time signing in once again there we go we are locked in we got mongodb connected which is great and if we go to our mongodb cloud and if we try to refresh the data we can see that we have a new share prompt database with the user's collection and with one document inside of it which is the username JavaScript Mastery containing the image exactly what we have right here now what was the reason for us creating the actual database if we were able to log in even without it to save prompts and attach them to specific accounts that way we'll be able to check out different accounts and different profile pages of different users so that finally allows us to dive into the create post functionalities therefore showing the prompts on our feed great work on coming to this part of the video we've already laid a phenomenal foundation for us to be able to go into the app and creating our second page which is the create post so we can right click the app create a new folder called create Dash prompt and inside of it you already know what we need to do is create a new page.jsx inside of which we can create a react Arrow function component here we can simply call it create prompt and for now it can say create prompt now if we go ahead and click create post that's going to navigate to create prompt and immediately that's it our route is ready just by us creating this specific file also keep in mind that our entire layout was inherited that means that our navigation bar is immediately showing right here how easy it is using next 13. so creating a prompt page is going to be our next step to get started with creating our create prompt page we're going to import a hook called use state coming from react and as soon as we import a hook we immediately know that we have to turn this into a use client directive page great alongside the use State hook we're gonna also import the use session hook coming from next Dash auth forward slash react this is going to allow us to know which user is currently logged in and finally we can import the use router hook coming from next forward slash navigation inside of the create prompt we're going to also import one component called form coming from add components forward slash form so immediately we can start by returning just one element from this create prompt page and that's going to be a reusable self-closing form component to our form we're going to pass a couple of things first we need to know about this state are we currently submitting the form so we can say use State hook and we can say submitting and set submitting at the start set to false and we can also create a new use state this time it's going to be called post set post and at the start it's going to be set to an empty object containing a prompt set to an empty string as well as a tag set to an empty string as well finally we're going to create a function called const create prompt which is equal to an async arrow function that accepts the event and for now we can leave it empty now we have access to all of the variables which we can pass to our form the first one is going to be the type of a form and that is going to be create in this case then we can pass the actual post equal to post we're going to pass the set post equal to set post the submitting state equal to submitting and then finally the handle submit State equal to create prompt this now allows us to copy all of these fields I'm doing this by holding the ALT key and double clicking the words and then I can simply copy them and control click into the form and accept all of these as props so we can nicely structure them right here in one line there we go and we can see them here so our form is accepting a type a post set post submitting and handle submit so we can immediately start working on it if we go here to our website we can see that we have only one element which is right now A div containing the word form inside of our form we're going to just need to import something known as a link coming from next forward slash link our form is going to be a section that section is going to have a class name equal to W Dash full for full width Max Dash W Dash full Flex Dash start as well as Flex Dash call for column inside of there we're going to have an H1 that H1 is going to render the type and then it's going to say post so the type in this case is create because we're passing that through props so it's going to say create post we can also give it a class name equal to head underscore text as well as text Dash left great now this type post it's wrapped in an H1 but we can also wrap it within the span element so right here we can say span close the current text and we can give it a class name equal to Blue underscore gradient and this is looking just a bit more custom below the H1 we're going to have a P tag and we can give it a class name equal to d-e-s-c for description text Dash left and Max W Dash MD for maximum content width inside of there we can say type and share that's going to be create and share amazing prompts with the world and let your imagination run wild with any AI powered platform great finally we can go below our P tag and create our actual form the form is going to have an on submit property that's going to be equal to the handle submit which we're passing through the props and it's going to have a class name in this case it's going to be mt-10 for margin top 10 to divide it a bit from the content W Dash full Max w-2xl Flex Flex Dash column so the elements appear one above another gap-7 for the spacing in between and finally glass morphism this is a special class that's going to give us this classy look within the form we want to have a label component that label is going to contain a span element and that span is going to say your AI prompt there we go of course it's not yet styled so let's go ahead and give it a style or rather give it a class name equal to font Satoshi font Dash semi bold text Dash base and text Dash gray-700 this is going to make it look just a bit better finally let's add a text area for this label so that's going to be text area it's going to be a self-closing component that's going to contain a value equal to post dot prompt it's going to contain an on change equal to a callback function where we get the event and we want to update the post by saying set post is equal to an object where we first spread the entire post value and then set the prompt to be equal to e.target.value because this is going to update the prompt of the post we also have to update the hashtag later on let's also give it a placeholder equal to write your prompt here let's make it required and let's give it a class name equal to form underscore text area if we save this we'll be able to have our post finally we can duplicate this entire label below and then the second label is going to be for the field of the prompt we can say prompt field or we can simply say tag so a tag that explains where this prompt could be used we can also create a span within a span that's going to kind of explain what it is so we can say something like hashtag product hashtag web development or hashtag idea and so on just to give you an idea and we can give this span a class name equal to font normal if we save this there we go and then we also have to provide a space right here there we go so we have the AI prompt and then we have the tag now this is not going to be a text area it's going to be an input because it's only one tag we can put the value as post that tag we can put the own change as equal but we just have to change the prompt to tag right here placeholder is going to be hashtag tag like this it's going to be required and it's going to be form underscore input if we save this we have a great looking form that looks great on mobile devices right now as we can see it but it also grows to be a great desktop looking post finally we need a button to cancel it or to post it so below this label we want to create a new div that's going to have a class name equal to flex Dash end margin X meaning left and right of three margin bottom of 5 and then gap of 4. inside of there we can have a link and that link is going to say cancel of course every link has to have an href so we can set the ahref to just forward slash meaning it's going to go back and the class name can be text Dash gray-500 and text SM or small there we go we have a nice cancel button there and below the cancel button we can also create a new button that's going to be of a type is equal to submit it's going to have a disabled property so if we are currently submitting it has to be disabled the button itself can check whether we are currently submitting and if we are we can say type so if it's edit it's going to be edit dot dot or if it is create it's going to be create dot dot dot else we can simply render the type which means that it's going to say edit or create right now we have create wonderful now we can also style it a bit by giving it a class name equal to PX of 5 padding horizontal py of 1.5 that's going to give it a bit of padding text Dash SM for small bg- primary Dash Orange rounded Dash full and text Dash white and we have a great looking call to action button this means that if we actually try to submit it it should work but it will not yet even though the form is fully complete so we have the form component done and you'll see how powerful this is because we'll be able to reuse it later on but for now we can go back to the page see how our form looks like right now but the functionality is not yet done so we simply have the create prompt which right now doesn't do anything to make our create prompt function work first we have to call the E dot prevent default this is going to prevent the default behavior of the browser when submitting a form which is to do a Reload in react and xjs applications we want that more native feel we want the least amount of reloads as possible so we definitely want to put that here after that we want to turn on the set is submitting to true because we can use that as some sort of a loader later on and then finally we want to focus on creating our first prompt so to do that let's create a new try and catch Block in the catch we have the error and how do we do it well we have to call some kind of an API right so we can say const response is equal to a weight Fetch and then we want to pass the API we want to call we're going to call the API that we will create it's going to be under forward slash API forward slash prompt and then forward slash new and we can pass the options object where the method is going to be post and then the body that we're going to pass in is going to be json.stringify an object where we're gonna pass the prompt equal to post dot prompt we're going to pass the user ID equal to session dot user dot ID we have to check if we do have the session and then finally it's going to be a tag post dot tag so we're passing all of this data that we have right here in our front end to this API endpoint using a post request then we want to check if response dot OK in that case we can simply call router dot push to forward slash meaning home page in the catch we want a console log the error to see what's happening and then we can also add a finally clause which is going to happen either way or set submitting to false there we go great so the front-end part of creating our app is done we have this API call put in place but now is the time that we create our API endpoint and for this you would need a separate backend developer back in the old days you would have to create a new backend Server Express routes controllers and all of that good stuff but now you can do that immediately keep in mind this is the API you want to call I taught you how you can create your own API endpoint in the crash course of this video this is what we need to do go to your Explorer go within the app and then API folder create a new folder within the API folder called prompt now you should have two you should have auth and prompt please ensure that is the case and then within the prompt we want to create a new folder called new and within the new we want to create a new file called route.js so if you open it it should say Here app API prompt new and then the route so if we expand it it's going to look like this finally we talked about how to create a new route the only thing you do is say export const specify the route type in this case it's going to be a post route make it into an async Rec and res function and that's it you write your code right here in this case we immediately get some things through first we want to grab the things that we have passed through the post request and we can do that by saying const user ID prompt and tag is equal to a weight rec.json like this and I don't even think we'll need to use the rest in this case finally we need to connect to the DB so what we can say is we can say import use that utility function we have created called connect to DB and it's coming from at utils forward slash database then we can open up a new try and catch block where we can await connect to DB once we are connected we want to create a new prompt but unfortunately we didn't yet create the model for the prompt so let's go ahead and do that right away by going to models and creating a new prompt dot JS file as before we can import mongoose as well as schema model and models coming from mongoose then we can say const prompt schema is equal to new schema we call it as a function and pass in an object we want to specify the creator of a specific prompt it's going to have a type equal to Mongoose dot schema dot types dot object ID so the Creator is going to be a document in the database more specifically the user type and now that I look at it we don't have to import Mongoose as we already have the schema right here now we have to create a reference ref is going to be to the user so it's going to be a one-to-many relationship one user will be able to create many prompts next we're going to have the prompt itself which is going to be a type of string and it's going to have required set to true but we also want to have a message that's going to say prompt is required finally we're going to have a tag for one specific prompt that's going to be of a type is equal to string required is going to be set to true and we can say tag is required at the end we can do the same thing with it with the users by saying const prompt is equal to either get the prompt that already exists on the models object by saying models.prompt or if it doesn't exist create a new model that's going to be called prompt based on the prompt schema and we can export default prompt great now are Mongoose and mongodb know how the documents in the database should look like which means that we can go back to our new prompt route and we can import right here prompt coming from add models forward slash prompt then like we created a new user we can create a new prompt by saying const new prompt is equal to new prompt we pass in the Creator which is equal to user ID as well as the tag there we go just to make it more readable we can do it in a new line we pass the Creator and the tag finally we want to call a weight new prompt dot save to save it to the database and then we can return new response with a capital R where we're going to stringify Json Dot stringify the new prompt and we can specify the status of 201 I'm going to now expand this just a bit further so you can see it in one line This is how an API route in nextgs looks like you can immediately extract all of the data that you passed through the post request and I can see we're not using the most important part which is the prompt so I want to add that right here to the new prompt we connect to the DB we have to do this every time because this is a Lambda function meaning it's going to die once it does its job so every time that it gets cold it needs to connect to the DB do its thing and then go in peace finally we created and then we return a new response and specify the status of 201 which means created if we get an error then we can return a new response that's going to say failed to create a new prompt and it can be a status of 500. means server error great now the functionality to create a prompt is done which means that if we reload our page we should be able to test it out let's try to think of a good one to start off something like you are a professional web developer I'm going to provide you with a snippet of code and you can give me advice on how to make it cleaner more readable and more efficient this is if I may say so myself a pretty good prompt there we go so this allows us to share this prompt and even if I hover it my grammarly just wants to sound more personable to the AI so why not we're not gonna say I'm going to give it we're just going to say please give me some advice on how to make it that way great we gotta be careful what we're saying to the AI but hey this is now a great looking AI prompt and I'm sure other people uh maybe yourself later on when you use this app are going to find it useful because you can type this into your chat GPT and you can get value out of it and the tag can be maybe hashtag web development and let's click create I click create but not a lot has happened let me open up the terminal and click it again still nothing so let's go ahead and check the create button that's going to be within our form inside of our form the form is submitting we call the handle submit which would pass through props to the form so now let's go to the create prompt and we are passing our create prompt as handle submit right here and then if it's successful we should be able to push to the home page but that doesn't seem to happen right now so let's go ahead and open up the console and we do have an error session is not defined so inside of here we're using the session to connect the currently logged in user to that prompt they're creating but we haven't yet imported it and we also haven't imported the router either so this is a rookie mistake from my end what we can do is we can get the router by saying const router is equal to use router like this and then we can get the session by saying const beta rename it as session is equal to use session now unfortunately I lost my grade prompt so I'll have to write something similar again so bear with me I'm going to give you a piece of code and you tell me how I can make it cleaner more readable and more efficient and we can use a tag web development create there we go we are back on our home page and apparently nothing seems to have happened because our feed is currently empty which is completely normal because if you think about it if we go all the way to our home page we are rendering the feed component but the feed itself is nothing so if we have successfully created a prompt our next job is going to be to display it properly so we can now go to our database and reload it to check whether we have really created a new prompt in the database and it appears as we have there we go I'm going to give you a piece of code tell me how to make it more optimized web development created by this specific object ID it starts with 645 and if I compare it with my user account it also starts with 645 so we know that is working and we have a one-to-many relationship wonderful finally we're gonna see how all of these crowd operations come to life once we now make a get request to get all of the prompts to show in our feed so that's going to be our next job to start creating our feed we're going to first import the use State as well as the use effect hooks coming from react and immediately turn this into a client component then we're gonna also import one and only components we'll use in this file and that's the prompt card component coming from dot slash prompt card and with that we can immediately start with the jsx part of our feed so we're going to turn it into a section that's going to have a class name equal to feed inside of there we're going to have a form that's going to be for the search of our feed and that form is going to have a class name equal to relative W Dash fool for full width and flex Dash Center immediately inside of the form we're going to have a self-closing input tag that's going to have a type is equal to text it's going to have a placeholder equal to search for prompts or rather let's say search for a tag or a username so we can search whatever we want we're going to give it a value which is going to be something like search text this is a state we'll have to create an on change equal to handle search change this is a function we have to create it's going to be required and it's going to have a class name equal to search underscore input and then also peer like this now if we save this it's going to give us an error saying that we don't have that state declared so immediately we can create a new use State at the top that use state is going to be called search text and set search text at the start set to an empty string and we can also declare that handle search function so const handle search change which is going to get an event and it's going to look like this for now and immediately we have a great looking search just below it we can render our prompts which is what actually matters and right below we of course want to show our prompts so we can render a new component called prompt card list this is going to be a self-closing component which is going to accept data for now can be an empty array and it's going to accept a handle tag click which for now can be set to an empty callback function now this prompt card list is a component that's only going to be used within this specific feed so we can create it right here above our functional component const prompt card list is equal to an arrow function that accepts the data and handle tag click and it's going to immediately return a div that div is going to have a class name equal to mt16 for margin top and prompt underscore layout if we save this we should be able to see nothing in here but now we actually can map over the data and show some cards but of course we first need to fetch the data so from our feed we'll have to make a get request to our own nextgs API to do that we can create a new use effect and we're going to have a callback function and we want to call it at the start initially as soon as the page loads there we can create a new function const fetch posts is equal to an async function where we get the const response by saying equal to a weight fetch forward slash API forward slash prompt then from the response we can get data by saying const data is equal to a weight response.json and then we can update our state with all the posts by creating a new use State field called posts set posts at the start set to an empty array and Below we can say set posts is equal to data the fetch post function for it to actually do anything so we can do it right here within the use effect great that should update our posts which means that we can take those posts and pass them instead of this empty array into the prompt card list as prompts great and it's not going to be prompts it's going to be posts so my bad right here now we have those posts passed over as data so we can take that data in our list and say data.map we get each individual post or prompt however you want to call it and for each one we want to immediately return a self-closing prompt card component to that component we want to pass a key equal to post dot underscore ID we want to pass the actual post itself and we want to pass a handle tag click function now the reason why we're still not seeing anything is because even though we're calling this API endpoint we haven't yet created it but thankfully you know how easy it is to do that using nextgs so we know we need API prompt and it's a get request so let's just go to our API prompt and immediately inside of here we can create a new route.js not within the new but just within the prompt there we'll have to import the same things as we did here that's going to be the connect to DB and prompt so we can copy those and paste them here then we need to say export const get is equal to an async function where we get the request and we can call a try and catch block immediately in the try we have to connect to our DB by saying await connect to DB and then we have to filter out our prompts and we can do that by saying cost prompts is equal to a weight prompt dot find we can find all posts and then we can populate the Creator in there as well to know who created it finally we have to return a new response passing the json.stringify and we can pass the prompts and return a status of 200. we can do a similar thing for the error by saying simply a string right here failed to fetch all prompts and it can be a status of 500. if we save this is going to compile successfully and we can reload our page and there we go a prompt card appeared that means that it is that easy to create and fetch the data using xjs the only thing we have to do now is go into the prompt card and actually display the prompt alongside the user that created it to do that we can first make this a use client component because we'll be using some states we can import the use State hook coming from react we're gonna display an image so we can import the optimized image tag coming from next forward slash image we can also import the use session coming from next auth react and finally we're going to import some new things such as the use path name alongside use router coming from next forward slash navigation we already know that our prompt card is going to accept some props and these are going to be the post as well as handle tag click later on once we show this card we'll also be able to delete it and edit it so we can immediately accept those as well handle edit and handle delete and we can dive into creating the jsx of our card by wrapping everything in a div and giving it a class name equal to prompt underscore card that should change the look a bit well not yet because it's empty so let's create an inner div that's going to have a class name equal to flex justify Dash between items Dash start and gap-5 we're just creating some space for the items that are yet to come inside of there we can have a div and that Dev is going to contain the image of the author that created it so it's going to be a self-closing next.js image tag with a source SRC equal to pose.creator dot image it's going to have an ALT tag equal to user underscore image a width of about 40 pixels and the height of about 40 pixels too and we can make it rounded by giving it a class name equal to rounded Dash full and object Dash contain if we save this you can see JavaScript Mastery created one and only prompt that we have so far now we want to make this card clickable or at least the profile clickable so we can give this div a class name equal to flex-1 Flex justify Dash start items Dash Center gap-3 and cursor Dash pointer to indicate that it is clickable now below this image we can also render a div that div is going to have a class name equal to flex and flex Dash call and there we want to show the person that created it so we can give it an H3 and there we can render the post dot Creator dot username and below that we can render a P tag that's going to have post.creator.email if we save this you can see JavaScript Mastery and JavaScript mastery00 gmail.com so now let's style these a bit further by putting them in a new line and giving the h3a class name equal to font Satoshi font semi-bold and text Dash gray Dash 900. that's looking a bit better finally let's give a P tag a class name equal to font enter text Dash SM and text Dash gray-500 to indicate that email is less important than the actual username now this does look a bit big but that's because I'm on 125 Zoom so if I do it like this it's going to look more like it now below this div and Below one more div we can create a div for the copy button in the actual prompt so the class is going to be class name copy underscore vtn and on click we can render just a callback function for now which is empty later on we're going to implement the real logic inside of here we want to show a button to copy that actual prompt that's going to be an image that's going to have a source equal to now it's going to depend whether the post has been copied already and for that we'll have to have some kind of a state so scrolling up we can create a new state use state called copied and set copied at the start set to an empty string so if we scroll down we can check if copied is triple equal to the current pose.prompt if that is the case in that case we can render the assets icons tech.svg and then else we can render assets Icons copy SVG so that's going to give us this icon and of course we have to give it a width of 12 and height of 12 to be able to see it there we go so later on once we implement the logic once you click it you'll get a confirmation that you actually copied whatever is in the prompt wonderful now below this div and Below one more div we're going to create a P tag this P tag is going to render the post.prompt the most important part and below that we want to render another P tag that's going to render hashtag post dot tag web development oh I added a tag immediately in the actual tag so I have a double tag now so in this case I can remove it from here now let's style this a bit better by giving this a class name equal to my-4 to divide it from the top and bottom by giving it a margin Satoshi text Dash SM text Dash gray-700 okay this is looking a bit better and we can style the tag by giving it a class name equal to font enter text SM blue underscore gradient and cursor Dash pointer there we go finally we can give it a non-click as well because later on we'll be able to click on a specific tag and see all related posts so that's going to be a function that's going to check if the handle click exists and if it does we can handle tag click and we want to pass in the tag we want to click pause that tag of course the handle click is also supposed to be handle tag click so what is this going to ensure it's going to ensure that we do have the tag if we do we'll be able to click it and then we'll show all the relevant similar tags great and this is it this is everything we need for now later on of course we'll add the ability to edit and delete post if it's being shown on the profile but for now we're just on the home page and we just want to read everybody's great posts and maybe even copy them so while we're here let's also implement the copy to clipboard functionality for that inside of the copy we can call the handle copy function and above we can create it it is as simple as saying cost handle copy is equal to a error function and then we can set copied to pose that prompt so we're going to update it we want to do a navigator dot clipboard dot write text and we want to pass the post.prompt and then we want to reset the state by giving it some timer set timeout with a callback function that's going to reset the set copied after about 3000 milliseconds or about 3 seconds so if we now save this and click it you can see a check mark and it is actually copied to clipboard which means you can paste it somewhere more specifically in your chat GPT to immediately make use of this prompt wonderful with that two of our four crud operations have been done the create post which we can do right now by going to here and create prompt and read all prompts so create and read now what's left to do is update and delete and we'll be able to add update and delete once we Implement our own profile right now the profile is just a 404 but as you know in nextgs it is so easy to add a new front-end route we can do that by going to app and then simply creating a new folder called profile inside of which we can create a new page.jsx and run rafce and we can call it profile same thing for the component in the export as soon as we do that and reload the page you can see our new profile and the shared navigation bar great let's start with the profile page to start off we can immediately turn this component into a use client component because we're going to import use State as well as use effect hooks coming from react we're gonna also import the use session to know whether we are currently logged in and we're gonna get that from the next Dash auth forward slash react and finally we need a router to navigate back to home so we can get the use router hook coming from next forward slash navigation finally we're gonna also create a special profile component which will be able to reuse later on so that's going to be import profile from components forward slash profile and make sure to add the add sign in front immediately on our profile we'll be able to render that self-closing profile component which we are about to create it's going to contain a name we want to know whose profile are we seeing and that's the primary reason why we're creating this separate component because it can be my profile but it can also be somebody else's profile so in this case the name is going to be my my profile later on I'm going to show you how to reuse this component to create somebody else's profile then we have a desc or description we can say something like welcome to your personalized profile page below we can have the data which is going to be an array of our posts we're going to have the handle edit functionality to edit the post and we're going to also have the handle delete functionality to handle the delete of the posts so let's create those functions right now so we can pass them over to that page to be able to create them we first need the const handle edit is equal to a function that looks like this and then we also need the const handle delete in this case it's going to be an asynchronous function that we're going to use later on so now we can pass the handle edit as well as the handle delete to our profile component now for the data we have to fetch the data and we already have the API endpoint to fetch it but we have to modify it just slightly because now we don't have fetch all the posts like we do on the feed we want to fetch only the ones belonging to this specific profile so first of all let's fix this error by renaming our component to my profile just so it doesn't clash with the component name so we have const my profile here and then the profile at the top and then also the handle delete it looks like I misspelled it so if I fix it we should be good great now as I said we can reuse what we had on the home page or rather in the feed page so if we go into the feed here we do fetch posts so we can copy this entire use effect go back to my profile and paste it here const fetch posts is async response await fetch API but this time we want to go to users forward slash and then we want to make this a dynamic template string where we're gonna search for session question mark dot user dot ID forward slash posts so we only want to get the post from that specific user and of course for that to work we have to get that session so we can say const data rename to session is equal to use session there we go so we're getting that data and we of course want to create our posts and we can do that by creating a new use State called posts set posts which is the start going to be equal to an empty string and then we are updating the data right here and then when do we want to fetch posts well we only want to fetch them if we have the session question mark dot user dot ID so we only want to fetch them if we have the user we want to fetch them for that is great and then we can reference the data equal to posts right here now of course we haven't yet created the API endpoint for this route but it's going to be really similar to fetching all posts so we can open up the file explorer go to the API create the new folder called users then we can create a new Dynamic route of ID and then within it we can create a new folder called posts and within it we can create a new route.js that route is going to be incredibly similar to a regular get all posts route which is going to be within the API and then where is it it's within prompt route there we go so this is just a regular get route we want to take that paste it right here and modify it to fetch the posts only from a specific Creator so through this request we're going to also pass some additional params right here those params get populated if you pass Dynamic variables into the URL such as this one right here so if you look into the route you can see that we have the ID as the dynamic parameter which means that we're going to have access to something known as two params dot ID as simple as that right so where do we want to use it well in the find right here we want to say creator is equal to params.id and this is only going to get us the posts from that specific Creator that's great and with that our route is done what we can do is go back to this page our fetch Works our functions work and we can move into our reusable profile component to get all of these parameters and show a profile page so let's control click it and start implementing not the profile page but the reusable profile component inside of here we can also import The Prompt card we created before coming from dot slash prompt card we can get all the props that we passed such as name description or DSC data handle edit and handle delete and we can create it by first wrapping everything in a section and giving it a class name equal to W Dash full we can immediately have an H1 right here that's going to say name and then profile in this case that's going to be my profile because we are on our own home page so let's save that reload the page and it still says profile even though we are on the localhost profile so let's see why that is the case if we go into our routes we can see that we have a profile and then the page which renders the name as my profile and there we render the H1 but I don't see an H1 here so I am a bit confused it does seem like I have a typo right here but if we open up the terminal it does seem like we have an error handle delete is not defined that is at my profile so if we go to my profile right here we have a handle delete and it seems to be defined properly so you know what let me just simply restart the terminal and start it one more time even the best next js13 sometimes maybe make some mistakes so let's check it out whenever you're getting something that doesn't seem right just restart the terminal just to be sure so we're going to wait until it is compiled and we're gonna check it out then and there we go we were right it's saying my profile now which is much better so we can continue working on it by giving it a class name equal to head underscore text and text Dash left now even though I saved it it didn't seem to have applied the changes so I'm guessing there is some kind of a change with this profile component Let's see we are importing that profile from that slash components profile and then displaying it right here but the changes are not live saved which is really weird so even if I start typing something like test right here and save it it does say compiled but on the profile page the changes are not actually there this is really interesting could it be that I wasn't signed in so maybe it wasn't giving it let's check it out I'm gonna sign in one more time and I'm gonna go to our profile and still as you can see it doesn't say this that's right here even though I saved the file so sometimes next 13 can be buggy it still is in the better version depending on when you're watching this video but even though there are these little bugs I still believe it is the future with all the new features we discussed today it's great so what can I do is I can develop this page fully and then we're going to restart the terminal to see the changes this H1 or specifically the text within the H1 is also going to be wrapped in a span element so we can put it right here at the end and give it a class name equal to Blue underscore gradient below that H1 we can also have a P tag that's going to render the description and it's going to have a class name equal to the ESC text Dash left and finally we have to map over the cards I think we can do that by copying the feed so if we go into the feed into the prompt card list we just need to get this div that goes over the prompt cards so we can copy that prompt card list div and paste it right below the P tag that's going to give us a div we want to modify the margin top a bit to 10. we want to map over the posts pass over the key and the post but this time instead of handle click we're going to have the handle edit functionality which is going to be equal to if handle edit exists meaning handle edit and end then we want to call the handle edit function and pass in the post and we want to do the same thing for handle delete where we have a callback function where we check if the handle delete exists and then we call it by passing a specific post now this is going to be it for the profile component which means that I can now close it go back here and I can restart our server and hopefully the changes are applied right now and we're going to have the live reload working for the rest of the project and there we go we can see my profile welcome to your personalized profile page but unfortunately we don't see our actual post so how can that be well it seems like we aren't signed in so if I press sign in one more time and then go to my profile we can see the post by JavaScript Mastery which corresponds to our currently logged in user that is great now we can add the remaining crowd functionalities such as handle edit and handle delete to be able to do that we need to go into the profile and then into the prompt card because now we're passing two new additional functions so inside of the prompt card if you scroll all the way to the bottom below the P tag we can check if we have a session question mark.user.id and if that is equal to to the post.creator.id and if the path name is triple equal to forward slash profile and only then do we show a div with those buttons so what are we doing here we're checking if the currently logged in user is the creator of that post and if they are on the profile page if that is the case we can show a div that div is going to have a P tag that's going to say edit and we can have another P tag below that P tag is going to have a class name equal to font Dash enter text Dash SM green underscore gradient and cursor Dash pointer to make it clickable but more importantly on click it's going to handle edit and now we can duplicate this B tag one more time below rename this to delete rename the function to handle delete and change it to instead of green gradient to Orange gradient if we save this you can see that we don't have access to the session right here which means that we have to import it at the top so as we usually do we can say const data rename it as a session is equal to use session and we also need to get the current path Name by saying const path name is equal to use path name and we also want to get the router by saying const router is equal to use router now if we scroll all the way down we should have everything we need so if we go back to the home page and revisit our profile you can see that we have a profile card but we don't seem to have the two buttons that we just created that's because the creator doesn't have an ID they have an underscore ID as that's how node.js saves those buttons and now we can see the two buttons appear right here let's just position them a bit better by giving this div a class name equal to mt5 for margin top to divide them from the tag a flex Center a gap-4 to divide them from each other border Dash t for top order border Dash gray Dash 100 and then padding top of three and now we have edit and delete now if we go all the way back to where we're passing that original handle delete function that's going to be in the profile but more specifically in the profile page so we are yet to add the logic and the functionality for the handle edit and handle delete functions before we implement the front end for these let's go ahead and add the API endpoints that we can then call for edit it's going to be inside of API prompt and then we have to know the ID of the prompt we're working with so that's going to be the dynamic ID parameter and then within it we can add a new route.js that route is going to have three different types of requests it's going to have a get to be able to read that request it's going to have a patch to be able to update it and then finally it's going to have delete to delete it so for the get we can go to our prompts and then simply copy everything we have right here to speed up the process and then paste it right here we get two different Imports which we're gonna need later on and then we get the export const get in this case we do have that extra parameter of ID so right here as the second parameter we can get the params object we can have a try block connect to database and then instead of prompts we want to get one individual prompt that we want to find by ID so find by ID and then we want to pass in the props or rather params.id if a prom doesn't exist so we can say if no prompt we can then return a new response of prompt not found status 404. otherwise we can return a json.stringify prompt and then a status of 200 else a 500. this is our get to be able to read one specific prompt finally we can collapse this because we're going to need two more we're going to say export const patch is going to be equal to an async function where we get the request and we get the params then we want to get the data we passed for the update we are going to pass a prompt and a tag and then we can get those by saying await request.json we're going to have a try and catch block one more time first things first we want to await connect to DB so we want to connect to the database first afterwards we want to find the existing prompt so const existing prompt is equal to a weight prompt dot find by ID and we can pass in the params.id once again if a prompt doesn't exist so if no existing prompt we can return new response prompt not found status 404. once for sure we have a prompt we can update it by saying existing prompt dot prompt is equal to the new prompt that we passed through params and then we can also update the tag by saying existingprom.tag is equal to tag once we have updated it we can simply await existing prompt dot save and then we need to return a new response by stringifying the existing prompt and passing over a status of 200. if something goes wrong we can return new response fail to update the prompt with a status of 500. the endpoint for the update is done as well feel free to pause this video and ensure you got everything right the file for the route is also going to be in the GitHub just down below so if you have any typos you can simply copy and paste it to ensure that everything works and finally we have the delete route delete is not going to be that tough we also have to export const delete that's going to be an async where we get a request and we also get some params I think you can start noticing the pattern once you know how things work you can get the hang of it and you can build anything you want if I just did that crash course that you watch at the start you would know that these Concepts exist but you wouldn't know how to do them but now that you've done this building a real crowd application you can actually put it in practice for your own future applications or at least refer to this video to be able to build it and that's exactly what we teach in our JSM masterclass experience it is a six month boot camp where we teach you how to become a software engineer and we have a crazy guarantee where I say if you don't manage to land a job within six months of graduating you're gonna get 100 money back no questions asked so we're that sure that I can help you become a great developer so if you like these videos just imagine what you could get with real mentoring by real expert mentors such as myself and everybody else that's helping to build these applications for YouTube great with that said we can proceed with the delete route it's going to be a try and catch block first we want to await connect to DB as we always do then we need to find the prompt by ID and remove it so there's a special function a weight prom that find by ID and remove all in one and we need to pass the params.id finally we can return a new response saying prompt deleted successfully and we can return also a new error if it fails failed to delete prompt status 500 and with that we have created three additional endpoints that we can now call from the front-end side of our application wonderful now we can get back to our page and we can continue calling these endpoints right from the front-end side of our code crazy enough hold from the same full stack development environment called next.js before we weren't able to do that now we can so let's handle the edit first the only thing we want to do here is not edit it immediately we want to navigate the user to a page where they can edit it in a nice way where they have the form environment so we're going to say router dot push oh I can see that we don't have the router imported yet so what we can do is say const router is equal to use router and then in the handle edit we can say router dot push to a dynamic route of forward slash update Dash prompt question mark ID is equal to post dot underscore ID so now if we save this and if we click the edit button we're going to get an error which is okay saying that post is not defined so if we look into that right here we have to pass the post through the handle added function and same thing is going to happen for the handle delete when recalling them or passing that post so we can simply reference to it and now if we click it it's going to go to the update prompt but as you can see it's a 404 but for you that's not a problem you can simply go to your app and you can create a new folder called update Dash prompt and create a new page.jsx file inside of it now here's the catch remember that create prompt page that we did it looked something like this I told you that inside of there we're using a special form component that we made to be reusable now I'm going to show you how we're going to come from create post to edit post immediately first you can copy the entire create prompt page and paste it into the update prompt let's change the name to the export to edit prompt of course and change it right here in the name edit prompt the difference between the edit prompt and the create prompt is that with the create you don't have any data right here available but with the create prompt we need to be able to get the previous data of that prompt to be able to update it so for that reason inside of the edit we're going to add an additional use effect hook that's going to look like this it's going to happen whenever the prompt ID changes and that prompt ID we can get through the request query because when you go to update prompt you will have a special forward slash ID right here so to get to that ID we can import something known as use search params coming from next navigation and we're of course also going to need the use effect and in this case we won't need the use session now that we have the search params here's how we use them const search params is equal to use search params and then you can say const prompt ID is equal to search prompts dot get ID now based on that we can create a new const get prompt details function equal to an async function where we get the response by calling our own endpoint a weight fetch Dynamic string of API prompt and then prompt ID we created it this is the first of the three endpoints we created recently out of the response we can get our data by saying const data is equal to a weight response.json and once we get it we can simply set the post data set post is equal to prompt is equal to data.prompt and tag is equal to data.tag finally we only want to call this function if prompt ID exists like this there we go so now if we go back to our profile and if we click edit we'll be re-navigated but we'll have to remove this used session tag because we're no longer using that and also for now we can comment out the create prompt as we're not using the create prompt and right here we can just put this as an empty callback function for now if we now save all of these changes we can see our create post and it automatically gets filled this is what I was telling you about we have the entire what seems to be a create but it's not the only thing you have to do to make it edit is simply say edit right here and it's going to change instantly edit right here edit right here edit right here and it gives you all the data from that specific post you're trying to edit the power of reusability in react is crazy the only thing we have to do is exchange this create prompt function with the update prompt so let's do just that I'm going to uncomment it we want to call it update prompt and also call it right here at the bottom at the start it's going to give us an error which is fine first we want to check if no prompt ID then we want to return an alert saying missing prompt ID or something like prompt ID not found else we can proceed this time we're not going to make a post request rather we're going to make a patch request we're gonna make a fetch to API prompt but not new rather it's going to be under a specific prompt ID like this so API prompt and then prompt ID this is the second endpoint in the list of endpoints that we created it accepts The Prompt but this time we don't need the user ID as we already know who created it finally we're gonna get the response and everything else can remain the same believe it or not this is it this is all that we had to do to switch our create into an edit great with that said we can go ahead and go back to the profile page one more time click edit it's going to populate it and let's change this from I'm going to give you to I well give you a piece of code let's say a snippet of code and then again grammarly wants me to be more appreciative of it so I'm gonna change it I will give you a snippet of code and I'd appreciate it if you could tell me how I can make it cleaner more readable and more efficient once again let's be good to our AI who knows what is going to be capable of in the future and I'm gonna remove this hash because we don't need to have the hashes here and I'm gonna click edit there we go it brought us back to the feed and you can see that our post got updated that is it the edit functionality now works as well let's go back into our prompt card just to modify this to also have that hash so we can add the hash up front there we go this is looking great so three out of four crowd operations are now completed the last one on our list is going to be the handle delete thankfully for our handle delete we have already created the backend endpoint we have it here so the only thing we have to do is first check is the user sure they want to delete it so we can say const has confirmed is equal to a confirm prompt and this is built into the browser API and then we can pass the question are you sure you want to delete this prompt if this variable ends up being true we can say if has confirmed in that case we can open up a new try and catch block within the catch we can simply cancel that log the error and then within the try we can await Fetch and then make an API call to forward slash API forward slash prompt forward slash post dot underscore ID dot to string so we want to ensure that it is stringified and that is it we of course want to pass the options object where the method is equal to delete finally once that happens we'll be able to get all the posts but without the deleted post so we can say const filtered posts is equal to my posts dot filter where we get each individual post and then we can check if post dot underscore ID is not equal to well we have to get the current pose that we're trying to delete so let's rename this post to just P where We're looping over so if P dot underscore ID is not equal to post dot underscore ID and that's going to give us the posts which we can then set to state by saying set posts filtered post great now let's go ahead and copy this one so we can later on reuse it but for now we want to go to the profile and delete it so if I navigate to my profile and click delete you can see this alert or rather a confirm that asks us if we want to delete it we're going to say yes or OK and then we are waiting and waiting but nothing seems to have happened we did get mongodb connected but the post is still here so if we open up inspect element and go to the console we can see images missing that's okay but we get my posts is not defined so this right here was supposed to be just a regular state of posts and not my posts that was my bad right here now if we save this you can see that it disappears and we no longer have any posts on our profile if we go back to the home page we also don't have any posts there and profile is empty too that's great so let's quickly go back to create prompt and let's just paste the one we already had say something like web dev and create it one more time just so we have something on the feed wonderful and with that we just proved that full crowd capabilities of these applications work we can create posts view them we can also update them if we are the Creator finally we can delete them straight from our profile and we did all of this with the help of nextgs both the front and side and the backhand side now that all of the primary crowd functionalities have been developed I have a couple of tasks for you watching these videos can be a phenomenal way to learn you get to see how code is being used and how projects are being created but of course you'll learn best while you implement new features on your own as I mentioned before that's what we encourage within our JSM masterclass experience there you will have to develop your own projects one huge project each month within a team with expert Mentor guidance but right here with this single free video I wanted to give you a taste of what that might look like yes it is true that you won't have me to teach you how to do it but hey you can give it a shot on your own in that way you'll be able to learn so let me show you the features that you will have to implement right here I have a finalized version of the application deployed so let's explore the applications full functionalities let's sign in of course we can see all of the posts from the different users but we can also create our own prompts nothing new so far right now once we create this post there's a couple of additional things that we can do in this deployed app that we cannot do at the current version of our app one of those things is search so for example I can see that in here this person is mentioning something like customer Persona so let's say that you're building your own customer Persona and you want to find all of the useful prompts that mention that word we can simply start typing customer persona and you can see that it shows us two different prompts with that thing also we can search by different tags so if we search for marketing it's going to give me only the marketing posts and you can also search by username so if I start typing tidbits it's going to show me all of the posts by the username tidbits so there are three different types of search that I'm going to list right here search by prompt content search buy tag so it's going to be prompt tag and then search by username great one additional thing that we implemented is that you can simply click on a tag to be able to see all of the prompts in that category so if you click right here it's going to automatically fill it in the search again nothing special if you make the search by tag work the only thing you have to do is populate the input so as you can see that works as well we can click coding we can click blogging as well and that works so that is the second feature that you will have to implement and then the last feature is to implement view other profiles so if I hover over the photo username or the email you can click it and then that brings you to a special URL called profile forward slash ID of that profile and their name so it no longer says my profile it says tidbits JS profile and then here you can see all of the specific prompts that this person has posted in the same fashion we can search for somebody else's profile and will be redirected there so I hope that these three features make sense and that with all the knowledge that you gained throughout the crash course and throughout the current project build you will be able to implement some of these features on your own of course take your time and don't worry if you cannot get it to behave like the finished application that's completely okay let me give you a hint on how you can Implement some of these features for the first and the second one that is for the search and for the click on tag the code for these features will have to be implemented within the feed component so inside of here you'll have to add some search states such as search text timeout results and then you'll have to filter the prompts based on those queries finally you'll need to handle the search change and also the function for the handle tag click is going to look something like this so if at any point you get stuck with implementing the search you can find the complete GitHub code repository in the description down below and you can reference to it same thing goes for the third feature which is to implement view other profiles for this you will have to create a new file or folder within the profile directory Dynamic ID and then the page this file is going to be incredibly similar to the old profile page that we have created but this time it's just going to fetch posts from a different user and we're going to reuse our existing profile component I hope everything makes sense but again if you get stuck the full finished code containing these features is going to be linked down in the description and whether you decide to implement these features or not I want to teach you how you can deploy this project to the web so you can deploy it right now with me or you can pause this video try to implement these features and then deploy it later on with me either way is just fine because the application even right now is looking great so let me teach you how you can deploy a new next 13 modern application first things first let's go ahead and check out our file and folder structure inside of here we can see dot r dot EnV is green but it shouldn't be we never want to push a dot EnV file to production so we can simply add it right here under get ignore and that should grade out that is good that means that it's not going to be pushed to get but we can go ahead and create a new GitHub repository so back on GitHub you can scroll all the way to the top click the plus button and then click new repository feel free to choose any name for your repository I'm gonna do project primetopia and make it public finally click create Repository after that pull this to the side and open up the integrated Visual Studio code terminal and stop the application from running and clear it then run get init gitad dot get commit Dash first Dash m first commit and then follow the commands from here get Branch Dash M Main get remote ad origin and then git push U origin Master this is going to push your code to GitHub and in just one second you can reload it and you should be able to see your code right here of course feel free to modify the readme add a screenshot tell everybody what you built once you have it deployed that's great now we can head to versl is a company that owns next.js so of course they have built it with nextgs in mind they have built it in a way that you can immediately develop and build specific applications like we did today and then you can preview it and finally you can deploy it they made this process so simple and so easy and since they are the creators of next.js they made it so seamless that you immediately get all the benefits such as speed SEO Global Edge Network and then first party monitoring as well so the only thing you have to do is go ahead and log in or sign up at the top right do so with GitHub because that's where we put our project code somewhere within your dashboard you should be able to find a button to create a new project most likely you won't have as many projects as I do but all of these are projects from many different cohorts of the master class experience students that we teach so every single one has their own deployment for their Capstone and monthly projects so in this case you can scroll all the way up and click add new and we want to add a new project they make it so simple you simply need to import a git repository and if you made it public it should be right here so you can click import the root directory can be the same as well as the build and output settings of course we have some environment variables which we want to add regarding environment variables we can add them once the project is deployed so let's go ahead and click deploy there we go it is deploying right now and we can see the steps right here and immediately we get a build error which is okay it happens right now we can see that it cannot resolve add components forward slash profile that is coming in the profile page.jsx so if we open up the page and check this out here we can go to some different file maybe the page and see how we're importing the feed feed it's a capital f here capital F here and the component itself is of course in a capital letter so in the case of our profile unfortunately we used a lowercase p letter so I'm going to bring this back to uppercase it didn't break our build locally but it looks like versel doesn't like inconsistency so if we fix this we can go ahead and run git add git commit Dash M fix typo and then get push this is going to re-push our repository which means that it should Auto build on the same project that you have opened so right here we can check it out it says building fixed typo there we go the ration 35 seconds and there we go it succeeded so we can see everything went great and if we click visit you can see that our application is deployed on this URL that is great now of course a couple of things won't work right off the bat and that is we can see that the sign in button is missing which means that we haven't properly connected next auth nor Google so let's do that together right away our application contained some environment variables that we need to fix for this to work we of course had our Google ID Google client secret mongodb URI and we also have the next auth URLs first of all we'll have to update our next auth URL to this newly deployed URL of course we cannot do it right here within our code we have to do it within environment variables of our project so let's click your project name right here go to settings environment variables and then you can add your environment variables one by one so let's add our next auth URL which is going to be equal to this URL let's also add another which is going to be the next auth URL internal also pointing to the same link we can add a couple more that's going to be next auth secret equal to this entire thing then we can have the mongodb URI equal to this entire query string then we can have the Google client secret and finally the Google ID there we go all our environment variables are here and we can save them now on top of that there are a couple of additional checks that we have to make first of all we can go to mongodb and then go to network access and once again ensure that you allowed access from all different endpoints right here so you can click add IP address and somewhere here it should say not only add current but add all addresses that's great on top of that we also have to update the Callback URL within our console.cloud.google.com so go to web client one and then under authorize JavaScript Origins we need to add our new URL so copy it and paste it here we have to remove the Slash and we also have to add the redirects so right here I'm going to add the base one as well as the one that's going to contain the forward slash API forward slash auth forward slash callback forward slash Google and you can click save now this could take a couple of minutes to refresh but now if we go back and reload the page if the environment variables have been set up correctly and are Google Now allows the Callback we should be able to see the button but it's not there yet so we need to ensure that our environment variables are there it is possible that we might need to rebuild our application for the changes to take effect so let's go to deployments click on the latest build click on Three Dots and then click redeploy and once again confirm it deployment started and our deployment should be done in about half a minute our application has now been deployed and we can click visit and there we go we have our snippet which means that we're successfully connected to mongodb and we have our sign in button which means that we have properly added our environment variables let's go ahead and try to sign in but this time it says that you can sign in because the app sent an invalid request okay that's interesting and here it says redirect URI mismatch so that has to do with the callbacks that we have said right here and if we look into it the URL ends with oex JS Mastery Pro it's the same one and then we also added what we need to add that's going to be the forward slash API forward slash auth forward slash callback for slash Google so this looks good to me it does say that the changes could take five minutes up to a few hours to take effect but hopefully it's gonna be sooner and it looks like I just noticed that these two versions of the app don't match so while we redeployed it it also changed the URL so we'll have to re-pass the updated URL to Google so instead of this one I'm gonna pass the existing one that is this one right here with 7z there we go I'm gonna update that and we are good to go I'm Gonna Save it and hopefully this time it's going to take less than five minutes or a couple of hours I'm gonna reload our page and try to click sign in one more time this time it did give me all the accounts I can sign in with in this case I use my personal account just to see if we can create another post with it so let's go ahead and create a new prompt let's do something for blogging so we can say I need a type of blog post that will provide valuable and relevant information to my ideal customer Persona and persuade them to take the desired action and we can say blocking I'm gonna create it and there we go we have Adrian we have JavaScript Mastery and for now I can just click here to go to my profile but if you implemented the additional features such as the search and the click on other people's profiles and clicking on the tag that should work as well and before we wrap up this video I wanted to talk to you about something really important you see creating these projects is just one part of the learning process but it's equally important to share your work with others sharing your work online can help you in so many ways first of all it can help you build your portfolio so if you're just starting out having some projects to Showcase can be a great way to demonstrate your skills to potential employers or clients sharing your work also gives you the opportunity to receive feedback and improve your skills in addition sharing your work can help you gain recognition when you share your work on social media other developers and enthusiasts can Discover it and share it with their own followers helping you get more exposure finally sharing your work can potentially lead to job opportunities employers are always on the lookout for talented developers and sharing your work can help you stand out from the crowd so I encourage you to share your work with us here's how you can do it if you're on Twitter you can share your project by tweeting the deployed project URL GitHub code URL screenshot or video in a brief description of the project to build don't forget to use the hashtag JavaScript Mastery and primetopia as well as tag the JS Mastery Pro profile if you're on LinkedIn do the same thing share the screenshot or even a video of you going through the project you build and the additional features you implemented add a brief description and of course tag JavaScript Mastery as well as Adrian if you want to recently one of her students share how they have built their 3D portfolio it is a phenomenal build and it got almost 10 000 views they shared what they've done as well as tagged who they learned it from and they also shared the GitHub link this is going to provide this person so many opportunities and you can do the same we have this great person that shared how they launched their own portfolio side and they also tagged JavaScript Mastery on Instagram I can't wait to see what you'll create so please share your projects and tag me on different social media channels I will make sure to check every single one of your submissions with that said thank you so much for watching this video and coming to the end you learned a lot about what next js13 has to offer if you want to explore our more in-depth courses check out jsmastery.pro for a couple of phenomenal react and nextgs courses and if you're serious about getting a job in Tech check out our JSM masterclass experience a six-month boot camp where you have expert developers at your disposal as your mentors once again phenomenal job when building this project I'll see you next time and have a wonderful day foreign [Music] [Music]