In this chapter, we're going to go ahead and build the basic layout for our app. As you can see on this screenshot, the basic layout will include our sidebar and our navbar right here. The full components will be the sidebar itself, sidebar sections, these and this, and then sidebar items like home, subscriptions and trending, and history, liked videos and all playlists. Then we're also going to develop a navbar with the search input and sign in component. So this is the search input and this is the sign in component.
In order to do that we're gonna have to add this logo right here and I have prepared that right here in this gist so you can download it using the link below or you can just use my source code and go inside of the public folder. You're gonna learn about the public folder in a minute. So what we're gonna do is let's start by adding this to our project right so I'm just gonna go ahead and right-click save image and download this and then what I'm gonna do or can I maybe just copy the image yeah I think I can also maybe copy it? Just go inside of your public folder and let's try. I cannot paste it here, so I'm just going to go ahead and drag it inside of my public folder.
There we go. I'm going to rename this to just the logo.svg. And there we go. Right. So it looks like YouTube's logo, but it is not, right?
I just made it in Photoshop. Great, so we now have this logo right here and we can already try it out on our homepage. So I'm just gonna go ahead and do bun run dev and I'm gonna refresh my page here to ensure that it is running and I'm gonna use the image from next image, right? So we can remove the button import here and I'm gonna give it a slash logo.svg with a height of 50 and a width of 50 and an out of logo like this. So make sure the logo.svg is exactly what you have in your public folder here and you should be seeing the logo right here.
Great! And then after that let's just for fun add newtube text here and as you can see it doesn't exactly look like we are planning for it to look like, which is a bolder font and a different font here. So let's go ahead and learn how to change the font of our project. So for that we're going to visit our source app folder layout.tsx. This is also known as the root layout.
And inside of here they already specify this Geist font. So what we're going to do is we're going to remove this. We're not going to be using that font. And we're going to import Inter from Next Font Google. So we're going to be using the Inter font.
And we're going to remove these two variables and we're going to replace it with a single called inter. We're going to use the inter class and we're going to execute it and let's give it subsets of Latin. So now we are using Google fonts with Next.js integration and we have that font inside of this constant. So what we can do now is we can go inside of here and we can simply remove everything inside and just do enter the class name here like this. So now this will use the new font, right?
So what we can do already is we can go ahead inside of our page.tsx and give this new to a class name of text extra large and font semi-bold and tracking of tight like this and there we go now it looks much better exactly as we're gonna want it to be right here great So you've learned how to add an asset to your public folder, you've learned how to use an asset, just make sure you have added the height and the width. So this image component requires the height and the width. As you can see it's gonna give you an error if you don't use it. That's because the image component will automatically optimize images for you. You can of course also use the normal image tag if that's what you want.
It's still going to work, but it's not going to be as optimized. So for this tutorial, I will mostly use the image. In some cases I'm going to use the native image element, but most of the time this is what we are going to use. Great! So we just added our logo asset and now let's learn the basic app router folders, right?
So I just want to check this and let's get this out of the way great now let's learn basic app router folders okay so for example we are right now on localhost 3000 this is our root page If I go instead of source app folder and if I create a new folder called feed, for example, let's imagine that's how we're gonna call our homepage, right? Feed. And if I create a new page.tsx inside, it needs to be called page.dsx and it needs to be inside of the app folder like this. And if I go ahead and simply export the default page component and give it a div feed page like this, What's gonna happen now, so what's crucial here is that you do export default. Please don't forget to do this, right?
Save the file, make sure it's saved. And now go to localhost 3000 slash feed. And there we go. You can now see the feed page. So that's how you create routes inside of Next.js 15.
But there are a couple of more things that you can do. For example, you can do a subroute. And while we learn how to do a subroute, let's also learn how to do a dynamic route. For example, let's do video ID inside of square brackets like this. Keep in mind that I have used the capital letter I for ID.
And inside of it the same thing, page.tsx. I'm going to go ahead and do another default export here. I'm just going to call it page. It doesn't matter what the component is called. And I'm going to call this feed or let's call it video id page.
So now as you can see this is not clearly defined what goes here. All that we know is that it's a sub route of a feed. So if I go to slash feed slash 1 to 3, it will load the video ID page. If I go to 3 to 1, it will also load the video ID page. If I go ABC, it will do the same thing.
So it's dynamic. It doesn't care what it's being passed. But here's what it's useful for. So inside of page.tsx, there is a way to extract those params and render it out here. So we can easily do it just by doing params like this and then I can do video ID params.videoID.
Let's see if this will work. There we go. So you can see that it works, but in case it doesn't work for you, don't worry. It probably means that Next.js has officially deprecated this. I say deprecated because this is not how you should do it.
It works and it's great because I can demonstrate how it works. So if I go to slash feed 123 it will now show 123. So this is basically a video ID. That's what it serves for. It's going to give us something to query the database with, right?
But first of all, we have a problem. If you go ahead and visit your server or your terminal, you're going to see this. The route feed video ID used params.videoID. Params should be evaded before using its properties, and you can learn more here. So dynamic APIs are now asynchronous.
This is a change that has happened in the Next.js 15, which means that whenever you're using dynamic APIs, which are params, search params, cookies, draft mode headers, any of those things, you need to await those things. So this is what we have right now. This works, right? Params, params.id. It's literally the exact thing we're doing.
Params.videoid. But it will issue a warning. It still works, but this is not how you should do it. So how you can fix it is, this is their solution if you are fixing this in a large code base. So they added a code mod, which goes throughout your entire project and fixes it for you.
We don't need that. What we need to do is learn how to properly parse this. So what we have to do is well first of all let's go on interface page props params video id let's mark this as string let's add page props here there we go no more errors right but still this doesn't fix our issue I just added the types What we have to do is we have to mark this entire component as an asynchronous component and we have to give this a proper return type. So this will be a promise which returns an object of video ID. And now we are getting the same error here that we are getting here.
Now it makes more sense for us what we have to do. So that's why you should always know what you're expecting. So now let's do the following. Let's extract the video ID from await params. And now let's use the video ID.
There we go. What I'm going to do now is I'm going to scroll all the way to the bottom and just leave a couple of empty spaces here. I'm going to go to my localhost and I'm going to refresh. Everything still works fine and this time no errors at all. So in order to use dynamic APIs like params, in this case, the video ID right here, you have to await them.
If this didn't immediately click for you, don't worry because we will encounter this again and again, and it's gonna become more clear the more we work with this. One thing that you're probably asking is how exactly can we async this, right? What exactly are we awaiting here, right? That may be confusing to you if you've never worked with Next.js before? Well that's because this is actually a server component, right?
And now I think you just have even more questions but you can try and do this server component. If you go ahead and refresh this you're going to find that console log right here in your terminal server component. So basically you can also see that here in the inspect element, but you can also see that it says server here. Whereas if you were to mark this as use client, first of all, you're gonna get a bunch of warnings here. That's because client components cannot be asynchronous components.
Client components cannot do this dynamic API routes. They can do it, but they have to use a special hook for it, right? If you want to use client components, in Next.js you have to mark your component as useClient. And I think a better way of explaining it is to go to another page like feed right here, which doesn't use the dynamic API endpoint. I don't wanna go too deep into this.
I don't wanna scare you off or confuse you. I promise you it is gonna become a very simple once we start to leverage the server components so you can actually see what they're useful for. I think that's the best way to learn, right? I can theorize about what server components are all day long, but until you actually see what they're used for, I think only then is when it's going to click for you. So don't give up yet if you find this confusing or unusual, right?
If this is your first time with Next.js, you're probably wondering what the hell is a server component. So let's go back inside of feed page.dsx and let's change our URL to go to the feed component. There we go. My apologies. This one.
Feed page. There we go. And Inside of here, I'm going to do the same thing. I'm going to do cons of log, where am I rendered? And when I refresh here, you can see that it's rendered on the server by default.
So server components will be able to do things like const, you know, data, and you will literally be able to do database. I don't know, select from videos where equals videos ID 1 to 3, right? And you would literally be able to render out data.name in here, right? Imagine you want to do this. You would be able to do this in a server component.
Server components act like an API, right? Imagine you're on the server. That's what a server component is. We're going to leverage this to prefetch our data and then we're going to leverage the client component to enable the reactivity that we are used to. So I'm kind of introducing you into server components now.
I promise I'm going to go deeper into this in the actual chapter dedicated for this. So let's go ahead and of course remove this and just write the page back. So what I want to show you before we actually go and build our layout is that if I add use client here and then refresh this, now you can see that it is first of all rendered twice and second of all, well, no server. And you cannot see it, well, you can still see it here. Let me just add some space here and then refresh oh looks like you can still see it here okay I did not expect that I I thought it was not going to be rendered when it's in use client here but looks like it is okay but you can clearly see that it no longer says server What can you do when it's in use client?
Well, you can do things like use effect, right? Use effect is something that you would not be able to do in a client component. So I'm gonna console log this inside of here. There we go. It works just fine.
And now you can see that you cannot see it here in the terminal on the server because this use effect runs exclusively on the client. But if I remove use client, what's gonna happen is you're going to get an error. You're importing a component that needs useEffect. This React hook only works in a client component. So I hope this kind of gives you a very, very brief introduction into server components and client components.
Client components, which in Next.js you have to always explicitly mark with useClient are your usual components that you're most likely used to. Whereas server components are the new type of components which can fetch the database and we can leverage them for pre-rendering, pre-fetching, basically making our app very very fast and once they actually click for you, you're going to like them. I promise you. At first I was very you know confused about them. I didn't understand why they were the default component here.
You probably noticed that right? They are the default component instead of the app folder everything you add here is a server component that's quite unusual you probably are not used to that but once you get a hang of it it will prove to be quite useful great so we've learned the basics of that And now let's go ahead and learn about another. You can remove, actually keep the video ID. And let's go inside of feed here and go ahead and add a layout.tsx file. So layout is another reserved file name.
And you also have to do default export here. So layout, and instead of here, let's add layout. What's gonna happen now is that just make sure you've added this instead of the feed folder. What's gonna happen now is that if you go inside of slash feed, it's just gonna render layout. If you go inside of slash feed it's just going to render layout.
If you go inside of slash feed one two three it will also just render layout. That's quite unusual isn't it? That's because layout functions work in a specific way. Let's create an interface to make this easier for us to understand. Layout props will always have children.
Like this. Not node, it's React node, like this. Let's assign layout props and let's destructure our children. And now let's render the children. Now everything is back to as it was.
Feed 1 to 3 or any other ID renders that. Slash feed renders the feed page. So what's the purpose of this layout file? The purpose of this layout file is exactly as it stands for, to create a reusable layout across components. If I were to go ahead and add a div here and say, I am a navbar, like this.
Let's give it a class name of padding4, background rows 500 and the full width. You can see that now this appears on my feed page and if I go to slash feed slash 123 it will also appear here. So this layout file is exactly what we need. That's why I wanted to explain it to you. Because this, the navbar and the sidebar will be inside of a layout file.
And what you're seeing right here, this part, this will be our page.tsx component. And this will be our layout component. Let me see, can I draw on the picture? I can. Great.
So this part will be our layout component, right? This part right here. All of this is our layout and the rest is going to be our page component. So this will be reusable, right? No matter which page we are on, this part will appear the same.
That's what we want. That's what I wanted you to learn the basics of this. And I think that we can now cross off this learn basic app route folders. Let's go ahead and mark that as learned. Great.
So this is what we are going to do. We're going to learn about one more type of folder and then we're going to go ahead and build something. I promise. I know this went longer than you probably expected but I think it's important to explain these things for you. I'm gonna remove the entire feed folder now and I'm gonna show you one cool thing.
I'm gonna create a new folder but inside of parentheses and I'm gonna call it home folder like this. Now what I'm gonna do is the following. I'm gonna go ahead and remove this. I'm sorry I'm gonna close my terminal. Basically, I don't want my app to be running, just because I don't want to confuse my hot reload.
Then what I'm gonna do is I'm going to copy page.dsx right so I recommend you copy it as well you can also move it but then you're gonna cause some well let me show you if you move it right here click move you're gonna get this update imports for page.dsx You can press yes for this if being asked, and then you're going to have this weird unsaved file coming from .next slash types slash app. So basically what's going on here? This is just cache. The cache is being confused. That's why I recommend that you shut down the app just so you don't have some funky errors that will confuse you but aren't actually real.
If this happens to you, you will see one unsaved. Make sure it's the one in .next folder slash types slash app. You can click on it, you can go inside and save the file and close it. If you think you've done something wrong, don't worry at all. So ensure that you have moved the page.tsx which was in the root of the app folder.
You should now have it moved inside of home which is written inside of parentheses. Very important! Make sure it's written inside of parentheses and just for fun let's remove the .next folder. Not any other folder just .next. Remove it like this.
I want you to learn to not be afraid of that weird folder because that folder is just cache if you do bun run dev again let's go ahead and there we go it's back right here it just rebuilt the entire thing so dot next folder can sometimes get confused when you move around pages and layouts, right? If that happens, if you think you've messed up, just remove the .next folder. It will regenerate. Don't worry about it. So Now our slash feed does not exist so let's go back to localhost 3000 and you should still see the page file, even though it's inside of the home folder, right?
If I change in YouTube too, it's going to change here in the root of my application. How is that possible? It's inside of a folder. That's because Next.js has special rules for how you name your folders. So the trick is not in the home keyword, no, The trick is in the parentheses.
When you put your folder inside of parentheses, it tells Next.js router that this part, this specific part, is not going to be a part of the URL. It will still be a part of the router, but not a part of the URL. This is useful when you want to categorize or structure something in the same folder, but don't want to make an entire new URL route out of it. Because if you just added home, right? And then another page.dsx inside, like this, you don't have to write this, I'm just doing it for demonstration this one is only accessible when you literally go to slash home But if you want to structure your root page and your root layout inside of a specific folder, you can do that with the route group folder.
This is what that is called a route group. And you can of course learn more about that here. Route groups, right here. So route groups are nested folders. So in the app directory, nested folders are normally mapped to the URL paths.
That's what we just learned with our feed, right? However, you can mark a folder as a route group to prevent the folder from being included in the URL path. They are useful for organizing routes into groups like site section, intent, or team. In our case, home is a site section, it's a home feed. And the cool thing is you can still do the layout file inside of it.
So if I go ahead and create layout.tsx, it's only going to refer to my routes inside of this route group. That's why I wanted to put it here. Keep in mind that this layout is a different thing. This is a root layout. You cannot move that around.
This one includes the HTML and the body. You can see that it's different than the one we've created because this is a completely different one. You will never move this one. You will modify it. You can of course modify it however you want but you should not move this file.
This is the root layout but you can create another layout inside of here and this is where we are finally going to go ahead and create our home layout. So let's go ahead and let's create an interface layout props give it a children react react node let's go ahead and create a const layout here. Let's assign the props and the structure the children. Inside of here, let's just render the children and let's export default layout. There we go.
Nothing should change right now. If I go to localhost 3000, I should still see new tube two from this page right here. So what we're gonna do now is we're gonna build our home layout. This is the decision that I will make now. I'm not going to do any components inside of the app folder which are not related to routing.
So the only files that I will try to keep inside of the app folder will be routing files. Let me show you what I mean. I'm now going to create another folder inside of my source folder, which I'm going to call modules. Like this. And inside of my modules, I'm going to go ahead and create another folder called home.
And inside of here, another folder called UI. You already see what I'm doing. I'm going to have a modules folder where I'm going to have my sections, my intents, my teams, basically whatever I need and I'm going to use these modules to store my components, my hooks, my API, my server, my utils, anything I need. And then I'm going to use it as I need inside of the router here. But the router itself is not going to have this.
I'm not going to have any styles inside of page.dsx. I'm not going to have any styles inside of layout. The layout will simply serve to render the children. So this is what we're going to do now. Inside of our modules home UI, we're going to go ahead and create a new folder called layouts.
And inside of here, we're going to create a home-layout.tsx. Let's go ahead and let's copy the interface from here. We can actually copy the entire thing like this. The only difference is that our components like HomeLayout are going to use named exports like this. This needs to be a default export because Next.js expects it to be a default export.
But for our own modules and components, we don't have to do that. And I prefer this one. Let's go ahead and be a bit more specific with our name here. Instead of the generic layout, this will be a home layout like this. But now we're gonna run into a bit of an issue here.
I'm going to go ahead and attempt to do what I just did previously. I'm going to create some kind of a navbar here, right? Home navbar. And if I go ahead and refresh this, my apologies, not yet. I have to go inside of my home route group layout here and I have to import home layout from modules home UI layouts home layout and I'll replace this with home layout like this you can see that it says home navbar now I'm gonna attempt to show you something but I'm not exactly sure if it will fail like I expect it to or not so I'm gonna give this a padding of 4 a background of blue 500 and I don't know let's keep it like that.
And there we go. You can see that something is obviously wrong. My padding works but this doesn't work. How come it doesn't work? Well, first of all, how come this works?
The secret is in Tailwind's just-in-time compiler. The padding-4 has already been used. So it was already, let's say, compiled. I'm not sure what's the correct expression to use. My apologies.
But it's already bundled in what styles Tailwind currently has for our project. So when it sees padding 4 here, it says, cool. I know what padding 4 is. But we have never used bg blue before at least I haven't right so it's confused it has no idea what that is why doesn't tailwind know what this color is well let me remind you why what is our folder name? Our folder name is modules, right?
Instead of source, right here. Let's revisit our tailwind.config.ts Can we see modules anywhere in here? We cannot. So Tailwind does not work inside of our modules folder. That's why it's crucial that we now do a proper fix for that.
So what we're gonna do is we can just copy the last line, which is in my case, source app, and change this to simply be source modules. And now every single component inside of modules will have Tailwind as well. There we go. We just added tailwind. I still have this little error at the bottom.
Don't worry about it. It will not affect anything. Now let's go ahead back inside of our home layout. So that is inside of modules, layouts, home layout right here. And instead of using div as our main wrapper, we're going to use sidebar provider from components UI sidebar.
We have this because remember a few, I mean a chapter ago, we run bunx dash dash bun chatcn 2.1.8 add dash dash all and that has added source components ui sidebar right here. In case you encounter a component that I have but you don't double check that you can visit it inside of Source Components UI sidebar. If it really does not exist here, you can always add it manually. I would recommend, again, running the command that we just used previously, which was this. But you can also just add for sidebar.
You can also just add sidebar, right? In case that happens, it should not happen to you. Great, so make sure you have encapsulated your home layout with the sidebar provider. Now for this div right here, we're going to give it a class name of FullWidth, like this. And then inside of here, we're actually going to render our HomeNavBar component.
Let's move the children inside of this div. And let's go ahead and encapsulate our children in a div here. So I'm just adding some semantics here. We are going to populate this with some classes in a moment. Right now, if you visit our app, home navbar is not defined is the error we are seeing.
Let's go ahead and build the home navbar. So we're going to do that inside of the modules home ui and let's open a new folder called components and then let's open another folder called home navbar. Inside of home navbar let's add an index.tsx file and I'm going to export const HomeNavBar and I will return a div HomeNavBar. The reason I have opened a folder for this and an index.tsx and not just home-navbar.tsx is because it's going to have some sub-components, right? So I just want to keep them all together.
That's the only reason why. If this was a simple component, I would just write the name of the component .tsx in case you were wondering. Great! Now let's import the HomeNavBar from ...components.home.navbar. If you want to, you can use alias, but then remember you have to go to modules, home, UI.
But since we are already inside of here, I think it's just nicer to just use this, right? So now you should see home navbar again. There we go. Now let's go ahead and let's properly style this home navbar. Instead of using a div it's going to use a nav element.
Let's give it a class name of fixed top zero left zero so it has a fixed position. Right will also be zero. Height will be 16. Background color will be white. We're going to add flex, item center.
Padding on left and right will be 2, which comes to 8 pixels. Padding on the right will be 5, because we need a bit more padding on that side, because of our login button. And the Z index will be 50, so it's above all other content. So right now, not much should really change, except that your content will be hidden, right? So my navbar right now is above my content, so it's actually hidden.
Basically, what we did here is we just created some basic rules for positioning our navbar and we added some flex items here so that we can properly you know use flex to align this on this side, this in the middle, and this here, right? So that's why we added those flex elements. Great, let's go ahead and continue developing. Inside of here, I'm gonna add a div with a class name, flex items center, gap four. So between each item that I'm going to add inside of this div, it's going to be a gap of four or 16 pixels and the full width.
Now inside of here, we're going to render menu and logo. The menu will be sidebar trigger from components UI sidebar like this. Like that. And let's actually encapsulate this in another div because we will have two items here. Like this.
And let's give the div a class name FlexItemsCenter and FlexShrink0. So this never shrinks regardless of our resolution. And now we're going to add a link component from NextLink, which is basically going to be a click on our logo. So let's give this an href to go back to the root page like this. And inside we're going to do what we did previously, which is render our logo.svg using our next image.
Like this. Let's give it an alt of logo. Let's give it a width of 32 pixels and a height of 32 pixels as well. And now let's add a paragraph new to... You should already be seeing...
So we have this little button here and we have this new tube here. So what we have to do now, what we have to do now is the following. We have to wrap this inside of a div like this so that we can fix the current state, which is that they are one beneath another. So what I'm gonna add this div is a class name, padding for flex item center and gap one. There we go.
Now they're nice next to each other like this. And now let's go ahead and give this new to a class name text extra large font semi bold and tracking tight like this. There we go. Now it looks much better, right? It looks way more similar to what we have right here.
Great. One issue that you can probably see here is this little icon, which is obviously different than from what I have here. We're gonna fix that in a moment. I wanna continue developing this so that we can actually see what this button is doing. And then I'm gonna show you how to change what this button looks like.
Great. So what we have to do now is we have to add our search bar. So find where this div ends, right? This div, which is our menu and logo. And now what we're gonna add is our search bar.
Okay, let me just add it here. So we're gonna have a div here with a class name, flex1, flex justify center, maximum width of 700 pixels. So it doesn't expand more than that. And MX auto. So basically I want it to be pushed equally from this side and this side.
So it's going to be rendered here. And then inside of here, let's add search input like this. Now we have to build the search input component. We're gonna do that inside of our components right here and we can actually put it inside of home number because that's the only place it's going to be used in. So let's add the search input dot dsx like this.
So I'm gonna go ahead and do export const search input here. For now this will not have any functionality just the UI. So what I'm going to do is I'm gonna add a form here with a class name, flex-full-width, maximum width of 600 pixels. I'm going to add a div with a class name, relative with a full width, and then I'm going to use the native input. So don't use the one from Shazzy and UI, just the native one.
Give this a type of text, a placeholder of search. And let's give it a class name. And before we start writing the class name let's actually import the search input from .searchinput so that you can actually see what we're building. Right now you should just see a random input here so now let's go ahead and let's make it pretty by giving it full width padding left of 4 so we leave some space for the icon, right? Because we are gonna have the search icon here appear later.
Like this, PL4, PY2, PR12, rounded L, full, border, focus, outline none, focus, border, blue, 500. Like this. There we go. You can see that now it already looks pretty nice. And you can see a clear cutoff here.
That's because we're going to add a submit button in this corner right here. So let's go ahead and let's do that. Outside of this div we're going to add a button. We're going to give this a type of submit because it's inside of a form. And we're going to give this button a class name of PX5PY2.5.
Background color of gray 100. Border border on the left side is going to be zero because it will directly connect to here as you can see So we don't want to have double borders on this side. That's why it's zero on that side. Rounded on the right side will be full, right? So we want it to be fully rounded so it matches this part like that.
And then on hover, Let's go ahead and give it some background gray to 100. When it's disabled, in case it's disabled, opacity will be 50 and disabled will also say cursor not allowed like this. And inside of here we're going to use the search icon from Lucid React. There we go. Make sure you have added this import.
If you're wondering where does this package come from, it comes from chat-cn, right? In case you don't have it, you can do bun-add-lucid-react or npm install-lucid-react and here's my version exact. But you will most certainly have this installed and let's give this a class name of size5 there we go perfect So we have our search component right here. But we are missing a couple of things and we're not going to develop them now. Instead, I'm just going to add to-dos.
So to-do, add remove search button, like this. And to-do, add search functionality. Button like this and to do add search functionality. For now we are only worried about the UI. Great!
Now let's go back inside of our home navbar index here and what we're going to do now is the ALT button. So let's add a div here my class name flex shrink zero items center flex and gap four and let's render the ALT button component like this. Now I'm going to keep the out button inside of a new module called out. So let's create a new module like this. Let's create the UI folder and let's create the components folder like this and inside we're going to have the out button.dsx like this.
Let's export const out button here. And now what we're going to do is very simply, we're going to add a button from components UI button, meaning it's from ShadCN. We're going to render user circle icon from Lucid React and a text sign in like this. I will just align my imports like this and let's import this out button from modules out UI components out button. So the reason I put it there is because it makes more sense semantically for it to be there, right?
We are going to reuse that. We will be able to reuse that component in other places and I think it just makes more sense that it belongs to the Auth module rather than it belonging to the Home module. You can make of course a different decision for yourself if you want to. Great! So we have a button here but you probably noticed that it doesn't exactly look the same.
So let's just quickly go ahead and resolve that. I'm going to go inside of the out button here and we're going to go ahead and first of all give our button a variant of outline. Then we're gonna give our class name px4, py2, text small, font medium, text blue 600, on hover text blue 500, so just a slight change, border blue 500 slash 20, rounded full, shadow none. And what we're gonna do is we're going to modify the size of this svg right here you're probably thinking can't I just do this you cannot unfortunately That's because if you go deep inside of the button component here, you will notice that it actually changes the SVG size like this, right? So if you want to change this to size 5 right what you have to do is you have to use that same target decorator SVG and then size 5 for example if you want to make it bigger but I think size 4 is actually okay so you can just leave it like this.
There we go. Now our button is looking much, much better. Great. So that wraps up the UI for our navbar. And now we have to do the same thing for the sidebar I will just add to do add different out states right because we currently well this out button is not really useful at the moment it's not really doing anything but that will change so We are now pretty much wrapped up with the UI when it comes to our home nav bar right here.
And what we can focus on now is go back inside of the home layout here, and we should actually find a place to render our home sidebar. Let's go ahead and give this div which is encapsulating our children a class name, flex, minimum height of screen and a padding top of 4rem, just like this. So now as you can see we have moved our body which was hidden behind the navbar. It's now being pushed right here. Great!
So now let's also render the home sidebar here and encapsulate our children inside of the main element. And let's give the main element a class name of Flex1 and overflow Y Auto, like this. And now let's focus on developing the Home sidebar. So basically, this is just some semantics to make this content behave properly when it's encapsulated in between the navbar and the sidebar. Those are these flexes and overfly Y autos and all of those things right here.
And the reason we are doing padding top for REM is because that translates to 64 pixels. And if you go inside of home navbar and hover over here, the height of our navbar is 64 pixels. So what we are doing is we are pushing the entire content below the home navbar for the height of that navbar. So that's why our content is now visible, right? Previously it was hidden behind.
Let's go ahead inside of our components and let's create a new folder home sidebar and inside of home sidebar let's create an index.tsx component like this inside of here let's export const home sidebar And let's return a sidebar components from components UI sidebar. Make sure you don't accidentally import the icon from Lucid React. Let's give the sidebar a class name of padding top 16, Z index of 40 and border none. Like this. And let's add a sidebar content here from components UI sidebar.
Let's give it a class name of background. So BG background will simply default to whatever our background color is, which in light mode is white. And now instead of here, we are going to add some sections. But I think that we should already perhaps be seeing the sidebar. So let's go ahead and import the Home sidebar from Components, Home sidebar, the same way we have imported the Nubbar.
We can't see anything, but we can clearly see that something has pushed our content right here. And you can see that also when I click on this icon, I can collapse our sidebar. So, before we do any changes to any of this, what I want to do is I actually want to go inside of the home sidebar and I want to add my first section which will be the main section like this. And the main section will be another component which we're going to implement inside of the home sidebar here create a new file main-section.tsx like this and this will most certainly be a client component because we're gonna be using some hooks. So we need to turn this into a client component.
And now let's go ahead and let's prepare const items here. It's gonna be an array of items. The first item will be a title which says Home. It's going to have a URL of a forward slash and an icon of Home icon from Lucid React. Like this.
And that's how we're going to build our items here. The next one will be subscriptions which will lead to slash subscriptions actually slash feed slash subscriptions like this with an icon of play square icon again from lucid react So that's going to be our second one. And we're also going to add a useful little work here, Auth True. We're going to use this later. It's going to be useful for us.
Basically, this page will only be rendered to authorized users because this will be used to load videos from your subscriptions. If you're not logged in, you don't have any subscriptions, right? And this one will be trending. So feed trending. And this will have flame icon also from Lucid React.
And ALT is not going to be required for this one. Great. So now let's export const main section here. Let's return sidebar group from components UI sidebar, sidebar group content, and sidebar menu. So make sure you have all of this from sidebar, sidebar group, sidebar group content and menu.
But while we are here, we can also add sidebar menu button and we can add sidebar menu item like this. So make sure you have all of this. Let me just collapse them so you can see them nicely. There we go. Instead of the sidebar menu right here, what we're going to do is we're going to iterate over our items.
Item.map, get the individual item and then inside of here, render the sidebar menu item with a key of item.title because each title is unique so we can safely use it as a key and let's render the sidebar menu button component like this Let's give this a tooltip of item.title. Let's give it an as child. Let's go ahead and give it an is active to be explicitly false. I'm going to change this in a moment and on click for now will just be an empty arrow function. Then inside of here we're going to use our link from next link like this with an href going to item.url And then inside we're going to render item.icon like this and a span item.title.
Let's give this some styles. So this will have a class name of flex items, my apologies flex, then items.center, gap-4 and this span here will have a class name of text small, like this. So that's our main section. Let's go ahead and import our main section from ./.main section. And now you should be able to see home, subscriptions, and trending right here which are all from our items as you can see here.
Great! So now what I'm going to do is the following. I'm going to go ahead and add a little to-do change to look at current path name. To do something on click. So these are all the things that we are going to have to do later but for now we are just focused on the UI.
Great! Now that we have the main section we can easily build the other section which we need which is the personal section. History, liked videos and all playlists. So what I'm going to do is I'm going to go inside of my home sidebar and below the main section, I'm gonna add a separator component from components UI separator. Make sure you didn't accidentally import this from a Radix because you're not gonna have any Shazzy and styles.
Let's give this separator, well nothing, it should just look like this. It should just be fine. Great. And then below that we're going to have another section like this. Let's go ahead and let's copy the main section and paste it here.
And let's rename it to personal section, like this. Meaning this will be the currently logged in user's personal items. But we are still going to render them regardless if we are logged in or not, purely because the sidebar really looks empty when you're not logged in. So we at least want to show the user what they could have once they're logged in. So that's my decision to show that.
Let's modify our, well, first let's rename this to Personal Section, like this. And let's go ahead and inside of Sidebar Group, add Sidebar Group Label. You have to import this and call it U. So Sidebar group label is a new import here. Make sure you're doing this instead of the new copied personal section.
Make sure you didn't alter the main section. Great. Now we're going to change the routes. So the title of this one will be the history which will lead to slash Playlists history. Playlists history.
And it will use history icon from Lucid React. And we're gonna add out true. Next one will be like videos. And this one will go to playlists liked. And it's going to use the icon thumbs up icon from Lucid React.
And the last one will be all playlists. And this will just go to slash playlists and it's going to use list video icon from Lucid React with alt true as well so make sure you have added history icon, list video icon and thumbs up icon So now if you save this and go back instead of your home sidebar and replace this duplicated main section with personal section like this, you should now see another section right here. Great! And we can now go ahead and go inside of source app folder, my apologies, inside of well yes inside of home page.tsx and just change this to you know I will load videos in the future like this and remove the import. And there we go.
Now it makes more sense what this will be. So this is our sidebar with home. If you click on any of this, it will lead to 404 because we don't have any of those routes implemented yet. But you can see our basic layout is definitely coming together. Let's go ahead and wrap it up by just modifying the icon of this sidebar right here.
You can do that by literally going inside of the sidebar component, which we can do because we're using chat CNUI. So just go to source components UI and select the sidebar component. Let me just find it. Sidebar right here and you can see that we are using panel left from Lucid React. Let's add menu icon from Lucid React and we can remove the panel left.
And now we can just look for the error. So just scroll down and you will see an error right here, I believe. There we go. The component is called a sidebar trigger. And what you can do is just change this to be menu icon, like this.
There we go. And now it's exactly the same as mine is. And another thing that you can do here is you can go inside of app folder, my apologies, inside of your modules, home, layouts, actually home sidebar index and you can add collapsed, I believe, is it collapse? Just a second, I'm going to, oh, it is collapsible, I believe. Not on the sidebar content, on the sidebar collapsible.
And inside of here, you can choose icon, none or off canvas. And if you choose icon, you're gonna enable the collapsed mode like this. I think this is quite useful if you don't want to entirely hide the sidebar but you do want to expand your user's view. Perfect! So we now have this and I believe that already If you go inside of mobile mode, let me go ahead and go here for example.
There we go. You can see that it also works in mobile mode. It does throw some errors. These are actually not our fault because this component that's doing this has been built from, you know, we didn't build the code for this and this error that's being thrown comes from a newer version of Radix, which I guess the creators of Shazam didn't exactly account for at the time. So now it's throwing an error because the way they implemented this sheet component or this dialogue component is throwing accessibility errors, right?
But I think it's okay for a tutorial. I will research a bit before I completely end the tutorial if that has been resolved somehow, but I think in this version it's gonna stay like that. But those errors are not visible in production as far as I know. Great! So one more thing I can show you how to do is the animation.
If you like the animation, great! I personally don't like the animation. I think it makes the app look slower. So again, let's go back inside of our components UI sidebar. I'm going to show you where you can change or remove the animation.
So basically, if you want to remove the animation, I don't think there's a prop for it, but you can search for any of the transition classes, right? And if there are any transition classes, you can remove them. So for example, I'm gonna remove transition all from here. You didn't have to do this, but if you dislike transitions as much as I do, you can just remove them. So I'm gonna remove the transitions here, right?
Transition transform, for example, I will remove that. Transition width, height and padding, I will remove that as well. Transition transform, remove that as well. And transition width. Let's see, anything else?
We do have this as well. And I believe no more transitions. So now let's see if I refresh. Oh, it still shows some transitions. I think I also have to change the duration.
So I will remove all durations as well. Let me see. Perhaps that's what was the problem. Again, you don't have to do this. I just really dislike them for some reason.
There we go. Maybe I could have just removed durations, but this makes it the same way it works on actual YouTube. So depending on what you prefer, you can either bring it back or you can change it as I did. Again, you can just search for duration or you can search for transition like this. And then you can just remove the necessary classes.
You don't have to do it if you like the animation. And if you think you've messed it up, what you can do is, well, you can undo the file. But remember, you can always run Bonnex add sidebar. And what this will do is... Let me just go ahead and save my sidebar component just in case I'm going to copy the entire thing.
You can do this, for example, and let's see. Oh, yeah, it will basically ask you the file Sidebar.tsx already exists. Would you like to overwrite? And you can just press yes, and then it's going to overwrite it, and it's going to bring it back to normal. So I'm just gonna remove, no, no, no, no, no, the entire thing, no.
Okay, great. So Let me just double check that nothing important was modified for me. No. Great. There we go.
So as I was saying, we just finished the basic layout. Great. So we built this red thing right here. It's not exactly finished finish. It's just UI, but it is the layout that we need.
Great! Amazing, amazing job!