Build and Deploy a Full Stack E-Commerce App with an Admin Dashboard & CMS in 2024 | Next 14, Stripe

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
are you ready to up your e-commerce and admin dashboard game learn an amazing CMS that isn't headache to use and use the best stack to do it next4 stripe and typescript hi there and welcome to a new build and deploy video where we'll build nextjs powered e-commerce site with an admin panel so good that even Tony Stark would feel a little jealous we will develop an attractive homepage that follows the best design practices we have a hero section categories new collections ongoing deals and Shop features all complemented by a crisp footer we'll create a shop page that even guests can visit allowing users to explore products apply category filters see more products with bination which is key for performance in e-commerce projects develop a concise product Details page with product recommendations Implement and add to card system which works without authentication users can adjust quantity get instant updates to the pricing or delete products Implement user authentication with a secure login and registration process including password recovery develop a streamlined and minimalistic checkout process which is optimized for the best user experience and most purchases securely collect and process payments and you'll also develop a userfriendly account page which allows users to update personal information see past purchases current orders order details and of course a log out option that's just the start the real fun is the admin panel from where you can control absolutely anything on your shop website starting from Custom Pages where you can directly add new pages tailor them to your liking by adding diverse sections authoring text images and more easily add new products oversee orders add remove or update categories in real time manage customers as well as page redirects for optimal navigation and user experience customize the header and footer and even manage SEO from the ad panel that's insane right it's like having the best parts of Wordpress without being limited by it and having all the best nextjs options at your fingertips this is all made possible with payload CMS a headless CMS and open- Source framework that optimizes your Dev workflow by providing you with the backend functionality while allowing you to customize your app and add additional functionalities so build and deploy a fast secure and scalable app in just days that would normally take months it is the fastest way to develop and power anything from websites to internal tools Define your schema in tapescript and get a full backend and CMS admin panel for free in about a month payload will put ver cell in their free tier because of that payload will essentially become the official next GS CMS you heard it here first that's going to make it that much more important to understand and therefore future proof your skills and speaking of NEX GS recently we have added two special bonuses to our ultimate next gs14 course one is a guide to Advanced features powerful libraries and robust security practices in x14 and the other most common next GSF aqs answered both of these bonuses offer short and precise explanations with the ability to dig deeper into it with many projects so if you want to enroll and join Over 2500 developers who already joined and love it go to jm.pro next4 or click the link in the description to enroll now let's get started building our incredible app to get started with building our great e-commerce application this time we won't start by creating a new empty folder on our desktop rather we'll leverage an existing open- Source tool payload a CMS that works it's all typescript all nextjs and it is fully open source so in this video not only will I teach you how to to build our phenomenal Tech related e-commerce shop but how to leverage payload to build any kind of e-commerce or any kind of app that requires a CMS for that matter incredibly easily and scalably up to the Enterprise level the link to the website as well as the special starter we'll use is linked down in the description and while we're here let's give them a star now on top right you can click try payload Cloud for 30 days but don't worry you'll be able to have your project up and running for much much longer than 30 days soon enough payload in collaboration with versel will allow you to deploy your projects completely free and don't forget payload is completely open source so you can always spin up your projects on top of their codebase with that said let's click e-commerce to build a full e-commerce back end alongside a beautiful storefront integrated with and ready to sell here you'll have to register for a free account you can do so by entering your email and password once you verify your account you can log in and we can continue where we left off by creating a new e-commerce project let's continue with GitHub connect and select your GitHub account and then choose a repository name and you can even choose whether you want to make it private or public in this case I'm going to make it public and click clone template that's it payload is already creating the starter repo for you which will be able to clone and continue building on top of here you can choose your plan and you can choose free trial no credit card required you can choose your project settings in this case I'm going to go EU project name project slug template and then the default domain which you can do something like e-commerce _ JSM app of course feel free to do something else by including JSM either before later in the middle whatever you prefer and let's click I agree and start free trial as I said even though there's a cost here to payload Cloud you will be able to have your project up and running in the future as well but as I said you'll be able to have your project deployed indefinitely with the free tier on verell or you can always build on top of their open source repo with that said let's wait until our project is deployed there we go and now the project configuration is happening and you can see the build logs below and in just a couple of minutes our new project is deployed let's click this URL as you can see our entire template is here although right now the database is empty so we want to seat it with some new products and we're going to do that later on within the dashboard but the full login account creation products even checkout all of that has been set up for us but considering all of this has already been done you might be wondering what will I do and what will I learn with JavaScript Mastery my goal has always been to make you an independent developer what does that mean well it means that if an employer or a client comes to you and says hey I need an Enterprise level e-commerce store for this specific category of products I want you to be able to say I've done this based off of a phenomenal open source project and I can make it completely custom for you and that's exactly what I'm going to teach you in this video so here we can go to our main branch and this shows you that payload is not some kind of a low code no code tool that non-developers use payload is built for developers where we use this as the star your template and then build custom functionality on top of it so our next step is to get this right running on our local machine which we can do by going to code I would recommend downloading and using GitHub desktop but even if you don't have it you can simply copy this URL once you do it open an empty Visual Studio code window go to view and then terminal and simply press get clone and then paste this URL and press enter this now cloned into e-commerce which means that you can CD into e-commerce and then press code dot which is going to open it up within a new Visual Studio code window so I close the old one and open this one in full screen to start running our project we first need to install all of the necessary dependencies so once again open up your terminal and then run mpm install -- Legacy dp-s this is needed to install some older versions of dependencies in case there are some you can also use yarn once you do it press enter while the dependencies are getting installed let me introduce you to the starting structure that we have right now you can revisit this GitHub repository that was created for you and then you can read the readme let's go through it together just a bit this is the official payload e-commerce template use it to power e-commerce businesses and online stores of all sizes this repo includes a fully working backend Enterprise grade admin panel and a beautifully designed production ready website which by the way we're going to customize as well this template is right for you if you're selling physical products digital assets or access to content like courses or premium articles now there's an important point I want to make this video will not only teach you how to build this e-commerce site this video also has a secondary learning agenda which is maybe even more valuable in the long run while going through this template together we will inevitably learn how to read and collaborate within large repositories this repo is huge it has a lot of custom files Pages folders custom functionalities Styles specific file and folder architecture rules and more and trust me when I say this in many cases working in a company or for a client is much different than our typical YouTube videos where we build something from scratch typically what's going to happen is you will be dedicated to a specific already existing code base which you will have to learn in a couple of days and start contributing the code too so while going through this repo I'm going to teach you all the tips and tricks and practices I've learned over the years of how to more easily get started working on a large existing codebase so I hope you're excited for that as well and while mentioning this I also thought about a third really important learning point and the third point is that in case you want to build your own e-commerce store in the future you'll be able to learn from Best Practices from payloads Engineers they've spent a lot of time thinking on how to make their product the best it can be so let's quickly go over the template we can quickly start it by cloning it and then we can go into the development by running mpm or yarn Dev and then opening Local Host and that's it changes made in Source will be reflected on your app then we also need to set up stripe and we also need to check out some production guidance once we're ready to deploy here they go deeper into how everything works so we're going to have different collections specified for functionalities such as users products orders Pages media and categories we'll also have some globals like the Heather and the footer and the foo we'll have the access control we'll have different role based system such as admin and customer we'll need to figure out how to manage the shopping cart and the products integrate stripe and connect it finally how to check it out how to go behind the pay wall how to build using their layout Builder how it handles SEO redirects websites cash ejections and Docker seeding the database and much more so this is big this is exciting in and now let's start dissecting it and customizing it together our dependencies have been installed and before we go ahead and run it let's quickly check out the env. example so here we have some environment variables which we can copy and we can create a new file called EnV to which we can paste all of these demo variables and here we'll append our additional variables later on as well and by additional for example I mean this database uuri which you can get access to by going to your payload project clicking database and then you can copy this connection string once you're back you can simply override this one right here next we need to choose our payload secret which is just a randomized string of characters I'm going to do JSM custom secret whatever you choose make sure to refer to it later on once we deploy our project now we can close this open up our terminal and run mpm run Dev this is going to start a project on Local Host 3000 so let's go ahead and open it up and there we go we are almost up and running but before we can see our products we have to actually add them so let's click go to dashboard and let's create our admin user I'm going to use the same email I used before to open up my payload account account choose my password confirm it I had a name such as Adrian we can select a role which in this case will of course be admin and purchases will be empty that's it let's click create now the first thing we'll have to do is seed our database that means add a few existing products so we can see and test application full functionalities so click seed your database and it says seeding once that is done simply go back to Local Host 3000 as you can see our full store is now up and running we have a nice looking landing page with all of our products and we can also click shop now to see all products now there's one thing I want to point out if you go to a specific product you might notice that the website feels a bit slow this is only happening in development once you actually deploy it it's going to going to be incredibly fast as of course it's using the latest and greatest of nextjs so this is a typical product page you can add it to cart this is your cart you can go to checkout and you can only go to checkout after we connect stripe but as you can see all of this is looking pretty Bare Bones right this image is huge the design is just minimal and it doesn't feel like a comprehensive e-commerce application definitely not what I promised right so now our real job starts we're going to turn this into this Tech Haven a clean minimalist maybe a bit Apple inspired Tech e-commerce store you can shop by category you can see all of the products within those categories as you can see everything is launching super quick the product page looks great with related products you can add things to card immediately view them within the card and then check out we even have this completely custom beautiful registration and login screen a lot of stuff is coming in this video and so far we have just been laying out the foundation which means creating all the backend systems necessary to run our e-commerce stores we have created an admin dashboard we have a complete login and registration screen we can even create new customers we can add items to the cart check out and pay later on once we enable stripe and even add new products through our admin interface not only products but manage the look and feel of our website design orders media categories and so much more now it's our turn to understand the codebase and to slowly but surely and to start customizing it so let's go through the folder structure within the source folder and then Within app is where the majority of our application is this is our nextjs shop app whatever you do here will modify your primary e-commerce store and then within the payload folder is where you can modify the admin UI the admin interface the most important files here are the payload doc config.txt end points about customers products seed and so much more and also the payload types where we can have the types for all of our products Collections and more which means that in case you modify something within your collection you'll have to add it here as well and finally we also have our API folder which is right here within the app and here we have all of the necessary e-commerce functionality endpoints such as fetch Doc and this is how we we fetch different pages products or orders or for example fetch globals which allows us to fetch header footer and the settings data but as I said we're going to go through everything together and fully explore it now first things first let's start by modifying the Styles meaning colors fonts and assets so to modify some default Styles we can go to Source app CSS and then app. SS here we can change the font body from system UI to a font known as just and we can also do Sans serif right here and we can do the same thing for font djust and also say that that's just and Sans serif next we can go ahead and modify the body which is right here the font family is going to be font just we're going to going to also add a padding of zero usually this is known as CSS reset we just reset some default styling that the browser provides we also want to change the default color so we can say VAR d-c color- dark- 500 and we can set the display to be equal to flex and a flex flow of column below we can modify the main class to say Flex is one one and then Auto this is going to be helpful with our future layout in the selection we can also change our color so we can say VAR -- color- dark 500 and in the M selection we can do D- color- dark D50 then we want to go down all the way to our P tag and we want to simply delete the include mid break and set the margin to zero in the O and UL we want to remove the padding and the margin and we want to Simply say margin is zero and padding is zero as well as a list style is going to be set to none we don't want to have that ugly underline for the a tag we can change the color to be set to VAR color-- color- dark 500 and these are all the global changes that we have to make now let's go back right here and let's go to the colors. scss here we want to add some special brand colors for our application so let's go all the way at the end and let's say brand colors of course you can fully modify these later on and here we can add colors such as d-c color- dark- 500 and then set a specific rgba value like we did before a link contain containing all of these code blocks that I will provide you is going to be linked down in the description so feel free to refer to it go to colors. scss and then simply add this part right here it's going to apply just a couple of colors so to simplify our styling later down the line there are also some small additional styling changes that I noticed that we have to make and those are going to be within type. scss specifically right here at the start we want to reset the margin for all headings once again this is something that you want to do quite often in your app if you're developing a custom design we also want to remove the margins from every single age here from all the headings and within the include as well so we can remove here here and repeat this for all headings we want to have clean setup so we can start styling from scratch H5 as well and finally H6 now we want to style the H4 a bit more since we're going to use it a lot so we can change the font size to 30 pixels the line height to 43 pixels the font weight to 400 and finally letter spacing to 0 em once again some small Global changes to make our styling easier later on and now we have to utilize the new font that we are about to import we can do that by going to app and then layout following all of the best NE GS practices by the way I do have these little eslint warnings we're going to fix those later on but for now let's simply import just which is a font coming from next SL font SLG gooogle and then we can use it right here by saying const just is equal to just which accepts an object of subsets set to an array of Lain we're going to get two different weights so that's going to be a weight on of 400 and 700 and a variable for that font is going to be-- font djust finally in the body right here we can apply a class name equal to it's going to be a dynamic string of just. variable and we want to wrap the children right here within the main tag because that's going to be the main HTML 5 semantic content and it's going to have a class name equal to main now I know that a lot of this didn't make too much sense but these were just some Global style changes that we had to make to allow us to more easily turn this into this you can see we're already a step closer because now the font is exactly as it is right here now back within layout. TSX you can see that we still have issues with es length and prer complaining about our line endings line endings are different on all different types operating systems so I'm on Windows and that's most likely why it's complaining so what you can do is you can press control or command p and then type eslint RC and press enter this was just one of many tips that I will share throughout this video of how you can better utilize Visual Studio code keyboard shortcuts of course you can manually navigate to the file right here as well if that didn't work here we have to add rules that's going to be an object inside of which we need to say prettier for/ prettier and then Define that as an array where we have an error comma and then an object end off line is going to be set to Auto like this if you save it it should look something like this rules prettier prettier error and the Fine Auto and now it should no longer complain as you can see right here now there's one more thing we have to do before we go ahead and start implementing all of the additional functionalities and that is import all of the assets will be using throughout the project so in the description Down Below in that same link where you can find all other code blocks you'll also be able to find a link to a Google Drive containing all of the assets for our project so simply download them go to our files remove the current public folder entirely and then drag and drop the unzipped folder right here in the root of our directory and click copy folder you can see payload CMS public is now here and we can simply remove the prefix and just leave it as public on Windows devices this renaming process can take some time but if you're in Mac it should be much faster and now that we have renamed our assets folder we have the assets public all the images and icons were're ever going to need for this application and I was also kind enough to include all the admin UI images these are images that you don't necessarily need to use within the app but you need to use them when you're uploading specific categories or products and so much more so I included those as well with that said we're almost ready to start styling our application but before we do that I want to ensure that we understand the terminology of payload but but before we do that I want to ensure that we understand payloads terminology so if we go into source and then app you can notice that here we can see a couple of things we can see blocks components Heroes providers utilities now what are those well one of the most important aspects are called Collections and payad collections are defined through their configs and you can Define as many as your application needs each collection will scaffold a new collection automatically in your database of choice based on the fields that you defined so you can think of collections as just typical database collections where each one has a specific URL it has some Fields labels admin and you can choose how you want to authenticate and upload those specific documents within that collection on the other hand we can also discuss globals globals are similar to collections but they can only appear once so they're one off and they're perfect for things like Heather navigations s banners or Footers so what do you say that we start by modifying a couple of globals we can start by putting our browser side by side to our editor then we can go to Source appor components and then we can find the header and go to the index. TSX I'm going to zoom it out just a bit pull this a bit over to the side and expand the code so we can better see what we're doing inside of here we can remove these classes as well as the header now and the gutter as we won't be using those components within our new modified header instead what we will be using is import heer component from SL header component and of course now we have to actually create it so let's go right here within our header let's remove this index. module. sccss and let's create a new folder called Heather component within it we can create two new files index. TSX as well as an index. module. scss this is going to be the styling for this specific component now within here we can run ra Ace this is a shorthand to create a basic react component component in this case we can call it heer component and then at the bottom export default header component as well with that done we can go back to our index and we can ensure that the import is done correctly but this time no longer will be displaying this entire header and The Gutter and all of those things we can simply return a react fragment and then within it we're going to render our own Heather component just like so and to it we're going to pass the heer so we can say header is equal to header this header is coming right here at the top where we're fetching it directly from payload CMS soon enough I'll teach you how we can modify it and we can also remove these comments right here and say something like console.log error there we go so now we can slowly see how we're starting to modify our code base here it's complaining about conso log so to fix this warning right here we can go to es RC and then say no console off this is going to ensure that it doesn't complain then we can move into our header component and actually Define it now we know that it's going to be accepting the entire header which is going to be of a type header header like so because we are using typescript and the pretty cool thing about payload is that they already created the types for us so we can simply import the header by pressing control space or command space while selecting it and we can import it from payload payload Dash types within here we can Define our nav that's an HTML 5 semantic nav tag within it we're going to use something known as a gutter which we can import from d// gutter within the gutters we're going to have a link component which of course has to be imported from next link and within it we're going to have a self-closing image with a source equal to/ logo-black SVG I'll tag of logo so we're just trying to display our logo and if we click on it the href is going to point to the homepage meaning just forward slash now if we save this you can see that Local Host is loading but there still seems to be some problems right here when importing the header component it says header component not found that's because we're importing it as a named import and here we have export default so what we can do is simply modify it by doing a default import if we now save it you can see that our tech key Tech Haven logo appeared on top that's great so now let's close the files which we don't need and let's only have the header component index DS over open now let's continue with styling our navbar which we can do by importing classes coming from index. module. sccss once we have it we can Define the class name right here by creating an array and then saying classes. header so this is now going to correspond to the header class within the index module scss so let's open it up by going to index. module. sccss and let's create a doer class that's going to have a padding of 36 pixels on top and bottom and zero on left and right so now you can see it just provided some spacing now we also have a warning here but we're going to fix that later on the next thing I want to focus on is adding a class name to this gutter which is going to have a class name of classes. r wrap and this wrap is going to be a simple class where we can say wrap it's going to have a display of flex align items of Center justify Dash content of space between and we want to wrap the content so Flex wrap is going to be set to wrap we also need to set the gap between the elements in the nav bar so we can say Gap and we can use the CSS C function where we can calculate the basee right here divided by two so this is for the row Gap and now for the column Gap we can use the regular VAR D- base there we go so now we're applying that as well but of course between the gutter we have a link this link has a class name of logo this link points to home and the image has a source but we can also give it a class name that's going to say classes. logo so now if we go into our classes we can do the do logo and simply provide a width of about 170 pixels I found that to work the best now you can notice that my class names simply Become Three Dots right here this is not needed for this type of application but I started using this because Tailwind classes can get so long so it's easy to hide them in this case I'm going to turn this extension off so I can see the full class name if wondering the extension name is in line fold here we go now we can see the classes and of course in this case we can transition to using next gs's image property coming from next image there we go just to make it a bit more optimized but of course in this case we don't need to provide it a class name rather just the width and height properties so we can say width is 170 and height is about 50 and there we go we have our optimized next xjs component now below this link we want to render a header nav which is going to be coming from do do/ naav and to it we want to pass the entire header and this header is coming through props we're passing it from the original header page right below it we also want to render a header mobile nav to which we want to pass the header now this one we have to create by going to our header and then within it creating a new folder called mobile nav within it we can create a new index. module. sccss as well as creating a new index. DSX right within it we can run rafc modify the index to mobile nav save it and then go back right here and import it with by saying mobile nav is coming from do/ mobile nav there we go so now you can see since in spooling the default navigation we already got some links right here now you can see that we maybe have a few links that we don't necessarily need here like create account or login or even Index right so what we can do is we can hide them and let me show you how we'll be reusing this later on so it's better to create it as a constants file so right within the source and then app we can create a new constants folder within it we can create a new index.ts file and within that same Link in the description I'm going to pass you all of the constants we'll be using here you have no header footer URLs so these are URLs that we can hide and also we have some profile MV items and inclusions like what do we offer so now that we have that we can immediately start using it within the class Name by saying no header footer URLs we can click it to import it dot includes path name so if it includes the path name then run the classes. height and how do we get to the path name well we have to import it by using nextjs so we can say const path name is equal to use path name which is coming from next navigation and of course we have to Define what a classes. hiide means so we can say hiide display is going to be none now this is not going to work right off the bat and that is because we still have to filter it and join it to be only one string because the class name expects a string and not an array of strings so we can call the dot filter on this and only get the ones that are bully and true and then we can join them with an empty space this is how from an array we're going to get a simple string and of course since we're using use path name we have to convert our header into a client component by using the use client directive there we go so now we have all of our links we can click shop that works and if we are on these links such as create account login recover password we can hide the navigation bar which is exactly what we're doing here because our create account is going to have a completely new layout inside of which we don't need our nav bar now let's dive into our header nav which is right here in the do/ naav and let's modify it further inside of here we can remove these comments to make it easier to see what's happening and we can turn these links into a button that looks a bit better so let's remove these links and react fragment and render a new button which we can import from sl. SL button it is a self-closing component that's going to have the L as an element equal to link it's going to have an href of forward SL login it's going to have a label of login it's going to have the appearance of primary and on click we want to have a call back function where we do window.location.href is equal to a string off for SL login so we're simply moving to the login that's it you can see now we have a beautiful login button we can also further style this button by going into it and making it also accept children so right here we can say children is going to be off a type react. react node we're going to pass it over through props children and we can then add it right here within the content so here we have content and right below this fan we can render the children this is in case we want to pass some additional icons or labels or arrows to style our button further what we can also do while we're here is also modify its index. module. CSS by styling the padding to 10 24 to make it a bit Slimmer as well as increasing the Border radius to 10 pixels so if we save it you can see now it matches our theme a bit more we can close our buttons that's good we have used it right here but now our button is complaining and that's because we didn't set children to be optional so we can modify this type always be careful about typescript types they're here to save us not Ro our day and finally fin sometimes we also want to display the cart link right below the button so here we can say if user exists then maybe that user has a cart link which we can simply Define like this I believe right now we're not logged in so we cannot see it which is totally okay also we no longer need to import the user so there we go and now that our header nav is almost done we have our mobile now but looking at this payload made it so good that technically it fits nicely in mobile devices so for now I'm just going to remove the mobile nav and we can revisit it later on if needed but for now as I said we can remove that folder as well now what we can do is go into the header component index module scss and this also removed that Index right here at the bottom so it's looking perfect with that said we have successfully modified the first section of our application the header but we have just modified the Styles and the content but not really the links right this is coming directly from header and header is coming from let's see where if we go to our main Index right here it's coming from Fetch header which is coming from API fetch globals which is a huge function so the question is how can we modify the content the globals the collections or the data of our application and the answer is we can do it right within our admin interface so let's expand this just a tiny bit and open up localhost 3000 SL admin then open up the sidebar which I believe is right here go to header and here you can add all the links you want let's add a new nav item in this case let's make it point to home and let's add the label of home it's going to be an internal link and it's going to show up at the first place we can leave the products as the second link and it can say shop now as soon as you save this and collapse right here go back to Local Host and reload you can notice that now you're logged in so we have this extra thing right here but we also have home and card considering that we're logged in so pretty cool stuff you can easily modify it right here within your admin interface now that we've modified the header let's focus on the footer next to get started working on our footer component let's find where we have this footer which is going to be in the components and then not header but this time it's going to be the footer there we go and we have the index. TSX now as before here we can remove most of these Imports which we won't be needing like the gutter like the CMS link the gutter also the theme selector and then also fedge globals we'll be using all of these within some other files we can remove these comments right here and just do a console.log with the error we can remove everything that is within this footer tag and simply wrap everything in a react fragment like so and right within we can render a new footer component self closing and to it we can pass the footer equal to footer this is it now we can also remove the classes and we can go right here within the footer and create a new footer component folder that's going to have an index.ts inside of which we can run rafc rename it to footer component say something like footer and we can create a new index. module. scss file which we can import within the footer component by saying import classes from SL index. module. sccss finally we can go back to this index and we can import footer component from that/ footer component now here it's complaining that we cannot have footer here and that's because I called it TS instead of TSX this is a component instead right so we can do it like this and now it's not going to complain that we imported the footer component to which we're passing the footer and at the bottom we can simply see a text that says footer which means we can start focusing on our new footer component so let's wrap it with a semantic HTML 5 footer tag like so let's also give it a class name equal to no header footer URLs coming from constants and we're going to do the same thing that we've done with our navbar do includes so if it includes this specific path name which we have to Define at the top const path name is equal to use path name coming from next navig which we have to import then we can do classes. hiide else we can do an empty string for the class name right within that footer we can render the gutter which is just going to provide some spacing and we can import it from. Gutter and within it we can render a UL an unordered list that's going to have a class name equal to classes is do inclusions soon enough we're going to implement the styling for them of course as soon as we added use path name we have to turn this into a client component by using use client now let's see how does a finished footer look like there we go so we have these so-called inclusions what is included with our payment like free shipping money guarantee support payments and then finally we have this footer on the bottom that looks very nice and of course our logos will be working so let's continue creating the layout for it and then we're going to focus on The Styling later on first we have a UL inside of which we can render inclusions which we can import from constants map where we get each individual inclusion as well as its index and then we can immediately return meaning just put a parenthesis here and Li each Li has to have a key which can be equal to something like inclusion. tile and then within it we can have an image a nextjs image component which has to be imported from next slash image we can give it a source an SRC of inclusion. ion and by the way if you're wondering where this is coming from look into inclusion it's coming from our constants where we simply give each inclusion a title description and an icon alongside an icon we can also give it an Al tag equal to inclusion. tile as well as a width of 36 height of 36 and a class name equal to classes. Icon if we save it you can see four icons right here at the bottom below the image still within Li we can render an H5 that's going to say inclusion. title and now if you reload you'll be able to see the text appear right here as well we can give it a class name of classes. tile and Below we can also do a P tag that's going to render the inclusion. description there we go every everything is now here of course once we style the inclusions div we'll actually be able to see them nicely appear in a grid type format so now we can go below this Gutter and we can create a new div that's going to have a class name equal to classes. footer while we're here why don't we immediately add the classes for our footer since this is just the styling once again in the link down in the description where all the code blocks are you'll be able to find the footer. module. scss which you can simply copy and paste over here it's just a couple of classes for hiding social icons as well as creating the grid for our inclusions so then you'll be able to see that now it's looking a bit better within our footer we can also do a gutter which once again just creates some space within it we can create another div that's going to have a class name of classes. WP then we can create a link that's going to point to hre of just home for now and of course we have to import the link coming from next slash link and within the link we can render an image tag that has a source equal to/ logo-white SVG and I'll tag of logo and a width of about let's do 170 and a height of about 50 should be fine if we save it you can see the nice logo up here now we can go below this link and render a P tag such as footer. copyright and here's the thing now I want to teach you how to add additional things to your content similar to what we have done with their Navar so let's quickly comment this out because if you leave it it says cannot find name footer well footer in this case is coming from params so we can destructure it because we're passing it into this component don't forget in our main index we get the footer by getting it from a weight fetch footer and then we pass it as a prop so here we can destructure it and then say footer is a a type footer coming from payload types and we can save it but you can see that the copyright doesn't exist on footer so how can we add an additional property such as copyright in this case to our footer well we can navigate to our globals dots right here within graphql you can see that here we are going to see our footer with nav links and and we also want to get copyright next to those nav links then we also want to go to our footer. DS of payload globals and here you can choose which Fields you want to add to it so right now we're in globals and then foter and here you can add a new field with a name of copyright label of copyright like this type of text and required of true there we go and add a comma here finally in payload types which we can navigate to as well payload types we can search for footer and here on top of nav links we can also add copyright of string so these are three places where we have to modify something one is payload Types on the footer another one is Global's footer right here and the third one is globals within graphql where we fetch that data we're going to go through this process many times but yes I agree payload requires some time to getting used to but once you get used to it you're essentially building on top of Open Source directories using graphql and using proper types right they're not Reinventing the wheel they just provide proper typing they provide proper graphql fetching and they allow you to then modify it using their own CMS so now that we have modified those types there's one more thing we have to do we have to go to our terminal stop our app from running by pressing contrl C and then Y and then I would recommend installing yarn so you can do that by running mpm install -- Global yarn in case you've been using mpm if you RN yarn then that's good already usually yarn works better with graph queries so I just like to use it here and then run yarn payload generate colon graphql schema this is going to generate a graphql schema based off our modified graphql config and finally we also want to generate the types by running yarn generate types great that is done as well now let's go back to our admin interface which is going to be right here let's expand it and check it out without even reloading our Local Host 3000 admin panel knew that now we have a new copyright field which we can add that's cool so this is how you modify your globals within payload CMS let's say at 2024 let's do something like Tech Haven or All Rights Reserved and we can click save now if we go back it's updating the footer and also if we go back to our footer you can notice that typescript immediately knows that now a copyright property of type string does indeed exist on our footer so let's rerun our application by running mpm run Dev and while we're waiting for it to run let's also add additional social social icons to our footer by going to our admin panel and adding new nav items we can add a custom URL open a new tab and let's do something like https colon slf facebook.com and then you can say label of Facebook we can also repeat this process for three more sites custom URL opening new tab let's do htps Colin instagram.com and we can do Instagram and finally let's also do the third one custom URL let's do youtube.com and let's say YouTube great so now we have three of these hopefully they won't have any more errors and we can click save there we go that's looking good and now our application is up and running we do indeed see our copyright at the bottom which is great and the last thing to do is to Loop over our social icons so let's create a new div with a class name equal to classes. Social Links and let's Loop over our nav items which we can import from constants map where we get each individual item and before we return it we want to just open up a regular function block we want to extract the icon from each one of these links for now let's leave it as an empty string and then we want to return we can return a button for each one of these that's going to contain for now just a piece of text saying item. link. label let's give this button a key equal to item link. Lael let's give it an element of Link an H of item. link. URL let's fix this a new tab of true and a class name of classes. social link item and of course we need to import the button from do/ SL button and if we save it you can see that it's going to break because it cannot read the property link right here and that's because I mapped over profile nav items instead of nav items which we're going to Define right here at the top by saying const nav items is equal to footer question mark. naav items so we're directly getting them from the footer coming from payload and if it doesn't exist we can make it an empty array great so now we should be able to accept those links that's good now items plural if we save it now we can see three logos but they're really dark so you can barely see them if you have but Facebook Instagram and YouTube are indeed here now the last thing we have to figure out is how to attach those social media icons to those different nav links and to do that we're again going to dive a bit deeper into how payload works so we're going to move over to graphql socore graphql and then specifically we're going to go to link. TS within here we can Define that on top of the URL we also want to get the icon which is going to contain its own URL then we also want to go to payload Fields link. TS and right here at the bottom below this admin withd 50 and then below two more curly braces we want to add a new link with the name of Icon label of Icon type of upload and we want to add a relation to Media so this is going to be a media file finally you know the trail if we modify the graph C config we have to stop our application from running we have to run yarn payload generate graph Quil schema as well as yarn generate types for that schema finally we can rerun our application and while we're rerunning it we can go to our admin panel and we can add those links over to those nav items as soon as the application loads we'll be able to to upload the media files there we go I reloaded the page and now you can see that you can upload New Media or choose from existing I'm going to go upload New Media select file and now you want to find the folder we're currently working on because remember in the public folder and then in admin UI I gave you access to all of the things that you might need such as footer and then icons so first we're uploading for I believe it is Facebook you can say Facebook and save then we're going to go to the second one instagram upload New Media Instagram Instagram as well and the third one is going to be in this case I think I called it YouTube but we have Twitter icon so I'm going to do Twitter save and I'm going to rename it to Twitter or now it's X and Twitter right here feel free to do whatever you want Twitter or X is fine and let's click save so now this is going to give us access to those icons within the code so let's go back to this index and within the button instead of rendering the label we can render a new self-closing nextjs image tag that's going to have have the icon right within but to get to that icon we can say item question mark. link question mark.on as media which is coming from payload types and then here we can say source is equal to Icon question mark. URL let's give it an ALT tag of something like item. link. Lael there we go let's also give it a width of about 24 a height of 24 and a class name of classes. social icon now if I save it all three icons appear and they redirect to proper pages in a new tab the footer is now looking great as well as the Navar it's plain and simple but now the main content is what truly makes this app Shine the products that we see on there in this amazing hero section but before we start working on the hero section and the categories there's one more page that is beautiful and so important which is the create account page and login page doesn't look like something on mobile but check out the desktop view this is great right it really screams Tech products so let's go ahead and create login create account and also forget password all at once I'm going to collapse this close all of the currently open files and hopefully we're getting closer to understanding how payload Works behind the scenes the learning curve is there but as soon as you understand how to use it it becomes such a powerful tool to create not only e-commerce stores but also all kinds of apps that require a CMS so let's get started by logging out if you haven't already and then reating to the login page this is the current login and this is what we want our login to look like quite different right so what we can do is open up the login page right here that's going to be login page. TSX right here within here we want to remove everything that we have within the gutters and we want to turn it into a section that section is going to have a class name equal to classes. login and within it we can have a div that's going to have a class name of classes. hero IMG for our main primary image and then a link that's going to have an href to forward slash and we of course have to import link coming from next link and within it we can render a nextjs image tag imported from next SL image that's going to render the source of SL logo-black SVG with an Al tag of logo a width of 250 a height of 23 and a class name equal to classes. logo if we save this you can see now we only have the logo and we can go below this link and below the div to create the form so we can say div with a class name equal to classes. form wrapper and within it another div that's going to have the class name equal to classes. form container and don't worry we're going to add the classes soon within it we can add something known as render params and this is coming directly from payload to it we can pass a class name of classes. perams below it we can render a div that's going to have a class name equal to classes. form title and right within we can render an H3 that's going to say welcome there we go and right below it we can render an image image that's going to have a source of SL assets slash icons SL hand.png with an ALT tag of hand a width of 30 and a height of 30 as well so that's just a waving hand below this div we can also do a P tag that's going to say please login here and right below we can render the login form coming from payload there we go now of course it's our turn to also style it a bit so in the description down below you can find the index. module. sccss the modified one at least and paste it which is going to completely change the look and the feel we also want to slightly modify the inputs by heading into the input index. module. sccss and here we want to change the Border radius to about 10 pixels that's going to make them a bit rounded we want to change the height to about 52 pixels to increase it we want to change the padding to about 16 pixels as well as the font size to 16 pixels if you save it you can see it looks good and we also want to give it a border of 1px solid VAR -- color- gray 500 finally we can go right here Below in the label and add the font size of about 12 pixels there we go that's going to decrease the font size now we also want to modify those links a bit right now they don't look so good so let's go to the login form so index DSX of the login form let's scroll down to where we have those to Links there we go and let's add a class name of classes. links as well as remove this text this is where customers will log in we don't necessarily need that here and this link as well the entire P tag for that matter there we go that's a bit cleaner also in this redirect right here instead of pushing to account we want to push to forward slash and set the window.location.href to forward slash as well since we added this class name of links we now have to go into this module and modify it on submit we can give it a width of 100% we can add this new DOT Links of display is flex this is going to make them appear in a row align items of Center justify content of space between and a width of 100% there we go that's better already let's also modify the form Itself by changing the width to 100% we don't need this include mid break then and we can remove the width here we can do a gap of about 24 pixels and a margin top of about 30 pixels to create some space there we go that's better already and with that we have successfully went through a couple of files and modified our login page which is now looking much better than the default create an account or recover your password pages so let's quickly navigate to create an account and oh my God would you look at that let's go ahead and modify that one next we can start with going to create a account and then the index of that create account page and modifying the Styles immediately by copying them from the description down below and then pasting the new ones and then we can go to its page. DSX within create account to start modifying it because right now it's not looking that good so we can do almost the same exact thing as we have done with the login so let's quickly go to login page. TSX and let's copy everything that is within the return statement and paste it right here within this return of course we'll have to import the link from next link image from next image as well as exchange this to create account form if we save it you can see that it's going to be working again but of course there's a couple of changes we have to make change this to classes. create account the logo can remain the same the form wrapper and everything everything else is good instead of welcome we can say create account instead of please log in here we can say please enter details and that's more or less it we have a nice looking form there's some inconsistencies with the design here we're missing some spacing and more so we can do a similar thing that we've done before we can go now into the create form or the create account form which is right right here we can scroll down and then within this else where we push to this different account we simply want to push to the forward slash there we go and add the window.location.href to forward slash as well I remember that I had to add this to fully make it work in the form data we can also add an additional field and that form data is I believe right here so we can add a name as well well which is going to be of a type string then we can add an input for that name right here below the first input by duplicating it changing it to name then we can change it to full name required register errors. name and type of text so this now added the full name property right here finally instead of create account here we can say something like sign up and I believe we have a great looking form oh yeah we have to do that styling so we can go to the styles of the create account form we can remove this width and mid break and instead make width of 100% add a margin top of about 30 pixels as before change the Gap to 24 pixels and in the submit instead of changing the margin top we can set the width to 100% there we go that's more like it so now we have our Great Tech Haven create account as well as login Pages done and you can notice how also the images change from time to time the last page we have to focus on is the recover your password page that looks like this and I think you can already guess it but the procedure is going to be quite similar we can close all of the currently open pages as before we're going to modify the form first by going to recover password form and then recover password module as CSS down below you can find the recover password form module. scss and simply overwrite it while we're here let's also go to the recover password form index TS X as well scroll to the return and if not success we can do a P tag right here within the react fragment something like enter your registered email address will send you a code to reset your password there we go password with 1 a we don't need an H1 here rather we just need a form so we can remove this form wrapper as well as this P tag all together and just have the form we also have to remove the closing div and indent it properly the form is going to have a class name of classes. form and within it we have a message we have an input and we have a submit button so now as you can see this is looking even worse than before but that's because we didn't did modify the real recover password page so let's navigate to recover password under pages and let's go to the index module scss first and override it there we go now we can see the background and then we can go to recover password page the real one and you know the drill it's going to look quite similar to login and register so let's quickly go to login page and let's copy everything from the return statement right here and paste it in this return statement of course we have to import the link as well as the image in this case we won't have render prams and instead of login form here we'll have recover password form if we save it it's looking a bit better but instead of classes that that login we want to give it a classes. recover password which is going to bring back that beautiful image we have our hero image then we have our logo as well we can go to the form wrapper and within the form container I was wrong we will add the render params as well and let me tell you why if you add it here and give it a class name equal to classes. perams and save it because this is needed to properly route through URL prams because if you open up this component you can see that they had some problems so to fix this they wrap the component in a suspense component right here and then they render perams component of course instead of Welcome right here we can say something like H3 off forgot password we don't need need this B tag right here and we also need to add a link to go back in case we maybe remembered our password so what we can do is we can put this H3 right here below as well as the div that's wrapping it so that's the form title right here that's going to make it look like this we don't need to wave here so we can remove this image that's a hand but below the render forams we can add a link that's going to have an href of SL login and a class name equal to classes doback link it's going to Simply render an image that's going to have a source equal to SL assets SL ions SL arrow-left SVG Al tag is left Arrow width is is 24 and height is 24 as well so now we have this back arrow and an additional letter L that I added here which I can remove and right below we can also simply do a P tag that says back there we go this is looking good to me and now we have completely customized login create account and recover your password pages of course let's go ahead and test it out I'll try to Simply log in with the account that I've created before as an admin and you can see that worked out and we're logged in this is great and finally now we can focus on the moment we've been waiting for which is modifying the homepage to make it go from this to this yep I know you're excited so let's go ahead and build it out together we can get started by doing the here hero section so let's open up the underscore Heroes that's a folder that's right here there we go so underscore Heroes and we have multiple Heroes here we have high impact low impact medium product and more inside of there let's add a new folder called custom hero within it we can create a new index. TSX and we can start by copying what we have in the high impact here so let's go ahead and copy it and modify this from high impact hero to custom hero now we have an extra hero and we can go to our hero index. TSX component so now under underscore components right here we want to add our hero to the heroes array so we have high impact medium and low impact and at the bottom we want to add a custom hero which is equal to custom hero coming from Heroes custom hero there we go let's go to our existing site and we can see that we have an issue and that is that we're importing the index module CSS but we don't have it so let's create a new index. module. scss within custom hero as well and you know the drill in the description Down Below in the same link you'll be able to find the custom hero module scss you can copy it and pasted right here with that said our app is now functional again which means that we can start making use of it for now the only thing we can do is just modify it slightly so we can see when this hero is actually going to appear so I'm going to comment out everything within the gutters and then say H1 say this is our custom hero just so I can show you how we can get to it because right now we can still see the other one to do that we also have to go to payload Fields so let's go to Fields hero. TS which is right here within the fields within the payload and here at the bottom below low impact we want to also add a new label for the custom hero as well as the value of custom hero there we go we also want to change the condition so here below we have admin condition show high impact and Medi impact but now we want to also add a custom hero here as well that's going to look something like this next we have to go to our page where that hero is going to be showing and that's going to be slug page. DSX written like this so Pages Slug and here we have to show our hero that's going to be happening right here Below in the return statement so we have to figure out if we are currently on the homepage by saying slug is triple equal to home if that is the case then we want to render a gutter and within the gutter we want to render the hero to which we're going to spread all the hero properties else we want to render another react fragment within which we want to have what we had before hero with blocks there we go so now we can display our own and of course we have to import gutter from components gutter now another thing we can do here within this try and catch is we're fetching the document which we want to show but we also want to fetch the categories which we will later on use So Below the page we can say let categories is of a type category which we can get from P types but array of categories and it's going to be set to null by default so if you're wondering why we're doing this well we have to fetch the categories right here because we're showing them them here we have them in a couple of other places as well so we're making our app a bit more advanced than the starter to fetch the categories we can do similar to what we're doing with the page here categories is equal to await fetch docs of a type category and we simply Call It by passing categories plural right here as a string we also want to import some additional classes right here so at the top we can say import classes from that SL index. module. sccss and therefore we have to create a new index. module. scss this one won't have a lot of styles we simply want to import. slash slore CSS SL queries. scss to get the queries and then we want to do a doome class that has a display of flex Flex Dash direction of column gap of 100 pixels margin top of 100 pixels as well make sure to add a semicolon right here at the end and we can also include a mid Brak media query with a gap of 60 pixels there we go so now we're almost done with seeing our new hero but in our terminal we want to rerun the graph Quil commands one more time so instead of reloading our terminal I'm going to open one side by side and then here I'm going to run yarn payload generate graphql schema as well as yarn generate types now if you reload the page nothing will happen but let's go ahead and log in we want to go to the admin dashboard pages and then home now if you expand it you can see that we have the title of this page and you can also see that we can choose from different hero sections so instead of high impact let's choose our custom hero and let's click publish changes it says that this following field has an invalid hero type that might be because we forgot to modify the types so if I go to payload Das types and then we go all the way to where the law impact is we can see that it also has a custom hero so no we didn't forget to add it so one thing we could try doing is just reloading our terminal once again so let's press contrl + C and then Y and then simply run mpm run Dev one more time this should ensure that all of the changes are indeed recognized by graphql as well as payloads admin interface let's wait until the app is up and running again then let's go to our admin panel reload the page and let's change it to custom hero and press publish as you can see the update was successful so now we can go back to our homepage and reload and would you look at that this is our custom hero so we just added a new hero that you can simply pick and choose from different Heroes right here what we can also do is modify the content so here we can choose a custom hero and then you can choose whatever you want to do with it so let's try to replicate what we have on the final site we have unleash innovation in every bite explore a world Cutting Edge Tech so let's just copy this and paste it right here there we go this is looking good to me and later on we can focus on the world of Cutting Edge tech for now the most important thing is that we can see later on what we have under the rich text right here and you're open to completely modifying it and changing the size and more let's also add the links so we can go to our link 01 make it an internal link pointing to product and shop now and we can also upload a new media file so let's go to Media select the file and we're going to go to admin UI hero and choose the hero one right here we can say hero and save there we go we can then remove this second link as well as the media and I just noticed that this icon for the link was not supposed to be here this link will not have ANC but here we have to upload the media for the hero section so let's go here and then upload Hero 1 by saying hero and let's click publish changes now we can preview it as well right here within admin which is going to open it up on our local host but of course we cannot see anything because if we go to our code in our custom hero it just simply does nothing so let's go ahead and customize this entire page I'm going to remove this H1 and bring back everything we had with our previous high impact hero and you can immediately see the changes unleash Innovation shop now and then our hero section let's make this a mobile view and let's style it like this we're going to start not with a gutter but with a section with a class name of hero within it we're going to have a div with a class name of hero rapper and we can also give it some additional Styles specific specifically you want to modify the background image but for that we have to get access to this image right here to make it a background so let's say const media URL is equal to and now we have to figure out how to get to this media we only want to get to it if media exists so media and end and if type of media is not equal to a string then we want to access the media that's hosted for us by payload so we can get into a template string that's going to have the process. env. nextore public uncore serverurl slash media media. file name there we go so now we have a link to our media URL and right here on this div we can give it a style equal to an object where background image is set to a template string of URL and then media URL like this of course that's supposed to be dynamic there we go so now we can style it and you can see that now it appeared as a background image which means that no longer do we need this specific media here so we can remove this entire div below there we go that's more like it but still far away from this beautiful thing so let's go back let's create a new div right here below or within this div that's going to have a class name equal to that's going to be classes. hero textbox within it we want to put the rich text which is coming directly from our hero and then within it we also want to put this array right here that's more like it everything we're getting back from the admin p panel we can see that right here unleash innovation in every bite but we have something else as well right explore a world of Cutting Edge Tech so if we add that here right now below we can for example make this H2 or something like that and now we can publish the changes again go back and reload and you can see the difference right you can automatically style this website and it looks so much better on larger screens but let's compare it with the finished side something doesn't feel right here our text is getting out un leash innovation in every bite if you notice on every size this text is in two lines right so the simplest fix would be to Simply here say unlash innovation in every bite that way that's going to appear below so let's publish changes and reload the page and there we go this is now EX exactly as it is on the finished site so with that said our hero is now done and if you click shop now it's going to point to products so our hero is looking great there is one Improvement we can still do for mobile devices notice these gutters on left and right side and here on mobile it goes full screen it just makes it look a bit better so what we can do is figure out where those gutters are coming from so let's see where our hero is getting cold I'm guessing it's going to be in the components hero well not here but rather in the index of the pages so Pages Slug and here we have the gutter and then we have the hero what we can do in this case is simply set this up as a section and then below later on for all the other content we're going to have the gutter so here later on we're going to put things like categories we're going to also put product Collections and promotions and so much more for now the hero is going to be without gutters and that's going to improve this look of the hero there we go so now we're already getting so much closer to the finished site and once again in case you want to modify anything you just go here and modify directly within the interface the next thing we can focus on is of course going to be the category section it's a beautiful section that's essentially a next step right you go here you see this beautiful hero but maybe you don't want to buy a phone maybe you want to buy some watches TV and home iPads whatever you want it is right here and we can implement it by doing this shop by category section so let's collapse it let's close all of the currently opened files by holding control and then pressing W and let's start implementing the categories now to start working on our categories first of all we want to ensure that they have images and by now by default they don't have them so we need to modify it within payload types so let's go to payload Das types and then here same thing how we have modified this custom hero we also want to go to category this time which is right here export interface category and then on top of the ID in the title which is not going to be optional by the way we also want to give it a media property of a type string or Media or n this also means that we'll have to go to collections for slash categories right here and then here on top of the title of type text we want to make it required to true and we also want to give it this media property by saying name is equal to Media as well as a type is equal to upload and finally Rel relationship or relation to is going to be set to Media you know the drill once you change this you have to rerun yarn payload generate graph Quil schema and you also have to do yarn generate types next we have to reload our app so let's press contrl C and then y clear it and then run mpm run Dev now let's ensure that we are fetching all of the categories that we later on create we we can do that by going toore API SL fetch doc or in this case fetch docs. TS right here we're fetching the pages the products but we also want to fetch categories so here we can say categories where we can specify the query to be set to categories like this and then we also want to do a key of categories that's going to be a capitalized C right here also these categories are coming from graphql categories on top now we want to modify our graphql by going to underscore graphql and then by going to categories right here for now we simply have categories but we want to improve on that a bit further by renaming it to productor categories we want to get the title ID breadcrumbs but we we also want to export just typical categories like this that's going to be a template string where we want to query categories by saying categories with a limit of 300 we want to get the docs the documents for each one of these categories with an ID title media and media is going to have an Al tag a width a height and the URL now we can retrieve those graphql schemas from blocks so we can go toore graphql blocks and we want to scroll down to line 45 and we want to change this over from categories to productor categories coming from categories similarly we want to do the same thing right here on line 66 product categories and finally when fetching the products we also want to display some categories so we want to go to products graphql and we want to scroll down to here line 22 and modify this over to say product categories and of course we have to import it and we're no longer using the previous categories so we can simply remove it right here at the top and I do think we'll have to reload our terminal one more time or rather regenerate the graph field schema because we have just changed it so just rerun both of the commands as before and the other one as well now remember that we had that homepage before so that's going to be on the slug and then page under Pages here I said we're going to render the categories so let's do exactly that we're going to render a gutter that's going to have a class name equal to home or rather classes. home and then right here we have to render the categories but we are yet to create that category component so we can go to components that is right here components and we can create a new categories component so underscore components new folder categories and within it a new index. TSX for now we can just run our afce and make it say categories so now this is going to allow us to import it right here from our page by saying categories make sure that you get one from the components right here and to it we can pass categories is equal to categories we already have access those categories because we pulled it right here before so there we go and of course now it's our turn to dive into the cat categories of course we need to reload our app because we have modified the graph kale config and then once it loads we'll be able to start creating the structure for our categories section there we go if you reload our app you can see that now we're displaying the categories which means that we can start coding them out so let's create a new section and this section has to have its own class name so let's go ahead and create a new index. module. sccss and you know the drill we can simply copy and paste the Styles right here for categories then we can give this section A Class name so that's going to be class name is equal to we have to import classes coming from index. module. sccss and then you can refer classes. container right within that section we want to have another div that's going to have a class name equal to classes. tile rapper and right within it we want to have an H3 element that's going to say shop by categories and we can save it already we're getting there right below we also want to display a link coming from next link that's going to have an hre pointing to forward SL products and it's going to say show all there we go that's better now below the most important thing comes and that is we want to create a new div that's going to have a class name equal to classes. list and there we want to map over all of our categories which for now are coming through props so we can say get categories from props which is of a type categories category array coming from payload types So within this div we can simply go categories map where we get each individual category and for each one we immediately want to return a category card category card this is a new component that we're going to create so let's immediately do that by creating a new folder called category card and within it create a new index. TSX file where you can run RFC and then modify it to say category card and finally also give it a new index. module. sccss and there paste what you can find in the category. module. scss below this video we can also just import it right here at the top by saying import classes from index. module. SS so now we can go back and we can import this category card from that/ category card and we can also pass to it a key equal to category. ID as well as a category itself equal to category so now we can go into the category card and you can see we already see three categories but now what we can do is we can modify their look and feel to look a bit closer this to do that we're going to return only one thing which is going to be a link a link of course coming from next link which is going to have an hre pointing to forward SL products it's also going to have a class name equal to classes. card and within that link we can render a P tag that's going to have a class name equal to classes. tile and it's going to render the category. tile of course the category has to be imported from props so we can say category is going to be of a type category card props which we can Define right here at the top by saying type category card props is equal to category of a type category coming from payout types and and of course that's a lowercase C once you fix it you should be able to see that we have some rectangles but we are yet to modify these to be actual images so as before we have to get the image URL by saying const media is equal to category. Media as media that's just for typescript and now we can provide an additional style property to this link that's going to be background image if is equal to a template string of url media. url now if we save this everything is going to break and if you remember that's because our previous categories didn't really have media files but now we want to upload new ones that have them so before we can see images we have to modify our admin interface so to do that we can go back to our admin interface we can make it a bit larger we can go to categories on the left side we want to remove all three existing categories and then we want to create a new category you can upload a new media select the file and this time go to categories and choose whichever one you want in this case let's do something like laptops so here we can say laptops and we can call it laptops or MacBooks whatever you prefer and you can click save this is going to create a new category let's try to add a couple more for example we can add a new category by going back to categories and creating a new one that's going to be a category of let's first upload a media file let's do something like phones we can say phones here and we can also say phones right here as the title of the category and let's also do one more by going back to categories creating a new one we can upload a new media file and do something like let's do watches and finally a title of watches there we go and click save right here so all three categories are saved there we go now let's collapse this and let's go back to our current website and reload as you can see the categories have immediately changed to watches phones and laptops and if we bring back this style you can notice that now they have their images because the images we just uploaded correspond to specific categories now if you click on it it's just going to point you to General all products not for products of that specific category so this is an extra functionality which we'll have to implement we're going to create a custom hook to manage our filters we're going to need it later on for managing the products as well so let's navigate all the way to Providers which is right here and we want to create a new provider called filter which is going to be within a folder called filter and it's going to have an index. TSX extension within here we essentially want to create a new context so of course it's going to be a use client component because we'll be using a lot of States essentially we want to keep track of all of the currently selected category filters and sorting options so we can say export const initial filter data is equal to an object where the category filters is set to an empty array the set category filters which is going to be of course the setter function is going to be set to an empty function sort is an empty string and set sort is once again going to be an empty function which returns a string and category filters returns an array so we can modify it right here next we have to define the filter context by saying const filter context is equal to create context of initial filter data then we want to export const a filter provider that accepts children because it's a context of course children is of a type react. react node so we can Define that right here or we can simply import react node from react at the top by saying import react node which is coming from react or I believe we can just do react. react node that should work as well finally we want to open up a new function block and then we want to return the filter context so we can say filter context. provider like this we want to wrap the children with this to make it a higher order component and we want to define the value that's going to be passed within it and those values are going to be used State Fields so we can say Ed use State snippet category filters set category filters which is at the start going to be equal to an empty array as well as sort options so we can say cons sort set sort at the start equal to minus created at this simply means that it's going to show the newest products first we of course have to import create context from react we want to import use state from react as well and then at the end we want to pass all of those values here so category filters set category filters sort and set sort it looks like we have to Define all the types properly and you can see some squiggly lines here these are just for tab scripts so no worries about that yet finally we can define a custom hook to consume this context export const use filter is equal to a cback function that calls the used context hook like this used context and we want to pass the filter context to it of course we also have to import use context from react so now we have created this Global provider and of course we have to use it somewhere we have to wrap our application with it and that's going to be within the underscore providers right here we have all of the providers we might ever need so we can also Al add the filter provider right here if we import it from that/ filter and we can put the children right here within it great so what did this allow us to do right now well if we go back to the link right here we can consume and then modify those filters on a global level so to use it we can use the hook we created const something is equal to use filter which is coming from from providers filters from it for now we simply want to get set category filters and then we can add an onclick property to this link and say something like callback function set category filters to be equal to an array where we pass in the category. ID and it looks like if we don't manage those tab script types it's going to complain constantly so let's go back to our filters which is is right here and let's properly Define those types first of all at the top we can define an interface of I context type say that the category filters are of a type string array set category filters which is a Setter function is usually defined like this react. dispatch of a type set State action and then of a type string array like so then we have a sort of a type string and then we have set sort which is another state action or set State dispatch action from react now that we have this we can Define the create context it's of a type I context type right here and I believe that we're good now so if we go back you can see it no longer complains because it knows it's a accepting this string finally we're using States and hooks right here which means that we have to turn this into a use client component so let's say use client and if we reload now if we click on watches not only is it going to go to all products but it also save the state that we clicked on one specific category ID so once we do the old products pages will be able to consume this context and read which category did we click to only display those products and not all products so that's going to come soon as well now you can notice that here we have underlines and on the finished websites we don't so let's modify that further and also there's some extra spacing happening right here so let's modify this further here this looks good to me but let's see where are category card is getting called and that's going to be within our Index right here we're mapping over the categories and each category card is put within this div with a class name of classes. list so this part seems okay as well but we have a warning here or an error saying index. modules instead of module so let's fix this to module and let's modify the file name here so that the styles are actually getting applied and immediately we get this beautiful layout where everything is looking good once we click it leads to all products but soon enough it will lead to a specific category product now after the categories on our deployed website we also have collections where you can show some of the products from specific Collections and even have a pagination right here for now we're going to skip this and just move straight to the deal of the month and that's because I'm so eager to start focusing on the products or even more specifically the product Details page so I want us to do that as soon as possible to have a fully functional e-commerce store so we can go back to the homepage scroll down and focus on the deal of the month right here below the categories to implement this promotion category we can close all of the currently open files and go to that same slug page this is our primary space where we can show all of the section on the homepage below the categories we can do a new component and its name is going to be promotion of course we don't have it yet so let's go ahead and create a new promotion component by going to our underscore components in the source and creating a new folder called promotion we can also give it an index. TSX that's for now going to just do a regular export saying promotion and we can also connect it with an index. module. scss file inside of which you can paste all of the Styles now let's go back to our slug page and let's import promotion from components promotion by pressing control and then space and then clicking it and we don't have to pass anything to it immediately below the categories we can see promotion so now let's focus on implementing our promotion we can get started by importing classes from index. module. sccss then we can wrap everything with a section tag and give it a class name equal to classes. promotion right within this section we can create another div that's going to have a class name equal to classes. text box and within it we can have an H3 that's going to have another class name equal to classes. tile and it's going to say deals of the month there we go we can see it immediately let's also do a P tag and from the deployed site which is going to be connected to the GitHub repo I believe you can take this P tag or you can just write something on your own something like get ready for a shopping experience like never before with our deals of the month that's going to be enough below that we can also show when are these deals expiring so let's go ahead and add a UL that's going to have a class name equal to classes. Stats and right here we want to show some kind of An Li that's going to have a class name equal to classes.at boox it's going to have an H4 in here and it can say something like five days then it can also have right below a label so here we can say days of course it's not going to be only one we have to have days minutes hours and seconds as well so we can turn this into a new component let's grab this Li and right here at the bottom create a new const stat box to make it reusable it's going to accept a label and a value as parameters of course we need to Define the types where a label is of a type string and value is of a type number and then we can immediately return what we copied An Li with days but we're going to modify it to render the value under the H4 and to render the label under the P tag that way we can make it Dynamic so now within this UL instead of rendering this Li we can render a self-closing stat box component that's going to have a label of days as well as a value of and now we need to Define some kind of a time frame so how are we going to Define what time is and when does the deal expire well for that let's first create a new use state which we can just call use State snippet time and then set time right here and the time is going to actually be an object that has days hours minutes and seconds all initially set to zero and we can also import use state from react and don't forget we of course have to make this a use client component considering that we have used state so now we can pass the value of time. days and now we can duplicate this one two three more times say something like hours the next one is minutes and the last one is seconds and we can modify it like so hours minutes and seconds there we go of course everything is just zero now but now we have to figure out how to make it count down to a specific time and in my opinion this is the perfect use case for chat GPT we can say something like write a use effect hook that updates a timer every second until a specific Target date and I believe this is enough information but maybe we can make the target date be equal to current datee plus 7 days so it's always going to be about 7 days and we can save it and there we go we got a response but let's make it modify it so it doesn't return the value rather it sets set time to an object where we have days hours minutes and seconds to the modified time so hopefully this is going to be clear enough there we go now it uses time and set time the target date and it gets values for days hours minutes minutes and seconds and then sets the time so let's go ahead and copy this use effect as well as the target date finally we can paste it right here and make sure to import use effect and then let's look into the target date here it's complaining about the way that it is being done using the target date right here so I guess what we could do is turn the target date into a number and the same thing with current time I believe this won't cause any issues but rather it will help us with our linting so now let's go back to our website scroll down and you can indeed see 6 days 23 hours 59 minutes and 44 seconds in case you want to define a specific date you don't have to make it Dynamic from the current date you can just use a new date and then pass some specific date in the future for example three days for now is fine as well and then it's automatically going to get updated as soon as you reload the page great so with that said we have added this new promotion and now our homepage is looking better than ever we have a phenomenal hero section we have the categories deals of the month and then finally the hero with some additional features that are store supports so what do you say that we move over to the only place that we can go to right now from multiple places in our homepage such as if we press shop or if you press categories all of these buttons lead us to the products page that's the forward SL products route so let's turn it from this to this that's a big difference right we have different filters here we can even impl pagination later on a lot of exciting stuff is happening so let's collapse this and let's modernize this page we can do that by navigating over to our products and then creating a new page. TSX right within it one has to be within the slug and then one has to be within just products where we can create ource and we can call it products there we go and now we can see just the page where it says products we're going to do this entire page from scratch so I can show you how we can fetch different products right here let's start with the layout so first we can wrap everything in a div and of course that div has to have a class name so we can create a new index. module. scss file right here this one is going to be pretty simple we're just going to import _ cssc common. scss or I don't think we need to add the extension we can leave it like this we can say container is width of 100% And later on we'll style the products too for now the container is fine so if we go here we can give it a class name is equal to we of course have to import classes from SL index. module. scss and that's going to be classes. container right within this div we can display a gutter which we need to import from components gutter it's going to have a class name equal to classes. products we're going to add that soon now right within the gutters later on we're going to have our own filters component so what do you say that we immediately create a new folder for filters within the products called filters we can also give it an index. TSX file where we can run rafc and just say filters and we can also create its corresponding index. module. sccss which you can simply paste here from the description down below so now we can import those filters coming from that/ filters and Below filters we'll also be using something built into payload which is blocks it's coming from components blocks and it allows us to pass which kind of layout do we want to enable so there we can pass blocks is equal to and then layout we don't have it yet but we will have it soon and also a property called disable top padding is set to true as we won't need it right here so now let's figure out how we can get to this layout well first at the top we can Define let page of a type page coming from payload types or null is equal to null by default we're going to have a similar situation for fetching the categories because we need them for the filters so we can say let categories is equal to or rather of a type category array coming from payload types or null is equal to null then we can open up a new try and catch block where in the catch we can simply console. logd error and in the try we can redefine that page by setting it equal to await which means that we have to make this page a sync and we want to await something known as fetch doc coming from API fetch doc make sure it's doc singular not plural we want to fetch a doc of a type page it looks like this and we can call it in pass which specific page do we want to fetch so we can say fetch collection of pages where slug is products okay so we want to fetch a page where we have products and we can Define that it is a draft mode by saying is draft mode essentially drafts allow you to build on top of versions functionality to make changes to your collection documents and globals but publish only when you're ready it allows you to check out how something is currently working so what we can do is we can also Define those drafts by enabling the draft mode we can do that by saying const is enabled which we can rename to is draft mode is equal to draft mode which is coming from next heads there we go and now we can simply Define is draft mode while we're here we can also fetch the categories by saying categories is equal to await fetch docs in this case plural so we have to import it again which is going to be of a type category to which we pass a string of categories and that's it it's going to fetch it so now how do we get this layout well we can destructure it from the page so that's going to be page do layout if we now save this our app should be working again and now we can see filters which is great that's here and then we can see all products this is coming directly from blocks because right now those blocks are tied to our product's layout we're going to modify that later on finally we can add an HR component no it's not human resources I'm guessing it's just a horizontal rule so we can add that import it from HR and it adds this nice line to separate everything so now the question is is how can we further style this product's page right now we have just redefined it in a way so how can we further style it well first let's not forget to add the class name for our products that is right here so that's going to be dot product it's going to be in a grid layout so here we can define a display of Grid it's going to have a grid Das template Das columns one F FR right here and then 75% and we can leave a gap of about 60 pixels there we go that's now making some space for the filters let's also include a large break where the grid template columns is going to be set to 100% and a gap of about 48 pixels so now on mobile devices still we'll be able to see everything but as we expand we can see the f filters now let's talk about the filters for a bit so if we go to our undor providers and then the index right here we can see that we're wrapping everything with the filter provider but there's one more place where we have to also refer the filters and that's going to be within the collection archive so there's a special component called collection archive it's a large component and it has everything to do with sorting and filtering you can see pagination as well so right where this component starts which is right here at line 38 we can say const category filters as well as sort is equal to use filter which we need to import then if we go into the results set results right here we're passing page and all the other stuff then if we go a bit down all the way to line 90 7 where we're modifying the search query we want to actually make the filters work so we're going to rename cats from props meaning categories from props into category filters and category filters. length as well as category filters category filters and category filters it's going to be of a type string right here so we can say cat is a string and return a cat just like so of course we have to properly wrap it and where we close this use effect we also need to add one more thing which are the category filter instead of cats from props there we go so now we're going to actually filter things once we apply those filters but it's complaining a bit right here in the collection archive about the sort property that we used because we have previously defined sort on line 48 so let's look into it it indeed is right here we're getting it from props so we can remove both the sort as well as the categories right here because now we get them from our filters we are again back at the working state which is great and now we can start focusing on our filters component first things first I'm going to close all the files and I'm going to open up the index DSX of the filters here we can immediately import classes from index. module. sccss and we can wrap everything in a div that div is going to have a class name equal to classes. filters within it we're going to have another div and within that div we're going to have an H6 that's going to have a class name equal to classes. tile and it's going to say something like product categories if we save this you should be able to see that it's going to appear right here then we need to map over the categories and display them like this of course on larger devices they nicely appear like this so let's do that right now by going right here below the H6 we can create a div that's going to have a class name equal to classes. categories within which we can Loop over those categories and the way we can get them is by using the use filter component we have created before so right at the top we can say const we can destructure the category filters the sort the set category filters and the set sort which is equal to use filter which of course we have to import from use filter and then of course we'll need a function to modify that filter const handle categories which is going to be just a regular function that accepts the category ID on which we clicked which is of a type string and later on we can Implement its Logic for now within this div let's map over our categories by running the categories. map where we get each individual category and we don't return an instant return rather we open up a function block and then here we have to figure out if the selected category is selected so we can say const is selected for now we can set it to false and later on we can figure it out now if you've been paying attention you can figure out that we should have used lowercase categories not uppercase but we don't even have access to categories right here only category filters so we need to pass categories as props to our filters we can do that by going to where we're calling the filters which is on our products page right here and we need to pass categories is equal to categories then we can right here Define them through props by getting the categories and defining their types as categories of a type category array and of course it has to come from payload types then we can make the is lowercase now for each category we have to also return something and in this case we'll return a checkbox of course payload has created its own checkbox component so we can create a self closing one give it a key equal to category. ID give it a label equal to category. title if we save this now we get an error saying that that this property checkbox is missing some types but hey that shouldn't really break our app should it now I want to share a quick tip with you whenever you use some custom hooks that are using some other states or whenever you use some form components that behind the scenes might be using some specific react State functionality or browser events or anything like that you need to make this component use client even though we're not EXP licitly using use state or forms or event handling right here checkbox maybe is which breaks our application so if we add the used client right here and it still doesn't work let's try to figure out why that is I'll try to give this checkbox some other properties as well we might need to give it a value which in this case is going to be category. ID and I'm going to also give it is selected equal to is Select Ed and finally the onclick Handler equal to handle categories if we save it now it complains that the value is not of a proper type and if we go to the console we can see the errors that says that there's a type error cannot read properties of undefined reading replace at checkbox that's interesting so something with our categories and mapping over them and displaying checkboxes is breaking our app so in this case what I'm going to do is I'm going to create custom checkbox and radio button components it might be better than to use the checkbox that's built into the form right here something breaks with it so let's go ahead and comment it out for now just briefly and then let's go to components create a new folder called checkbox within it we can create a new index. TSX as well as an index. module. sccss of course the styles are below you already know the drill we want to focus on the e-commerce functionality and payload here not necessarily styling every little detail and then in this case I'm going to provide you with the checkbox component as well so I'm going to Simply paste it here you can see it's a typical checkbox component where we created from bear Beginnings where we have a label and an input and then we receive all of the props we're going to pass to it so now if we bring back this checkbox and import it now coming from components checkbox you can see that now we have watches phones and laptops which are the exact categories that we have created within the CMS before now how can we figure out if this category has been clicked for real well let's say category filters do includes the category ID so if it includes the current category ID it must have been clicked for now this is just fake clicking it's going to work once we implement the handle categories function but for the time being let's go below this div and let's create an HR kind of just a simple component of a horizontal rule to create some space let's add another H6 right here that's going to have a class name equal to classes. tile this HR can also have a class name equal to classes. HR and the title can say sort by so here we can do sorting on top of filtering by creating a new div that's going to have a class name equal to classes. categories and within it we can create a new radio button component which we can create in the same way that we created the checkbox by going right here to components creating a new folder called radio giving it a new index. module. sccss which you can copy from below and also giv it a new index. DSX which is a simple component which you can also copy from below and then paste here similar thing we're doing with the check box we have a label value and then we simply put it in this regular HTML 5 label input combo so now if we go back and if we import the button from components radio button we can pass it some props such as label is set to latest value is equal to minus created at we can also pass is selected and that's equal to if sort is triple equal to minus created ad then we're going to know that it has already been clicked we're going to have an on radio change which can render the handle sort function and we can give it a group name equal to sort of course we're still missing this handle sort so let's create it right here con handle sort is equal to just a typical empty callback function for now we can duplicate this and create another one that can say oldest and instead of doing minus created ad we can simply do created ad everything else is the same so now later on we'll be able to sort and we also have our wonderful checkboxes right here now what do you say that we make them work the only thing we need to do to make our sort work is to Simply get the sort value right here of a type string and then say set sort and then pass that value if we save it we can now switch between and you can see it's actually switching from latest to oldest and to make our filters work it's not going to be that hard but it will require a bit more functionality than the sort we have to figure out if the current category filters do includes the category ID that we're currently clicking on if it does then we want to set category filters to new category filters containing all the filters without the one we just clicked on so we can say const updated categories is equal to category filters. filter where we want to filter out the current ID if it's not equal to category ID so we keep everything else besides the one we clicked on and then we simply call set category filters is updated filters else if we want to add a filter then we simply set category filters where we spread the previous category filters and append the additional category ID so now we can actually switch between we have watches phones and laptops and for none of these products apparently we don't have anything or no we do I think if we do laptops no phones no watches no currently we have no products under these categories and that makes sense because we have just created them so it would be our turn to add some of the actual products if I just reload you can see the products though but then once we start adding or filtering them then they get removed because the search is doing its thing so finally let's adjust this shop page from our admin panel as well we can go to our admin panel right here if we log back in of course we need to enter our details and then go to Pages select products and then you can choose content here you can see all products and this corresponds to what you can see right here this is just the regular intro content which in this case we don't need at all so we can remove it then we have populate by collection specifically collection to show is products and the limit is going to be nine three rows of three now if you publish changes and go back and reload you can see that now we can only see the products but those products don't really look good do they they don't seem to be in sync with what we're aiming for which is is kind of a clean minimalist apple style website and to achieve that look we can navigate to the card component within underscore components card here we have our product card with the categories and all the other good stuff but we want to simplify it further it's going to end up being simpler than what we can currently see here so how can we do it well first let's put this side by side and then we're going to wrap everything not in a div but rather in a link so we can turn this into a link which of course needs to have an href equal to href it's going to have class names of card and then class name the div within so this is going to be the div is going to have a class name of media wrapper where we can have this meta image as well as the other media file below it we want to have another div with the class name of classes is. content here we want to remove this entire categories part we don't want to show the categories here then we have a title to use which is going to be simplified once again it's going to be just an H4 that's going to say something like title to use there we go if we save it description is gone then we have a description which is going to be a class name of class body if we have a description we simply return a P tag with a sanitized description so this is looking good to me and finally the doc but then we want to style it and you already know the drill down below is going to be the modified index. module. scss which you can paste right here and that's going to turn these cards into this it's a bit different but still not entirely there now the reason why this is not working perfectly yet is because the products are part of something known as a collection archive so we're modifying the product card themselves but still we have to modify the wrapper that's wrapping them and to do that we can go to a collection archive the component that wraps the products and specifically we want to go down to its return statement right here there we go so there we are returning a div with collection archive and we need to remove this gutter to have less space when we do loading now we want to simplify this layout a bit now here we want to remove this Gutter and that's it for our page range then we go down we remove this other gutter as well right here and then we have a div that has a class name of classes that grid where we go over different elements and each one renders a card that has a relation to product with a doc result and show categories we don't want to wrap it in a div anymore of classes. column because they're not going to be showing up in columns they're going to be showing like this finally the pagination is looking good so now let's also apply the styles for our collection archive and that's going to be just some minor changes but for your convenience once again I left it down in the description and now we're getting even closer to our final products look and the last thing we need to do to achieve it is to close these two files and go to the price file so that's going to be components price inside of here you can see the price and that price is a bit different on our end here we also have an add to card button which we don't need in this case so right here we can remove the add to card button by simply deleting it we can also remove this remove from card Button as well and we can can remove the quanti we don't need it in this case we're going to simplify everything to have that clean minimalistic look and then we're going to end up with something like this which is already closer than what we had we can also remove those two buttons right here on top now we can also modify our price styles by going to our index. module right below align item Center we can also add justify content and then make that space between we can also modify the way that the price shows by giving it a font weight of 400 and giving it a font size property of 18 pixels to make it a bit larger we can also give it a gap of 12 pixels instead of four we also want to modify it on small brake devices by saying include add small Das break and give it a grid Das template Dash columns to make it appear in one FR like this and we can also modify the font size to 16 pixels and we don't need an add sign here with small break so after we fix this you can see it's looking good on small devices and as we expanded it's still looking good and the last thing we need to do is go to the general app. sccss file and specifically go to the Anchor tag right here on line 112 there we want to add add a text decoration of I think you can guess it none this is going to hide that ugly underline and going to make it look so much better now this is still far away from this but believe it or not that's just because of the images if you look at it our design is the same we just have to modify the way that these images look like so let's go ahead and go to our admin dashboard under products and let's delete all three products that we currently have it's as easy as that so now if we go back and reload you can see search produced no results so now if we go back we can create a new product and to check which product is it going to be let's go to upload New Media select the file and then as you know I have already prepared all of the products for you if you go to public admin UI products in this case let's go with Apple Watch series 9 and say something like Apple watch n there we go and click save now of course we also have to add a title so let's go to the deployed website open up the Apple watch and let's copy the entire title and also paste it here in the title as well as in the SEO title we can also copy the description and paste it right here in the description great now the last thing we have to do is add a new layout and we're going to choose a layout of content finally click publish changes our product has successfully been published we can see that by having one product here and later on we're going to also attach a striped product to it which means that we'll actually be able to purchase it so if we now go back to Local Host 3000 products you can immediately see our great Apple watch appear so now let's add another product specifically another product belonging to another category so we can then test out the filters and sort as well so let's go back to our editing in our products admin dashboard and let's create a new product let's first go to our upload New Media select the file let's do something like this Apple iPhone 15 and say Apple iPhone 15 and click save we can go go to the deployed website and try to find our Apple iPhone 15 amongst old products we can copy the complete title and paste it right here at the top under title and then under SEO title as well and let's go ahead and copy the entire description and paste it right here let's not forget to go to layout and also choose content right here and publish changes our product has been successfully created and now if we go back back and the reload you can see that now we have a phone and an Apple Watch so let's try to filter them but if we do that nothing is happening yet so before this works there's one more change we have to make let's collapse this just a bit and let's head to collection archive this is a component that we have modified before but now we have to put our category filters coming from this specific use filter hook that we have created to use so right at the top let's say const let's destructure the category filters as well as sort which is equal to use filter coming from provider filter and then we don't have to use the sort from here that's coming from props anymore so we can remove this sort and we can also remove these categories categories from props because now we get our own category filters with that said we can go a bit below and whenever we say cats from props we can now rename this to category filters I believe if you double click and press f2 on your keyboard oh no it's going to say you cannot rename this element so we have to do it manually so let's simply copy cats from props press controll F and then here you can press this little arrow and replace and here we can say category filters so this is going to replace if you click right here all six instances of cats from props to category filters now we're almost there but as you can see it's complaining about cannot find category filters did you mean category filters it does look like I misspelled it above so let's properly import it as category filters right here there we go and now if we go a bit below we can also modify the type no longer is it going to be of a type category it's going to be of a type string and we don't have to get the cad ID we can simply just return a cad not a real CAD just a category and we can join them with commas and if we scroll down since we used rename all it also got renamed right here in the dependency array of the use effect so it's going to get updated whenever our category fills filters change so now if we save this file and go back you can see that the page is working again I'm going to expanded a bit let's see the product categories on the left side and let me click watches and this time we get search produced no results let's also try to do phones and once again we get nothing well at least we do get some kind of an error message or some movement happening but now we have to figure out how to add those products to specific categories how to give them an attribute of that category so going back to our admin dashboard let's try to see oh there we go on the right side we have categories select a value and this right here is surely a phone so let's publish changes let's go back to products and let's also add a category for our Apple watch that's going to be a watch let's click publish changes and if we now go back reload the screen and click watches there we go we have our Apple watch and we have our phone which means that all of our filters are working perfectly and we can also sort by latest or oldest that means that our entire authentication page is now done our homepage is also looking wonderful with categories hero section deals of the month and the footer and now we have implemented the entire shop page with product categories and sorting the next step of course the product Details page so now if we click on a specific product you can see that the image is quite large the product hasn't been added to stripe yet and this doesn't really look good we want it to look like this this is going to be our new modified and kind of minimalistic apple style product Details page so let's collapse our screen close this file and let's get started by modifying this to look more like this first let's adjust the default product hero we can do that by going to underscore Heroes and then forward slash product there we can modify the hero of that specific product so what we can do is scroll all the way to the top right here line 26 and we can remove this entire first starting fragment talking about stripe we'll surely connect this product to stripe later on for now we can remove it there we go and also we need to close the closing fragment as well if you save that it's looking good now our gutter is going to have a class name of classes. product hero then we can remove this content div so just remove it and of course we have to close it right here below the add to card button so we can remove the closing part of that div and we want to move some things around here here we have our categories but in our case we want to show the image first so what we can do is we can move this entire div that says media and media wrapper above by copying it and then putting it directly within product hero we don't need a class of media we're just going to keep the one that says media rapper so you can delete this one and we have a media wrapper there we render a placeholder image if we have one and then we render a real image finally we can remove this entire part about a meta image and Rich Text we won't be needing that and then after the closing of the actual media wrapper we can create a new Dev that's going to render the details if we search for details we don't have any right now so let's create a new class name that's going to say classes. details and then within it we can render an H3 that's going to render the title property and we can give it a class name equal to classes. tile if we save this you should be able to see that now we have a title right here and it's looking closer to what we have here so we can definitely remove this entire title right here an H1 right there we go okay we're getting there now let's modify the classes a bit we have to make our image look more like this our title is smaller description smaller and we're going for that minimalistic look so you can go to product index. module. sccss and you already know the drill where you found all the other styles you can find this one that's going to be product. module. scss and you can paste it save it and then we're going to look like this now we're still not done there are still some modifications we have to make so let's try to go below the title and while still being inside of the details we can create a new Dev that's going to have a class name equal to classes. category wrapper within it we can then render these categories so let's take these categories and move them a bit up to within the category wrapper and if we go back it's going to look like this and then we want to modify this fragment right here it's going to be a P tag because we want to give it a class name as well specifically a class name of class say. category so this is going to give it that pop or not yet but it will soon now next to the title we have if not is last then we display an empty space and after that we want to add a span element this span is going to have a class name equal to classes. separator that's because this is going to be a simple separator character just a straight line like this and then below this div we can render a P tag that's going to Simply say in stock and it's going to have a class name equal to classes.in stock or just stock is going to be fine there we go so now we say it is in stock now we have to further modify the spacing here because it's not as it is right here we have to say description so we want to go below this div where we have the inst stock and we want to render our price we can pull the price from below we already have it here so let's pull it right there and save it and then we can have a div with a class name equal to classes. description that class name doesn't have to be on the P tag itself and then we can remove all of this content from here and we're going to make a much simpler description with an H6 that's going to say description and we can simply render a P tag that's going to render the actual description if we save this you can notice now it says description now we also want to move our price next to the description right here so they're in the same level and we still cannot see the price as we can see it here so we'll be able to make a small modification soon so to check why our price is not showing let's dive into it by control clicking it and then double clicking right here which is going to lead us to the price component here we have the product we're setting the price with the actual price and with quantity we have a use effect to set it up and then finally we have a div within this div we check if the actual price is not defined and if the quantity exists and then we return a div with a class name of price where we say price. with quantity so this is looking good to me and here we're calling it in the right way so let's let's try to expand this just a bit and you can see it's not responsiveness it's still not showing but we do have an empty space for it right here if we go to another product maybe go back to shop and then the Apple watch you can see it's not showing still now ask yourself why or better yet have we ever added the price in the first place I don't think we did so if we go back to the admin dashboard and click on the Apple watch here if we expand it it's going to be easier to see but we have to add a price somewhere specifically the price is going to get added once we connect this product to stripe then it's going to pull the values directly from there so this product is going to mirror the product on stripe so more on that soon but for now it's good to know that our layout is good it's just missing the actual value finally below this div we have the add to card button that accepts a product and a class name which looks great immediately below we have related products and if you check the deployed version you can notice that here we don't have any kind of a description rather we just have a list of related products so how can we make that happen well we can go to the product Details page by going to slug like this specifically slug under each individual product that's the product Details page here we're rendering different blocks of this page and we can see a block that says something like the products displayed here are individually selected for this page same thing that it says here so how can we modify that well first of all we don't need the layout so we can remove it from here we can remove this blocks of layout as we don't want to render any additional blocks then we can turn this into just a regular simple react fragment we can modify this from H4 to H3 to make it a bit bigger and the only thing you have to do delete this object that contains this P tag right here so we simply delete it if we save it you can see that related products got a bit bigger and there's no description left that's great you can notice that now this is touching the button which is not really the best look we want to give it so let's go into related products SL index. module. sccss and let's make some minor tweaks we can give it a class of do related products which is going to have a width of 100% And then we want to modify the grid so in the grid let's remove everything we have right now besides the display grid let's give it a padding of zero then a grid Das template Das columns repeat three and then min max 30% and one F FR I don't really use grids often but in cases like these they can really be useful of course if you spell columns correctly now we can show three related products then we can also delete this column span and instead of a span of six we can only give it a gap of 20 pixels and on small break we're going to say template Das Columns of 100% finally since we don't have columns half or/ thirds we can completely remove those classes and just say do tile font weight is 400 and margin bottom is about 30 pixels which is going to give us the space that we need of course only when we actually go to the related products component and then on top right here within the gutter add a new H3 that's going to have a class name of title and it's going to say related product of course this has to be classes. title if you save it now you see two related products so let's remove the other one and we can do that by removing this intro content from here and we don't need to import it anymore from props so now we have only one and we can significantly simplify the return right here we can look into the docs if they exist that's great if not return null and then the only only thing we need to return is going to be the card we can remove the columns that we have here by simply saying return card and we can leave everything else as it is of course while removing the closing brackets parentheses and everything else so now if you save it and reload you can still see the product but it kind of stretches too much so of course let's see if we have done our classes properly our related product has a width of 100 here we have a position of relative then right here within the grid we have a display of grid a padding of zero we have grid template Columns of relite no it's going to be repeat that's a mistake on my end and we can also give it a gap of 30 pixels so now if we save it you can see that now our product appears in 1/3 but that's not exactly how it should look like if we're in small devices they should go one below another in a column not in a row so let's see what else do we have here instead of within the column our small break and mid break should actually be going within the grid so this was a mistake on my end so now if we save this you can see on small devices it's going to behave differently or it will behave differently once I specify columns correctly right here and there we go now we're good now if we compare this with the finished website you can see that it's looking great but we're missing some space right here here below the add to card button don't worry we're going to fix it really soon and I think it's this part of the same problem where here we're also missing some space between the products and here we have some extra space so if we compare it as you can see it's looking quite different and I think that's because the description and add to card should go within the div where the title and everything else is whereas here we put it below so let's go to our heroes and then then for SL product here we have our description and everything so let's see if we're properly unwrapping everything in our divs here we're starting with the details and we're ending it here but rather this div should be ending after the add to card button if we now put all of this inside you're going to notice that the situation is going to change now recently the app started breaking a bit but if you just reload one more time it should be working and now everything fits nice nicely and you can see the related products below and I believe we can fix this related products issue by going to our collections SL products and then index.ts here we have a special layout property and we're saying that this content has to be required and that shouldn't really be the case for our app why because if you check out our products you can notice that we have added the layout but it's not really NE Neary we're never using it so we can make the content or the layout not required in this case and then we can rerun the two commands we used before yarn payload generate graphql schema while that is happening we can stop our application from running by pressing contrl C and then Y and once this command runs we can also generate the types what this is going to do is it's going to modify the payload types so if we go here here under layout or under product specifically you're going to notice that layout will now be optional so if we rerun our application by running the mpm Run Dev and if you reload your admin dashboard go back here and delete the layout and publish now it's going to allow you to do so we can do the same thing with our Apple iPhone 15 Pro as well remove and publish so now if we go back and reload the app still breaks so if we open up inspect and then go to console we can see a couple of different errors well it's more or less one more of the same so here if we look into it it does point us to related products line 32 that could be useful so if we go back press contrl P go to related product index. TSX line 29 or 30 you can see that we're mapping over a card but we're not passing a key that might be the error you know all of these times in all of these videos when I was telling you to add a key on the element you're mapping you thought okay it's just a warning it doesn't matter but in situations like these in bigger applications it truly does matter because it can interrupt the flow of the application well I'm just guessing maybe this is not the solution but let's check it out I'm going to pass a doc Dot let's see ID as the key this is the best key we can give it not the index we're getting from here great so now let's save this and let's reload the error seems to be gone that's good if I reload one more time it seems to be working well that's great so now let's add some margin to this related products header we can do that by going to related products index. module. scss and then give it a padding top of something like VAR D- base this is going to just give it a bit of padding I think that's more than enough so with that said we have a great looking product Details page which we can expand and ensure that it looks good it still does and we can also check the mobile view looks amazing as well so now of course the next logical step is to add the product to the card we can do that already the functionality is there but the card now looks like this and we want it to look something like this there we go much cleaner much better so let's go from this to this to do that I'm going to collapse her browser close all the files and then open up the cart for/ page. TSX page inside of here we can remove this entirey hero saying that this is a cart and what it is for so we can scroll down and we can take everything from the hero including the hero to above right below the fragment and we can remove it if we save it already that's a more minimalistic cart then right here below the gutter we can add an H3 it's going to say just cart and right here under blocks we can add the disable bottom padding is set to true I think a Shand is just by doing this automatically that's going to be set to true so now we have something resembles this a bit more but of course we have to modify the Styles so if we go to index. module. sccss we can remove this message and add a DOT container that's going to have a margin dashtop of 50 pixels to create some space it's also going to have a width of 100% finally on small break so include small- break we're going to give it a margin top of a bit smaller 30 pixels and if we go back we have to actually utilize that container so we're going to turn this fragment right here into a div with a class name equal to classes. container if we save it you can notice it looks a bit different give some spacing but still it's far away from looking like this so now we'll have to modify something known as a cart page and then a cart item cart item is this the item in the cart you can see it looks quite different it's essentially one row or one line of items here it's just big it's in your face and we're going to make it look something like this so let's close the page and do that right away to get started we can head to pages is and specifically we want to go to cart where we were just before but now we want to create a new folder within the cart called cart item within it of course we create a new index. TSS where we can run ource we can of course rename it to cart item and we're going to also create a new index. module. scss within the card item and there you can paste the corresponding card item module scss and then go back here and import it by saying import classes from index. module. sccss next we can create a simple card item by wrapping it in An Li so it's a list item that's going to have a class name equal to classes. item and within it for now we can simply render an ag6 that can render the title for now static but soon enough Dynamic now if we go back to our website nothing really changed so where can we call this cart item we're going to call it within cart page index. TSX here we have a lot of stuff happening right here so we are initializing the cart if it's empty we show that it's empty if it's not we show the items and so on so you can see a lot of stuff is happening here but we want to get rid of most of that but for now let's simply utilize the cart item we can do that within the UL so if we search for items list you can see that here we're calling the items and then here we're mapping over them cart. items. map for each one we get a type off a quantity product and item and then we return this entire fragment for now we're we're going to delete that entire fragment going all the way down we don't need that much stuff and the only thing we're going to return is a cart item so let's specify it and import it from do/ cart item and close it right here there are a couple of things that we need to pass to it such as of course the entire product we also need to pass the title we can then pass a meta image not a mate image but a meta image right here equal to meta image uh all the things that we were previously displaying right here we need to pass the index as well we can pass the QT y as quantity and the add item to cart which is going to be a function of course adding the item to cart so let's save this and let's go into the cart item and let's accept all of these props right into it we can accept a product a title A meta image a quantity or qty an add item to cart and then an index as well since we'll be mapping over this we can provide a key right here equal to let's do title all products should be unique and in that case I believe we don't even need to pass an index so if I go back and remove the index we should be good to go now back in part item we're going to also Define a new use State and that's going to be quantity and set quantity as well at the start set to qty so we're going to use this default value but we'll also allow our users to modify the quantity later on in case they want to so let's import use state from react and immediately therefore we have to make our function or our component a use client component now of course if you reload the page I don't believe it's going to work or yeah it will but it says your card is empty so I'm going to go back to shop and I'm going to read a product right there add to cart there we go there is one item in your cart now we can only see the title so now we know what we're working on and now that we know that we can start working on jsx but before let's create a couple of functions we'll use such as decrement qty that's going to be just a typical react Arrow function we of course want to have increment qty and we're going to have the enter QT as well so const enter qty because we'll be able to enter it manually as well and that should be good we can start creating the look of our cart item to look like this so first we're wrapping everything in An Li and then right here we're going to then render a link component this link is going to have have an href equal to SL products SL product. slug with a class name equal to classes. Media wrapper within this link we're going to render a new Dynamic block saying that if there is no meta image then we can render a span saying no image but right below that if there is an image so if meta image and and type off meta image is not equal to a string then we can simply render that image by using the built-in media property which is coming from components media to that media we can pass a class name equal to classes. Media we can pass the IMG class name which is going to be equal to classes. image and of course we want to pass the resource equal to meta image and finally give it a property of fill and of course we have to import the link coming from next link if we do that and reload the page we still cannot see anything I think that's because our card got emptied again so before I add another item to the cart let me go to login I'm going to sign in with my account using this beautiful signin page I get redirected to this great page where I already have one product in my cart which is a watch and now we can see the image and if you click on it it's going to lead you back to the watch Details page and then you can go back and continue now below this link we want to have a div that's going to have a class name equal to classes. item details within that div we want to have another div with a class name equal to classes. tile wrapper and of course there we can render an age6 property where we're going to render the dynamic title there we go Apple Watch series 9 right below we can render the price which is coming from undor components SL price and to it we need to pass a product equal to product and a button equal to false as it's not a button it just says the price so if we save it you would hope you can see the price but you cannot because remember we didn't yet connect this product to strip we're going to do that as soon as we're done with the cart now going below this div we can create a new div that's going to have a class name equal to classes. quantity within it we can have another div that's going to have a class name equal to classes. quantity button and on click we want to decrement quantity in this case so that's going to be decrement quantity and there we want to render an image so that's a self-closing image tag which we can import from next image it's going to have a source equal to for SL assets SL ions SL minus. SVG we can also add a few more properties such as the AL tag of minus a width of about 24 pixels and a height of 24 as well as well as a class name of classes. qtn BT there we go so now if we save it and if we properly spell height in class name we should be able to see this quantity button but it looks like our cart got emptied again that's unfortunate if I go back to shop yep it still seems the cart is empty if I go to homepage it is empty so I have to read the product okay that's definitely something we can look into later on so we don't have to reload every time but for now let's just duplicate this entire div right below and of course we're going to make it say increment qti we're going to also render the plus SVG change the AL tag to plus and above that increment we also want to have an input so keep in mind on the left side we have a minus on the right side we have a plus and then here we have an input for manual entering of the quantity so that's going to be a simple input that's going to have a type is equal equal to text a class name equal to classes. quantity input value is set to quantity and on change is equal to we get an event and then we call enter quantity to which we can also pass an event and whenever you call functions like this you can simply then use the function declaration there we go so now if we save it you can see that we have minus one plus it looks like we have in right here which we don't need and this is now getting closer to what we need let's see if we have properly spelled quantity it looks like we have but this minus button is still a bit off so if we look at quantity button it's supposed to be a quantity BTN that's how we have declared it in Styles so I can modify this as well as this to quantity BTN and now we are good of course they're not going to modify the values yet but we're going to implement that soon finally we want to go three divs down one 2 three and then here we want to show the total so we can do a div with a class name equal to classes. subtotal wrapper and there we're again going to show the price of course we need to pass the product as well and as before we're going to pass a button set to false but this time we're going to pass quantity equal to quantity so we're not referring to one product but multiple in case there are many and finally we also want to render a remove from cart button coming from components where we want to add a product into it just like so so now we have the remove Button as well now as you can see it's looking quite similar of course once we connect the stripe we'll be able to see those two prices right there and you can see we'll have to modify the actual trash icon because this remove is a bit ugly so let's move into the remove from card button by control clicking it and then here we have a button but instead of saying remove this button can render an image that's going to be a nextjs self-closing image tag coming from next image that's going to have a source equal to SL assets SL ions SL delete. SV G we can also give it an Al tag of delete a width of 24 as before a height of 24 and a class name equal to classes. qtn button or BT for short and there we go and if you have that ugly button outline this class should remove it so remove from cart it is all unset that removes all the original button Styles so now this is looking great and with that our cart item is done so we're getting close to having this now we can focus on this nice looking summary and log to checkout button so let's go back to cart page and let's go below the cart item that's this HR which is a horizontal rule we have it here as well on the deployed website we don't have it but rather we have this box so let's go ahead and and implement it together we can remove both the HR and the H5 button we can leave for now but let's place it in a new div this div is going to have a class name equal to classes. summary and we can put the button right within it there we go so if we save it and go back it didn't change too much but this now allows us to create a couple of rows of different prices so let's create a new div that's going to have a class name equal to classes. row and within it we can have an H6 that's going to say summary we can also give it a class name equal to classes. cart total so if we save it you can see the summary but I noticed it's way too high so we should have actually wrapped our cart items in a UL so right here you can add a UL an unordered list and properly close it right here at the bottom below the cart items right here there we go we can give that UL a class name equal to classes. items list and here if we do have the card so if it's not empty that is this part right here we can simplify some things we don't necessarily say there are this many items in your cart the users can see that visually from our new design so we can remove almost everything that we have here and rename the div to classes. cart wrapper within that cart wrapper we can have another div within that div we can show the cart list header which is essentially going to be a div with a class name equal to classes. header and then below that head we want to show a cart list item so cart item list so that means that we have to pull this entire UL right here above within this div there we go and save it but now it's not going to allow me to save it because I have to properly close our divs I do believe we have one div extra so I'm going to remove this one and then we're good I'm going to go back to shop and add a new phone and we can see it right here at the top but now everything is a bit more structured and we can polish our header Now by correcting this to class name and then here we can have a P tag that's going to say products also right below we can have a div that's going to have a class name equal to classes. header item details there we can render a p tag that's going to say Quantity and Below we can render another P tag that's going to say sub total it's going to have a class name equal to classes. header subtotal like this with a lowercase s and you may be wondering hey why did we add the products quantity and subtotal right here doesn't make any sense well if you check the deployed website you can see that they're hidden on mobile but if you expand they nicely show the products quantity and subtitle right here so the only thing we need to do to make that happen is go to our index. module. styles of the card page and then modify it right here by replacing the CSS Styles sheet that's going to make it look much better with that said we can continue where we left off right here in the classes. row where we show the summary we can duplicate this entire div with a row and the second one instead of summary is going to say delivery charge that's going to be a P tag which we can duplicate below and that can be set to zero and we can duplicate it one final time right below and here we can say something like grand total and then we can render a variable of cart total. formatted there we go and now we have everything we had before but still keep in mind that the price is zero because we haven't connected our stripe products we're going to do that soon if we are logged in this button is going to say check out else it's going to say log to checkout which means that it's working perfectly there's also the continu shopping which is good but here we also have some additional text which we don't need so to get rid of it we can do exactly what it says this is a custom layout building block configurable in the CMS so let's go to the CMS let's go to Pages cart and then here if we expanded we can see some kind of a content and there we go in the content we have our column which for now we can completely remove and publish changes if we do that and reload the page this block is completely gone so it looks great on mobile we have our footer we can continue shopping which also works and we can go to checkout but before we go to checkout let's just check how it works on large devices there we go we're almost there I can see the quantity is above the title not the actual quantity whereas on the final design it is right here so let's look into why that is not working we can go to our quantity which should be right here in cart page and then here we have a cart list header the simplest possible fix would be to add about two MTP tags I think one is not enough but if we add two it's going to move it just enough so that it actually says quantity above the quantity so now if we expand it it's looking good on all different devices and that reminded me hey we haven't yet implemented the functionality for the quantity so for that we have to go into our cart item and then we have to implement those functions decrement increment and enter quantity doing that is quite straightforward let's implement the decrement first there we can say const updated qty is equal to if quantity is greater than 1 then quantity minus one else we're going to keep it at one then we want to set quantity to be equal to updated quantity and we want to add item to cart with a specific product like this inside of an OP object but we want to pass the quantity which is going to be set to updated quantity which we want to convert to number there we go now we can duplicate this right here below and paste it to increment quantity this time the updated is going to be simpler it's just going to be quantity + one not minus one we set the quantity here and we update the product and finally for entering the Quant quantity we get an event right here and then we get const updated qty is equal to e Target value but we do want to convert it to a number there we go and we don't want our typescript to complain so we can say this is of a type react dot change event HTML input element there we go and then we can do the same thing we've done before set quantity and add item to card so now we can modify the number of items and we can also manually change it this is great and we cannot go below zero let's also try to remove it that works as well if we go back to shop let's try to add both products that we currently have the iPhone is added and let's also add the watch there we go this is great now now the next thing we have to do is actually connect this products to stripe so that they have a specific value connected with them because right now we cannot see their price so before we move to check out we're going to have a big and quite an interesting task which is to integrate stripe quite exciting great job for coming this far into the video you're amazing and now let's Implement stripe to get started with adding stripe you can go to stripe.com and I say it every time but I'm going to say it again this is one of the most beautifully designed landing pages as of today so without looking at it too much let's go to start now and then either create your stripe account or sign in once you log in you can open up your dashboard specifically you need to toggle on the test mode then you can go to developers API keys and then you can copy your public publishable key which we can move to our code Base by going right here going to our EnV and then you can simply paste it right here below under next public strip publishable key similarly you can reveal your secret key copy it and then paste it right here under stripe secret key once you do that it says reload EnV but I always like to just reload my application manually as well to ensure that the changes have been saved so let's rerun our application then you can go back to your admin dashboard open up products go to one of our products go to product details and here it's going to ask you to add a stripe ID or select a new product from stripe or we can create a new one if we haven't yet so go ahead and click this link once you're here we can add Sim similar data that we have here in the SEO section of our product so this one is going to be Apple iPhone 15 Pro we can also copy the description under product tax code we can do something like let's do a technology maybe or it's going to be Electronics let's see electronic this is electronic software let's try to search for Phone mobile phones there we go feel free to choose whatever you want this is Forest ing purposes only and then we have price information which is really important we can choose a standard pricing model and you can enter a price for example let's do something like 999 in this case let's do American dollars you can choose whether you want to include tax in the price or not and this is going to be a one-time payment and it is as easy as that now you can save your product and you can go back to your admin Dash dashboard scroll up reload the page and under product details select a value for a stripe product and there we go we can connect the two let's publish changes and let's do the same thing for Apple watch so we can go here Apple watch product details create a new one we can immediately copy the product title as well as a product description this is going to be a smart watch there we go and we can make it standard pricing let's do something like $300 American doll and it's going to be a one-time payment now I just noticed that I forgot to add an image so let's also upload an image it's going to be this Apple watch and we can save the product and we can also go back to our previous Apple product and we can go edited so you can go under edit and then you can upload an image so here we you can choose Apple iPhone 15 and upload the product there we go let's go ahead and connect our Apple watch as well by going here reloading and then selecting a new value of Apple Watch series 9 and click publish immediately if we go back to our website you'll be able to see that now all of these items have corresponding prices attached to them not only that we can see the individual price and we can also see the price get updated as we have a larger quantity of that item trust me working on an e-commerce like this from scratch and making sure that all of these variables are correct like the individual item price that the price matches to stripe product then the quantity price and then the total price and then especially if taxes are playing a role or delivery fees it's just a mess but thankfully payload makes it so easy to implement all of this so now if you want to just get one of each item the prices are reflected and the checkout button works and leads you to our checkout yeah we're there we're the final step of our journey but now it's our turn to turn this checkout into a checkout that's going to look a bit more like this clean simple as before so with that said let's collapse this right here and let's implement this wonderful inline checkout which looks great for mobile devices as well to get started we can first simplify our checkout by going to checkout page. TSX here as you can see we have a lot of stuff which we don't necessarily need so we can go all the way to the return and remove this entire fragment and everything that is within it and when I say everything I really mean everything besides this bottom checkout page part so let's wrap everything in a simple div like so and then let's put the gutter within the checkout page right here within it if we save this you can see that now we have just the products here and we can also give this div a class name equal to classes. checkout the gutter doesn't have to have a class name then we can quickly go to the index. module. sccss and instead of checkout page we can do the dot checkout class and get give it a margin of 50 pixels in top and bottom and zero on left and right a width of 100% and include small Das break margin top 30 pixels like so so now if we save it we're just going to get some additional space and that's it we have the products and we have our checkout now we can close those two pages and then go to checkout page index TSX so this is really similar to what we had with cart if you remember we had cart item cart page and then the original page inside of which we created our cart item and let me remind you what that is it looked really similar to what it looks like on the checkout so for that reason I'm going to provide you with the files for the checkout starting with the checkout item we can create a new folder right here in checkout called checkout item it's going to have a new index. DSX and since it's so similar to our cart item I'm going to give you access to the code right below so simply paste it here and you'll be able to notice that it's using that same media to display the image and then it shows the quantity and the subtotal and we also need to get its corresponding scss file by creating a new index. module. sccss and pasting the Styles right here and then we can close those two and modify the checkout page not this one but rather the index within the checkout page to actually use that checkout item we can override the entire component with the code that I'm going to share below once again it's quite similar to the code we had in the cart so once you paste it here you'll be able to see something that looks like this and we can repeat the same thing for the index. module where you can override the classes once you do that we'll have something that looks like this a wonderful looking and quite minimalistic and simple check out with the same thing we had before in the cart which is a summary of the items we're ordering but this time right below we have our payment details and even if we expand it you can see that it looks great everything is visible right away and you can enter your car details so what do you say that we try purchasing an iPhone and an Apple Watch whenever you're purchasing something with stripe there's a test card that they give you it goes 42 42 42 I think you get the idea just keep saying 42 until the end for expiration you can also enter any date in the future and you can enter a random CVC you can choose your country and press checkout and just like that we have our order confirmation page and while we're here let's style it to match our minimalistic theme we can do that by going back and then heading to order confirmation page index. TSX within here we can first change this button that points to orders and we can simply make it point to account slash orders slash order ID and we can do the same thing right here slac account SL orders then we can go to the corresponding index. module. sccss keep in mind we're within the order confirmation page and we only have actions here so let's give it a justify content equal to Center as well as a margin top of about 30 pixels okay that's better already especially on larger devices and let's also style our regular not order confirmation page but just the order confirmation by adding a couple more class names such as padding dashtop of 50 pixels display of flex Flex direction of column align items of Center justify content of Center and text align of Center as well and finally the P tag within the confirmation page can have a margin top of about 16 pixels there we go so now if we expand it you can see that now even our order confirmation page looks just a tiny bit better but now if you go to view all orders you're going to notice a 44 page that's because I purposefully changed the URL we're going to the original account page is simply under for/ orders and you can still see it if you go there it looks like this and then the account page looks something like this everything is on a simple page and while it works it doesn't look so good since users really don't care what's happening after they purchase your products this is an optional part it works it's functional you can see purchase products and orders so all is well but as you know here at JSM we always like to go a step further so I have prepared a challenge for you modifying all of the payload components and understanding how it truly works definitely has a learning curve and to ensure you've learned how to properly use it which means traversing the files folders and creating new files components and styles the challenge for you is to convert this to this this is a much cleaner looking account page which matches our minimalistic Vibe you have our orders right here you can go to personal info and change it go under my purchases my orders or even log out everything from this account screen and to achieve this look we'll mostly have to modify all of the account pages so if you go to Pages you'll see an account folder where we have an account form and we'll be able to add many other files and folders here later on we'll need to modify the form as well as the original account page to make this happen it doesn't have to look like this but you can use this just as an example of course you'll be able to refer to the finished deployed website and in case you don't want to follow this design but do it some other way I still invite you to do that because from modifying the class on your own not by following the video tutorial you'll become an independent developer that can now do it by itself so you can now achieve things by yourself after having learned all the useful Knowledge from this video and of course if you get stuck there's going to be a whole section with all of the code needed to achieve this look in the same markdown where you have been getting all of the other code for this project so far once you complet it your codebase should look something like this everything should be contained within the account folder in the pages folder there's going to be an account form orders purchases user info and within orders we also have a specific order ID the goal is to build on top of what payload starter template for e-commerce provides us with and then add and change your own Styles once again the entire code as well as the entire zip of the completed account folder is going to be down below so in case you get stuck just delete yours and add a new one that's going to give you with this wonderful new beautiful look and with that said we're getting really really close to running our app in production it's all starting to look so good now before we deploy our app there are a couple of fixes we have to implement one bug that you might not have even noticed is what happens if we switch our device theme to dark I'm going to do that right now and reload the page and as you can notice we have this dark background here here and half of the text is not legible so to fix this we can go back to code and navigate to theme index. TSX right here on line 49 where we're setting the attribute of data theme of theme to set we can just make it the default theme like so and also set theme state to default theme and then we can right here modify the theme to be also the default theme so now if we save it and reload the page you can notice we're back on life even though my device is set to dark the second fix is not for a bug that we have created but recently there is a specific unsolved bug in njs unhandled runtime error so sometimes in our code we do get this unhandled runtime error and this issue still hasn't been solved it's happening only in production in a couple of cases I as you can see we would have know is the same issue in production but thankfully there is a quick fix and that is to go to init theme index. TSX and then here we can simply comment out the before interactive strategy that way it's not going to apply it and that's going to get rid of that error that we might have seen in the future if we didn't remove this line great the fixes are done and we're one step closer to deployment but before we proceed we have to ensure that our product IM images that we upload on Local Host are the same on our production application as well and thankfully to ensure that payload has created a payload cloud plugin it's an official plugin that connects our payload instance to the resources that payload Cloud provides essentially giving you access to file storage so how to use it we simply have to install at payload CMS SL plugin Cloud by going here and running it in our second terminal mpm install add payload CMS SL plugin Cloud then we can scroll down to accessing file storage from local environment this is what we want to do then let's copy it go back to our EnV and here we can paste it right at the bottom you're going to notice that a couple of these such as Port are going to be the same so we can simply remove the port from here here as we already have it above mongodb is going to be in the databases Tab and I think we already have it it's the same one as the database URI here so we can paste it payload Cloud project ID you can get from settings and then billing so if you open up your project on payload and go to settings and then billing you can see your project ID which we can copy and then put it right here as payload Cloud project ID and the last one is payload secret from settings environment variables so right here we should be able to see our secret there we go almost all of the variables are here so if we search for secret we're looking at payload secret and specifically this is going to be the one at the bottom so you can simply copy it and paste it right here usually never share this with anybody else in this case I'm just sharing it as these codes will be deleted right after the video recording is done now we still have plenty of these variables to fill so we can fill them by going to file storage and then all of them are here so we'll have to copy one by one so let me put this a bit to the side we have a Cognito user pool ID so we can copy it and simply paste it right here that's going to be userpool ID then we have the userpool client ID which is going to go right here then we have the identity pool ID which is this one to the right that's going to go to the identity then we need the bucket and we can get to the bucket by expanding this a bit and finding bucket name it's right here we also have a bucket region right here so let's copy the EU West or whatever else you chose and then we have a password which you can find right here by simply copying it and pasting it and I'm going to wrap it in string signs just to be sure right here and with that I believe we have successfully filled in all of the variables as well as the payload secret and we also have all of the previous ones right here so all of this is looking good I know there's a lot of keys take your time while copying this over and ensure that you copy the right once but essentially you just have to match the name here to the name of the environment variable with that said I'm going to reload our terminal we can wait for our server to start and now you'll be able to see that even our hero image is right here nicely synced as well as all the other images if we go to our phones you can see we have our phone image right here as well so why have we done this well now we're syncing the images from a local host to our production environment as well so no matter whether you upload or create products here or in production it's going to work if this doesn't work immediately for you try to give it 1 to two minutes and if the hero image won't show after a couple of refreshes just re-upload it and then restart the server and try again and it should be there let's try to log in one more time there we go these images are here as well we can get in and let's go to shopping this is looking really good but let's go ahead and add another laptop as well we can do that by going to our CMS products and you already know the drill create a new one upload a new media in this case it's going to be let's do this one 15inch MacBook Air so we can say 15 inch MacBook Air save and from the deployed website and we can find it on the deployed website by going to laptops you can see how fast the app is on the deployed version we can copy the title copy the description as well and the meta image I believe should be getting read correctly and don't forget this SEO title should also be here within our main title as well then we can go to product details and we can create a new stripe product you see how easy it is now that you know what you have to do once again we're going to copy the title we're going to copy over the description as well and we're going to upload an image then this is going to be a laptop so let's say personal computer uers and we can charge something like 1,600 USD for it and it's going to be a onetime payment let's click save product let's go back and publish changes on this product and then under product details you can select a value and choose a 15in MacBook Air and publish changes once again if you go back you should be able to immediately see the laptop on your screen but as you can see the image is broken so let's try to fix it together if I go here and try to re-upload an image by going to meta image and upload it and let's try 15in MacBook Air once again and click save you can see that still the image doesn't get uploaded correctly and I like it when that happens in a tutorial because it allows us to debug this together one thing that we could try to do is go back to our code and then notice this media folder here are all the images we have uploaded so far let's delete it we don't need it anymore as now our files are stored on the cloud so if we do this and try to re-upload the image one more time and say 15in MacBook Air and still we can see that even though it's a good thing to remove that media folder that didn't fix our upload a error a quick look into our terminal is going to immediately point out to the error it says error getting the file from cloud storage both user pool ID and client ID are required so let's go to our envs one more time and they are referring to the user pool ID and the client ID so let's see where those are we have a user pool ID right here which we have added and the client ID right here both have values attached to them oh but maybe the way I pasted them didn't add them to the same line so if I just remove it oh now it's in the same line there we go and I have to do it for all the other ones too it needs to look like this there we go that's better and if I expand it you can see that now all variables are connected to specific values so now I'm going to stop our serve from running and run mpm run Dev one more time and now back in here let's try the upad load for the third time third times the charm as they say so now if I say 15in MacBook Air and save you can see that now the image appears so if we publish it and go back and reload everything works perfectly and it was just a small mismatch with our envs but now we know that they're good so if you're experiencing any errors just please ensure that the envs are exactly as they should be so the only thing we need to do to get our app deployed is push the code we have so far as you can see I have 46 commits right here you might have a few more but in any case we can open up our terminal stop the app from running and then run get add dot get commit DM and then we can do a meaningful commit message such as Implement e-commerce functionality and finally we can do a get push this is going to automatically trigger out the deployment but just to check that that is truly the case we can go to our payload expand our browser fully go to overview and you can see the status is online and it is currently building and we got an error which is totally fine whenever I deploy something for the first time in most cases I have an error it could be the envs it could be typescript errors whatever it is we're going to get to the bottom of it together and before doing that just ensure that your proper commit is getting deployed because sometimes it can be late in my case it is but you can always click trigger redeploy manually after pushing to ensure that the correct commit gets redeployed so let me just reload the page right now and if we go down we can see some of our errors here we can see that the build has failed specifically it's a typescript error and this happens often I mean think about it we've just built a huge e-commerce application with a couple hundred files if not even more it's possible that we forgot to add a type somewhere so just in this case you can go to your code and you can go to next. config.js within here right at the top you can add a new object called typescript and you can simply say ignore build errors is set to true usually in a real world application we would go across the entire application and fix all the errors which I still recommend you to do but just to finalize the deployment process we can do it like this and then just do another commit by saying get add dot get commit DM ignore typescript I'm going to add in parenthesis only for now so we know that we have to get back to it and then a get push now I believe that payload will Auto automatically figure out that we started a new push and you can see I didn't even have to reload the page and it says building ignore typescript so let's give it a couple of minutes and hopefully this time it is green and there we go this time the build is complete so let's scroll up and click on your url that's going to lead you to the deployed website now looking at it at first everything seems good we have our Navar we have our hero image but if we scroll down you can notice that we don't really have any categories right here or at least it appears to be that way but don't worry about that at all we're going to re-upload those images so everything works perfectly even in production let's start by closing all of the other files we currently have open and let's simply navigate to for SL admin then you can sign in with the same account you've had before and then go to Media remember how we implemented that plugin well now is the time to re-upload the images and every image we add from now on is going to go to the file storage bucket that's deployed online so we can retrieve all of those assets but that goes for all of the assets we have deployed before so if we go to the page to you can see all of the hero images Twitter links everything we uploaded before we need to re-upload it so go to media and then let's start one by one first let's go to Facebook remove it right here and then reupload it we can go to our public admin UI footer and we can add Facebook there we go that is saved we can again go to the page two we can do Instagram as a matter of fact let me just open up all of these in a new tab there we go that's going to make it just a bit simpler I don't think we need those and then on page one you can do the hero as well if it's not here for you for me it is and also all the other products we have uploaded so far then just go one by one this is the Instagram one remove it select the file and read it close it remove it read it save it and just keep repeating that for other images here we have our hero as well so let me just add a new hero that's going to be under admin hero Hero 1 and finally we have the last four this is going to be the Hero 2 there we go and we have the three categories so let's add laptops that's going to be right here under categories laptops then we have our phones so under categories and then phones and finally we have the watches so right here we can add watches and press save in case you need to read them for the product you have added so far you can also add them here I have already done that so I have my laptop my phone and my watch so with that said if we now go back to our new deployed website you're going to see that the hero is here as well as our categories deals of the month look great feel free to add some image right here on the right by playing a bit with the layout and we have our footer icons and if we navigate to laptops we have nothing there as we forgot to attach the laptop category to this laptop but we do have a phone a laptop and a watch and as you can see all of it is functioning perfectly in our deployed application how great is this that you can have your deployed application up and running in no time if you go to checkout you're going to notice a little error but that's totally okay we simply have to update our EnV keys to ensure that we are now in production and not in the test version with that in mind if you had any issues with the deployment whatsoever just message payload on their Discord they're really prompt in replying and they'll quickly help you out with that said huge thanks to payload not only for sponsoring this video but for creating such a comprehensive piece of software that will in my opinion become the official nextjs CMS especially with the changes they're making right now and as I said before don't really worry about the pricing because their versel free tier is coming soon and you'll be able to deploy your projects freely and with nextjs in mind I must not forget to mention our ultimate nextjs 14 course I've worked for months on this course to ensure that it is the best and the most upto-date nextjs course out there the most comprehensive one as well if your goal is to learn how to develop modern web appli ations like these companies do and truly use nextjs the right way the way it's supposed to be used with all of these new features to go from this to this then you're in the right place because we're going to do it with deep Dives build and deploy a complex app and active lessons so you can test your knowledge all of that is covered and the link is in the description with that said once again huge props to you for coming to the end of this video and building such a phenomenal e-commerce application thank you so much for watching and have a wonderful day
Info
Channel: JavaScript Mastery
Views: 125,927
Rating: undefined out of 5
Keywords: javascript, javascript mastery, js mastery, master javascript, next 14 tutorial, next 14 project, next 14 server actions, next 14 auth, next 14 js, next 14 e commerce, next 14 course, next, next js project, nextjs 14, next js ecommerce app, next js ecommerce store, next js ecommerce 2023, next js ecommerce template, next js ecommerce site, ecommerce react, ecommerce website, ecommerce nextjs, payload cms, web shop, online shop next js, payload cms ecommerce, ecommerce app
Id: 3JUsg-WsU9o
Channel Id: undefined
Length: 232min 16sec (13936 seconds)
Published: Fri Dec 01 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.