Fresh React Portfolio Website (Next.js App, Framer Motion, TypeScript, Tailwind CSS, Email)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to this tutorial in which we'll be building a fresh cutting-edge responsive portfolio website from scratch throughout this video we'll be using modern technologies that any developer needs to know it may look difficult to implement but it's going to be much easier than you think so we're going to use nextges 13 we'll be exploring the latest features like app router and server actions we'll also discuss clients and server components and we'll be using typescript in this project now don't worry if you're a beginner or intermediate developer we'll cover the basics and explore how typescript adds type safety and enhancers our coding experience this project will level up your typescript skill for styling we'll use Tailwind CSS sailwind comes with a lot of helpful features out of the box which makes it very fast for us to style our project and as we style our project I will also mention UI design tips and tricks now to manage the state and data flow in our application we'll be using the react context API so for example we need to keep track of the active section in our project here so we can properly Mark the active item in the header and we also keep track of light and dark mode so we're going to use the context API for this and this helps us easily share data across multiple components we will also Implement Advanced animations using framework motion so we're going to create these eye-catching transitions interactive elements and smooth scrolling effects such as here in the header as the active section changes this active nav item will animate I think that's really cool and this website will also have a smooth scrolling so when you click in the header we have a very nice scrolling effect now for contacting functionality we'll integrate react.email and resend to handle contact form submissions so it actually works you will actually receive emails in your inbox and throughout our coding journey we'll be using the power of react hooks including custom hooks to simplify our code and make it more reusable we'll focus on the visual aspect as well and create a fresh modern UI design for our portfolio website will Implement a light and dark mode to satisfy both preferences and it's also completely responsive so it looks and works on both mobile and larger devices this is also something that till when really helps us out with now it has all the bells and whistles that a portfolio website needs so if I click on this context me here it will actually send me to the contact form you can also click on the download button and it will actually Download a pdf file these links will actually open up in a new tab for your LinkedIn or GitHub profile and in the context section we can click on this to open up our default email client on the computer or actually send an email from this contact form and by the end we will deploy this live on the internet with for sale alright so when you're building a portfolio website you need to know the type of people that are going to visit this website there's going to be two groups primarily so first of all you have the recruiter the recruiter just wants to take a look at some general overview of what you are capable of they want to know your skills your years of experience and they want to have a quick way of contacting you they want they basically just want a quick grab of information you need to make sure that you are displaying that type of information you know right when you load the page and that's what we're doing here right so here we're saying I'm a full stack developer with so many years of experience your core technology stack right react next chance and then there's a way to contact you quickly download CV or resume quickly contact them or you on social media right so these recruiters they are people that usually are contacting many people right so hundreds of people a week and they're not going to take a very deep dive into who you are right so they just want a quick grab of information and a quick way of contacting you right so that's exactly what we're doing here now the second type of people that are going to come to your website are more technical people and so after the recruiter has connected you to a company usually there's going to be a more technical person a team lead that's going to take a deeper dive into who you are and your background and those people are gonna yeah they're gonna look around a little bit better here so they're gonna look at about me they're going to look at the projects that you've done um your actual skills um your experience they want to get a good sense of your capabilities because they you know maybe their team lead they're looking to add another developer to their team and they need to make sure that you as that new developer would be a good fit right so they're going to do a deeper dive into you so that's primarily due to two types of people that you're targeting with a portfolio website and that's exactly what this portfolio website will do properly right so for a technical person it's important that not only you actually have the information ready here but also that you're presenting it on a modern website using the latest you know standards of the web so that's what we're doing here right so we're using next to us with the app router uh you know things like react contacts API so that it shows that you're actually you know comfortable with react modern UI design implemented with Tailwind CSS typescript Advanced animations and transitions you know things like you know dark mode you know hosting on for sale all of the showcases that you are actually up to date on the latest standards for the web and also responsive design that you you're capable of making projects responses that looks good across multiple devices right it's all in this project all right let's take a look at the code base to see what we're going to implement the types of things that you are going to implement and maybe learn about if you don't know about those things yet first of all of course we're gonna we're gonna use react right so we're gonna use these react Primitives so those are things like for example you use state right so we're going to use for example use data use statehook but also use effect we're also going to use use ref right so these are really three common hooks that you really need to know as a react developer so that's what we're going to use now we're also going to use the context API so for example here for this dark and light mode we need to keep track of the active mode right so here we're gonna talk about react contacts API the user can switch from light to dark and many components throttle application need access to that setting so it's better to put that in a react context API we'll talk all about that and we're also gonna see how we can refactor things into their own hook so here we have a hooks file and here we're going to have our own custom hooks looks very complicated all of this but we'll do it step by step don't worry it's beginner friendly you know some duplicative code we can refactor that into an own custom hook this Hook is keeping track of the active section so that we can actually uh you know have this little animation as we scroll throughout our page so that the active section actually is active here in the nav bar alright now we're also going to use the latest next year as feature Society such as the app directory or the app router so that means in the app router we're going to have this layout file this is basically the root of our whole application and typically if we look at how we are implementing that here typically you're going to have a header right so you want to have the same header on all pages so typically you have a header in this layout file and typically also a footer and then in here usually you have the children so this is going to be the actual page right so then you have a page file that will actually be basically the child here so the page file here in the root of the app directory that's going to be for the home page now in this project we're only going to have one page you don't really need multiple pages on a portfolio website it should be very easy and quick to access all the information that the person wants to see so I think it makes more sense to have one page but let's say we want to have another page in this app directory you would create a new folder let's say about and then you would have another page file right page.tsx and now you can go to slash about and uh this page here would become the chat now we're only gonna have one page from this page file and the root is going to be the home page okay now you can see we have this other weird looking stuff here as well if you're not familiar with react context API we have this context provider component actually two of them a very typical pattern here to wrap all of your components in a provider component so that they all have access to that state that you're passing through we'll talk all about that right so here we have for example uh active section context provider that's taking that's taking care of this active section here in the nav bar and then we also have this theme context that's just for dark and light mode and then we also have this toaster so for example here at the bottom we can send email messages so we can send a message to ourselves and so if I fill this out and I try to submit this we should also get a message to see if it fails for example now it's failed because I removed the API key so I get a nice little message here this is a toast and you can see it eventually disappears but you can see you you have to provide this toaster in here somewhere that's what we'll talk all about this again don't worry if it looks complicated but how this is structure then we have the actual theme switch As for the dark Mouse here so that actually scrolls with us and these two divs here are actually just these two colors in the background to make a little bit more interesting looking and that's how the app directory works so you have a layout and then you have a page that will be uh that's here we will actually use for all the different sections so we're gonna have the intro section divider about projects right all the sections here right that will that will be put here right but we'll talk much more about that how the new next.js app directory works right so one of the things we'll also talk about is a server and client component so for example this layout file the root component essentially of your whole app this is a server component by default so this will be rendered only on the server and that's actually beneficial it comes with certain optimizations so ideally all of our components are server components but sometimes you need some client-side features such as you know an on click Handler you just need some interactivity in that case you want to convert it to a client component so for example this about section although it looks quite static we still made a client component with used clients because we need to keep track of it when it actually is in the view right so that's only possible on the client and therefore we have to convert this to a client component we'll talk much more about that right now common misconception by the way if we look at these provider components that we get from the react context API we are also making these client components right so then here when we are wrapping all of these other components in those provider components a common misconception is that these then will also become all client components and that's not the case right so something only becomes a client component if you actually put use client at the top of the file or you are importing it in a in another client component so if I here I'm importing section heading right this is a component so this will automatically become a client component as well but these can still be client components without making all of these also client components right so you can Nest server components right so this could all still be server components likely that are wrapped by this and because these just pass along their child elements and so here we have children in the active section context provider it's just passing through the children right so that's why these are not automatically becoming client components right so a bit Advanced but this is new in next year as we have to learn about this we'll talk all about this as well all right now one other very cool feature of next.js these days is we have server actions so if we look at the contact Section here we have a form Let's see we have a form and then what you can do these days is you can use the action attribute and this will actually pass the form data to you that you can actually use on the server without creating a whole you know API endpoint right so in the past if you wanted to submit a forum you would do something like on submit and on submit and then handle submit and you would have a whole separate function here that would send it to some API endpoint and we don't have to do that these days because we have so-called server actions so here you can use the action attribute you get the form data and this is still all client-side code but then you can pass it to a server action so here we have a send email as a server action we pass the form data and I put the action here and we're going to put that in a separate folder here actions and then so this send email function that we're passing it to this will only run on the server and so here we're executing a function that will only run on the server we have U server at the top and this can deal with all of that data right and we we're not creating a new API endpoint right so we don't have something like slash API slash you know send email this is just a function we don't have to deal with the whole API this is a new innovation right so here we will actually send an email we're going to use a service called resend which is by the same team as react email so we'll talk about that and then you can actually return an error or data that you can then immediately access here on the front end on the client side again all handled for us behind the scenes this flow between server and client by next to us and you can even use a new hook in the submit button here for example because you saw when I submitted this actually I can submit again you can see we have this loading indicator right so we can use the new hook use form status it's still experimental but you people are already using it you might as well already get familiar with it you can use that it will show you the pending state of this form right so really cutting edge stuff this is really going to Showcase that you are up to date on the you know the latest and greatest in the world of web development alright so we're also going to use the next.js image component so let's see in the intro here intersection we have image right so here we are using an external URL for our image and in that case you need to provide these width and height properties yourself right if you are using an image that you have locally so here for example we're also going to have images for these projects but only on wider viewports right so here we have images for these projects and these are actually local right so let me make this a little bit wider and so these images are local they are in our local file system here and to use them it's a bit different with the next JS image component so here if we want to use those we can go to projects here and here you can see let's see image component here we have source and then we have a variable image URL right and we are actually importing that here let's see we have some static data so for the projects we just have data here so here we have that image URL and this that's a variable here because we are importing that here and so we can import images right locally and we'll talk about what this at forward slash means but you can import images from the public folder and you can use that as your source for the image and then you don't have to provide the width and height properties yourself next chance will automatically do this for you right so it basically allows nextgens to optimize this a little bit easier and and better so typically you do want to make your images local files right then on the image component you can also place a quality setting because by default it's something like 75 percent so it's going to reduce the size a lot by default but also the quality so you can change that priority to make sure the loading happens faster than the other assets on the page for example right we'll talk all about this powerful image component of next.js as well all right now if you look at the colors on the page if we inspect these colors for example in the background color here you can see they actually have a little bit of blue in this and this is a common design tactic these days instead of having like plain Grays people often designers often put a little bit of blue into the grains to give it a cooler look it just looks a little bit better than just plain gray and this is actually very typical of the Tailwind colors as well so the stillwind team has hand-picked these colors and they make it very easy for us to use these colors right so this is one of the reasons why we're going to use till when CSS so you can see they actually have some plain gray some actual actual pure Grays and then here on top of them they have essentially also grass but with increasingly more blue in them so the zinc the zinc palette here has a little bit more blue than the just pure Grays and then we have the actual gray class name which has even more blue and this is actually what we're going to use mostly and then there's also slate which has the most blue in there right so this is how this color scheme is structured now below the neutral you can have warmer colors right just a warmer look right so that's one of the design tips that I can already give you but as we built this project I will mention other cool modern design tips and tips and tricks and how to implement them with tailwind and another cool thing we can do with till winds very easily is for example when I hover this button I actually want to animate this icon to the right a little bit it's a bit difficult to see so let me zoom in a little bit more so here when I hover this you can see the icon moves a little bit to the right right so how do you how do you implement that with till wind right so here we have this button here that's going to be here it's actually a link but we're going to sound like a button but what you can do is on Hover we want to scale this button bigger right that's what we're doing but we also want to have this icon here move to the right and not only when we hover the actual icon but for example also when I hover here on the left side of the button but those are two different elements so how do we do that well what you can do is you can add the group class and then you can say when that group is hovered move it to the right and so that's group hover and there are other cool things we can do in till went as well for example here with these projects we want to have them alternate between right and left side right so these images here should be on the if it's odd it should be on the right side and the image is uneven should be on the left side we only have three here but if you add more it automatically works right so the images here on the left side well how do we Implement that well we can go to the project components here and we can see um so we add the group class here to the overall outer element and this is a motion component we'll talk about that it's necessary for frame or motion it allows us to do all sorts of cool animations and transitions but it's just a normal it's just a normal element essentially so we can just add the group here and then we can go here we can use group even right so we have group hover we also have group event so when it's when the overall outer element is is is even so that's this one right one two three we can add some special Styles we can even combine it right group even with hover so when it's even and the outer is is hovered right so these are very cool tricks a bit Advanced that we can do until then another cool design uh thing these days is with these see-through backgrounds for for example the nav bar here right so you can see it's a bit see-through and it's a bit it blurs the background I think that looks pretty cool so you'll you'll learn how to implement that as well also sometimes you are repeating a lot of classes in Tailwind so for example these little elements here they have a they have a sort of border around them right so these skills have a sort of Border but we use that in different places as well these cards also have a subtle border around them and these buttons these white buttons also have a solid border around them and this is this is necessary to to add some contrast but between them and the background right so these are some styles that we are repeating right so what you can do until when if you are repeating those classes you can go to your globals CSS file and here you can just add a normal class we're calling it border black hair and you can use at apply and tailwind and then the till when classes that's going to be border and Border black 10 opacity and then you can just use this one border black instead of repeating all of those still in CSS classes for all of those elements we now only have to add the Border black class right so this is another cool till when trick that we're going to use also in terms of responsiveness if we look at the form here for example what we want is that this form is this size but as we make the viewport smaller and smaller it should progressively become smaller at some point as well so here for example you can see it's very smooth here at some point it just it just basically decreases with the viewport at some point right but then if you put a smaller it doesn't become huge it just has some maximum size right so these are subtle things that you need to know if you work with the front end as well how do you implement this responsive CSS basically with tillwind we'll talk all about that now also when we load the page here we have these very cool intro animations right so this is all done with frame or motion and so if we look at the nav bar for example it comes from up here and goes down and has this cool bouncy spring animation effect and that's actually the default in framer motion and then these other ones all the other endless they come up from a little bit lower and they come up here so it's it's also staggered so they have a bit of a delaying right so this one's a bit faster than the other one so it gives a staggered look and this is very easy to implement with frame emotion for example if we look at this uh this text here this is in the intro so that's actually an H1 right so what we did was we first just use H1 all right just an H1 for this text and then we were like it looks cool if we if we can animate that so to do that with frame of motion you can just convert this into motion.h1 and then you get access to these two properties that you don't typically have on an H1 element so you just say initially it should sit zero you know 100 pixels lower right zero opacity and then during the animation it should animate towards opacity one and you know zero movement right so that's this text right so that's the only thing you have to do if you then refresh you will get a very cool uh bouncy animation that's really playful and I think looks uh yeah it just looks really nice and I keep refreshing to see the animation and that's also what we're using for this nav bar here so if you click close attention to the nav bar here if I zoom in a little bit you can see this home section is currently active if I scroll down a little bit you can see it's the about section that becomes active and we have this background thingy that will just go to the next section right so you can see that also has a bit of a bouncy springy effect I think that looks really cool and also very easy to implement with framer motion really modern if I click on content you can see it's it's it slides through there and if I click on projects it slice through there right very smooth and also without bugs right so some other people have attempted to implement this but what happens is if you click on skills there's background thing it will first go to about and then project and then go to skills that's not what we want it should immediately go to scales right and that's what we get right so that's really cool of course we also have scroll based animations we have these projects you can see when I scroll down they sort of grow into the view it's a really nice smooth effect also when we scroll out of there again they disappear very smoothly right if we look at the skill section here if I re if I refresh here because we have configured it to only animate once so if we scroll into view here for the skill section we have this very cool staggered animation then the experience action also has some cool animations here and the context form nicely fades in right so looks complicated but very easy to implement all right so we're also going to use typescript in this project don't worry if you're a beginner or don't even know much about it it's not that difficult to pick up and you often don't even need to use it in that many instances so in react you often use it if you have a component that that's taking props so this project component for example takes props my title description tag tags image URL and we're gonna describe what those variables can are going to be so we'll talk about what that means they're basically going to be some type of the project data that we have that's just a constant here in our data and so what we're basically saying is those props are going to be this right so uh and specifically they're going to be this only so so only these right so only these specific strings right so that's what we can use with s-const this is a typescript feature you can say that project's data is going to be specifically this title not any string right because by default typescript will infer that this is the title for example is going to be a string but we can be more precise than that because we know it's not going to be any string it's only going to be these three strings this is a constant this is not going to change this is not coming from some outside Source but we are hard coding this here and we only want these titles to be these specific strings so we can say as const and it will infer and it will make and it will type this as literally those strings right we'll talk about what that means but I just said if it's includes you don't worry rapid that's a nice trick that as const trick also when you're using these hooks like use ref for example initially you're gonna pass null and a typescript May infer that reference is then going to be a null but we know that eventually we're going to put this on a div element so we're going to say this is going to be a type HTML div element right so we need to type we can type that like this with this angled bracket looks a bit strange but very easy to pick up once you once you get once you use it once or twice all right so then let's see what else we have here we also have an email folder here so we're going to send emails and just show you that now to style emails these that has a popular Services react email makes it very easy to style your emails appropriately for all sorts of email clients and you can even use till wind for this now it's not really important that we style it so we keep it very basic here we we will quickly go through it but this is how you would style it and then to actually send an email we use resend that's what we're doing in this server action right here we're actually sending an email and we'll talk about how you can make a set when you we're going to send this to our own email inbox so it would be nice if you can then sort of hit reply and then immediately send an email to whatever the user wrote here and so you can use the reply to field here and then here recent actually wants to know you know the HTML or actually react component that you want to use for the email now what you can do is you can write react and then you can say contact form email like jsx right you can do this but this is a TS file right or JS file if you're not using typescript and here we're using jsx so that won't work so we could we could change this to TSX right so now we can write this components here and it's actually expecting some props so we can pass those messages message and sender email is sender email right so we could in a TSX file or jsx file you can write jsx and without any issues but we don't really want to convert this whole file to a TSX or jsx font just for this one line of code and so you can actually write the equivalent like this in react right so you can actually just say react create element that's actually what reactor is doing behind the scenes when you're when you're writing or reacting opponent like this behind the scenes its writer is going to convert that into all sorts into many react create element function calls so you write context form email and then you can pass props with an object like this so now you don't have to convert this to a TSX or t or or jsx file you can just you can just keep it as a TS or JS file right so those are you know subtle things that you you just have to know about them as a modern developer I think so I will also mention those things also here for example with typescript when you're catching an error we don't really know what that what the type of error is going to be because technically in JavaScript you can throw anything you can throw a string you can throw a number so how do you deal with that in typescript right not the most exciting topic as an error you know dealing with errors but professionally if a more technical person is going to look at your project they also want to know you know these details how do you take care of this all right now by the end we're also going to deploy this to for sale right so you can see here this is live in the internet right so here before I was using logo host now I'm using this public URL on hosted by for sale right so it's going to be very easy to deploy to for sale I will even show you how to change this URL into something that looks better because by default you get some strange URL from for sale some random words in there but you can change that to a more well maybe your own name for example there's a lot in there you will learn a lot by doing this now if you really want to become a professional react developer or next.js developer I have a react next to S course coming up very close I highly recommend you get on the email list so you can get an early bird discount I also have JavaScript and CSS courses I highly recommend you go through them as well because you really need to master the fundamentals if you want to be a professional developer I see a lot of people they are very excited to jump into react for example but they haven't really mastered JavaScript itself yet right so you're going to run into many issues if you haven't done that yet so I highly recommend you check out JavaScript course in which we will build some beautiful web apps from scratch step by step and you know react this next going to be super easy to pick up once you have mastered those underlying fundamentals same with CSS by the way right so you need to know how to use flexbox CSS grid animations and Transitions and there's a lot to it and and it's gonna be very easy to pick up till when for example once you have already mastered CSS so I also highly recommend especially if you work with the front end as a full stack or front-end developer that you master CSS go through my CSS course it takes an afternoon and you'll basically never have an issue with CSS again if you go through it so check those courses out the links are in the description this project also has a GitHub repo so if you get stuck or you don't want to type out something just go through the go to the repo you'll find all the code there you can copy and paste it you also find the images there so you can always use that to get the get the code for this project alright so then let's actually get started alright so I opened up my code editor on the left side and the browser on the right side I'm going to open a new folder here so we can get the project started I'm going to go to my desktop here I'm going to create a new folder and I'm just going to call it something like portfolio I'm gonna open that up here in Visual Studio code and then I'm going to open up the terminal terminal new terminal you can also use the shortcuts and here we want to create a new next.js project now it's very important we're going to write MPX create next app at and then we can say latest but we don't want to use latest because we it's changing quite a bit we want to use the same version so what we're going to use is 13.4.7 and then after that I'm going to press I'm going to put a period so that it will install the project right here in this folder so it won't create a new folder all right so it's going to ask us if we are if we want to use typescript yes yes we're also going to use stillwind CSS and if we want to use the source directory directory with this project for a small app like this I think it's not necessary but you could make an argument for this use the app router yes do we want to customize the default import Alias no okay so then it's going to install a bunch of packages and I'll see you once this has finished downloading all right so it has finished downloading this and now if we open up the sidebar you can see all these files and folders have been created for us so let's actually start this app we can type in the terminal npm run Dev and that's going to spin up a server for us but you can see there's going to be localhost 3000 I can hold a control click here to open that up it's going to open it up in a new window so I'm just going to copy the URL here and open it up in this window now the next.js in development is a little bit slow these days so here with startup it's going to take a couple of seconds before you can see anything on the page and also when you make a change it can it takes some time but the next chess team is working hard on that I think it's their number one priority right now to improve that so don't worry alright so I'm going to close the terminal here you can see this is the default nextgs app scaffolding that we get so let's actually take a look at this folder structure we don't have the Pages directory anymore I mean there is still exists but we're going to use the app directory this is basically going to be the the future of nextges and in there we have four files here the root of your app is going to be in the layout file here so if I open this up here we have one component and this is going to be the root component of your app so this also has the HTML and body tags for your actual Pages you're going to use the page dot in this case TSX files so here this the synthesis is in the root of the app directory this is going to be for the home page right so then if you have a slash about you would say about and then in here you would have another page.tsx file and this would be the file for slash about now in our project here this is all going to be on one page right so it's a simple project I think you know for a portfolio website you don't need multiple routes it can all be on the home page much easier to get quickly get some information about your recruiter or anyone else looking at your website right so I'm gonna delete this about we don't need that we're all gonna work on this one page now there's one page is going to be the child's element right so that's basically what's going to be in here right so here we have the root component and this page will basically be put here all right so let me actually save here to remove that uh stuff and let's go to page.tsx and let's also remove all this stuff here I'm Gonna Keep the main element though all right so just remove everything and I'm Gonna Keep the main element so I'm gonna remove the class names but we'll keep the the main element and I'm also going to remove this import and you can see we can actually still name these components right so it's called the home component but the file is page.tsx all right so then we also have this globals.css file in which we're also going to remove everything so just remove everything here except the add Tailwind lines here so keep till wind Tillman needs these so we're just going to keep this this is imported here in the layout file right so then the bundler can pick it up and in here we also are importing this interfont I think uh this was one of my favorite fonts so I think we should use this so it's a bit strange here so we have to import enter and then it sort of uh instantiate it and then we can use enter.class name here which is already done for us this metadata is necessary for what you see here in the tab so here create next app is what you see here in the tab that's this title here let's actually change this so in this example we're going to have a fictional person called Ricardo and I'll just have this bar here we'll call this personal portfolio just closing the sidebar there and then the description is well basically the what what this website is about right so this is also going to show up on Google for example so here we can just you know type something Ricardo is a full stack developer with eight years of experience all right so now when I save this file you can see that's a bit small here I can't zoom in there but you can see it's now changed into whatever we put here as the title you can also see we have this fav icon here in the tab and that's actually also coming from uh within the app directory so if you have a fav icon dot Ico or Ico file in your app directory that will automatically become the fav icon right so you don't have to manually specify that here it will automatically automatically be picked up by next.js now we're going to use a different one so let's remove this one and that gave me a brief error for some reason and it's actually interesting that we get an error here because we are not importing fav icon ourselves anywhere so here's our you know sometimes you get these issues with next.js there are some things that are simply not working properly so sometimes let's when this happens I just uh you know I will just restart and see what happens so I'm gonna restart here I'm gonna run npm run Dev again and let's see what happens all right so a bunch of stuff happening all right so we get the same results we still get this error so usually what happens then is I started to think it's something with this cache that they have so what you can do is this next folder you can just delete the next folder and it will just be uh recreated the next time you run the dev server so it's not a big deal I'm gonna delete everything here and now we get this error we cannot uh yeah we can do this for some reason my guess is because this server is running so let's try that again delete this folder yeah so now that the folder is gone so now we can try running the server again npm run Dev and let's refresh here you can see the next folder is automatically created again all right so now when we come back we indeed uh see that there's no error anymore so it was probably something to do with the cache I'm not sure exactly how they're uh handling this uh that's usually yeah this is the real world right you're going to run into errors and this is how I would solve the error just restart the server try removing this next folder because they do some kind of caching there and you know eventually is that if that didn't solve it I would have to stop the video and start really Googling or something usually you know other people have the same problem so usually there's going to be some solution out there all right so currently we have a blank page so let's actually see what we should add here let's actually start with the background so the background is not going to be a plain white color it's actually a bit of a blue color and then we're going to have these two colors in there that's basically like big blurry dots which is a popular design Trend these days so for the background we want to put that on the body element so that's actually uh style it here right so here we need to change it a bit because we're using this inter class name here let's make this a template literal So within the curly braces we can use uh this backticks and then we can use the dollar sign and and then again curly braces for this variable and then after that we can just write our other class names here right so this is going to be BG Gray 50. when you do that you'll see that the background has changed a bit it's very subtle which is what you want for backgrounds which is now more blue color now one of the reasons that we're using Tailwind is because it comes with a lot of Handy features out of the box like color so the creators of toolwind have actually hand picked these colors these these color palettes for us so it makes it very easy for us to create a project with really nice color schemes that are consistent and basically cover the whole range of what you need now a very quick design tip like I just said you can see the background is a bit of blue it's not pure gray and this is a very typical design Trend that you're going to see a lot these days right so if I I just added the color here so we can get the Color Picker here if I just pick a color here you can see it's a bit of I can't zoom in here but you can see there's there's a little bit of blue in there right so here you can see they these are the colors that you get out of the box they do actually have a plain gray color palette they call it neutral but usually you wanna that's gonna be too plain so usually you want to add a little bit of blue into your Grays very typical and they basically have three degrees to which you can do that so sync is a little bit of extra blue and then gray is actually not plain gray that's actually gray with quite a bit of blue in there even more than zinc and then this slate has the most blue in there so if you want a really blue blueish Grace this is what you would use lace now we're mostly going to use gray though right so this is the actual gray and then up here it's more blue usually it gives a bit it also gives a bit of a colder look a cooler look which looks good but sometimes she actually want a warmer look so then they also have some Grays with a little bit of yellow or orange in them so here we have stone and then of course red and orange right so after neutral you're gonna get the more warmer colors right but we're just going to use uh BG gray and then whatever number we deem appropriate now we also want to set the default text color so we can do that on the body as well and it will be inherited by all the other elements that need a color property right so by the way it's really important as a front-end developer or full stack developer that you have mastered the underlying fundamentals that's not only JavaScript but also CSS right so till winter is really easy to pick up once you've mastered CSS itself I highly recommend that you check out my CSS course you can do it in an afternoon and if you go through it you'll basically never have an issue with CSS again so here we can say text Gray and here we get some options from intellisense so here we can see the different colors I want to use the most dark one here so we're going to say 950. by the way I recommend that you install this till wind uh distill wind extension here it will give you that it will give you those classes right so that's where I got them from till when CSS intellisense it's by the official Tillman Labs company right so this will be inherited all right so then let's add those colors so I picked a bluish color and a bit of a red or orange color so this is also a bit of a design Trend that I've picked up on uh you just add like a DOT of color it's going to be blurry but looks look kind of cool it makes it look a bit more interesting so let's add that here as well so we have two of those colors so we're just going to create an empty div for each of them so here in the body these children will be by the actual page will be placed and here we're just gonna have two divs two empty divs and I'll just duplicate this and this left this first one will be for the left one it's going to be the blue issue one so they will have custom colors so here we have BG and then usually until when you can use gray blah blah blah or you can have something custom you can use square brackets and this is going to be hex code fbe2e3 and they need to be positioned absolute which will take it out of the normal flow as it's called so they're not going to take up any space and we're going to position them from the top right so with absolute absolute positioning you have top left right bottom offset so here we're going to say it should actually be going up a little bit and actually let me make this a little bit wider right so we actually want to pull it up a little bit so it's going to be a negative number here right so negative 6 REM we should try using the REM units here because that's also what till wind uses and then we're going to say it should set 11 Ram from the right and actually this is going to be the the red color the other one will be the blue one this is going to be the more red yeah red reddish color so we also need to give this a height and width so we can say uh a height of 31.25 RAM and so you can see these are all custom uh values right and I'm I have wrapping on so when I make the size of my code editor smaller or wider it's going to wrap so that's why it looks a bit strange here with h and ends cut off but just because of my uh code wrapping here line wrapping all right so then the width is also going to be 31.25 Ram the exact same so then we can make it a circle by using a rounded full and then we want to make it very blurry and actually let's just see actually without the blur what we get that's now we just have a plain you know Circle but then the trick is to make it very blurry so we can say blur and also custom value of 10 Ram and then it's almost disappeared you almost don't see it but it's still here not very subtle which is what we want now we're also gonna work on responsiveness so until when you can use these uh break points so we're gonna say from small viewports and bigger right so this is this is It's mobile first until wins if it crushed acrosses some thresholds we're gonna increase the size a little bit so we're gonna say on small on small viewports and bigger the width should actually be 68.75 Ram right so if I save here and now for some reason it's not blurred anymore so let me refresh okay so for some reason it's not blurred anymore so let's see ah of course yeah so just a typo and so now it's blurred again and now we have a very subtle reddish color now we actually can just duplicate this entire div but let's just remove the empty one and just duplicate this and just change the color here so this one the blue one is to be DB D7 FB and this needs to set let's see only negative one Ram or actually it needs to be pulled up one ram to the to the top all right so then instead of right we're gonna have left and then the custom value is not going to be 11 Ram it's going to be negative 35 Ram all right now this one is a bit difficult here because you can imagine that as the viewport gets smaller and smaller you have to reposition these dots otherwise they're going to fall off the screen or they're gonna overlap with each other and the blue is going to become too dominant right so we want to have the red a little bit in here as well so we're gonna have a bunch of uh break points here just to position them a little bit better as the viewport changes so here from medium and onwards so we say MD the left should actually be negative 33 Ram and on large and you can also copy this if you don't want to type this out you can also just copy this on the GitHub repo so here we have on large we can say left should be negative 28 RAM and on XL it should be left negative 15 RAM and on 2XL it should be left negative 5 Ram all right so you can see almost every breakpoint we're changing the position a little bit and that's sometimes necessary right so with a huge element like this the positioning gets very awkward really often so you you really need to be precise on positioning for each break point all right so now if we have this you can see we have a little bit of color in the background right so if we compare this with the example you can see that looks about right all right looks a little bit more interesting now all right so we're using absolute here absolute positioning usually you then also want to use relative on the element that they should be positioned to relatively so if we go to this body here and we add the relative class they will be they will be positioned relative to the body right so make sure you also add this right and then I made one small mistake so for this blue one here the width should not be 31.25 but should be 50 RAM and what we also want to do is we're going to put content on top of it so we want to play with the Z index here we'll actually give it a negative Z index you can just do that by placing a minus in front of it and we'll just use 10 and just add the same one here then everything will be on top of these dots so if I save here it still works all right let's also add the fav icon so if you go to the GitHub repo you can just go into app and then here you'll see this faf icon file now if you click on that you won't see anything but you have a download button here so let's just download this and then it's downloaded here so then here I'm going to open up this sidebar and I'm going to click and drag this here in the app folder right and then I'll just change the name into fav icon right so next.js will automatically pick this up and make this the fav icon now I've noticed that during development that actually doesn't work so smoothly but then we will deploy it to for cell and make it live on the internet it works so you may actually not see anything here during development or maybe when you remove the cache here and try again but we'll leave it like this for now alright so make sure you have that file here in your app folder alright so then let's see what else are we going to need let me close everything here so we have the app folder here with page and layout we have this next folder which is just something that nextgs uses internally we don't really have to do anything here not modules for our installed packages and we also have a public folder where you can put static assets like images now we don't need these so let's actually remove these but this is also what we will use for example for the PDF file now what we're also going to use is a lib folder so let's actually create a new folder here in the root called lip as in a library and we're going to add some data here that we're going to use in the project so let's create a new file in here let's call it data.ts and in here what we're gonna place is if we go to lip right so you can go to GitHub repo go to lib and then into data.ts here you can see all the data that we're going to use so for example we're also going to use some links here right for the nav bar we're going to use this data for the experiences section the project and the skills right so we're not going to type all of this out by hand but we're just going to copy all of this let's just copy all of this and don't worry I'll explain everything as we start using this so I'm going to copy everything here from the data file and I'm gonna paste it right here all right now when you do that we get an issue because we are going to use icons here so so for example here we'll talk about what all of this means react create element what is that but you can see we're using this this icon here and it's coming from a package called react icons let's install it package I'm going to open up the terminal here I'm gonna close out of my server here and I'm gonna call I'm gonna run npm install react Dash icons as this is this is I think the most popular package for icons in react okay so then I can start the dev server again npm run Dev all right so now that error is gone now also what we're going to need is images so here you can see if we look at the project here in these in the project section we're using these images right now you can include images as an external URL or just like the fav icon we can place them here locally in a public folder that's that's what we're gonna do so let's go to the public folder this is the final code let's go into the public folder here you can see some of this actually all of the static assets that we're going to use so we have three images here and also a dummy PDF file right so that here when you click on this you are actually downloading a PDF file now we don't you don't have to download that what you can simply do is create a new file in the public folder and just call that cv.pdf right and we'll leave it empty for now in the real world you this should be your actually your actual CV file right or resume if you're American I get this notification but we don't need that this will just be an empty file here and then I want to have these three images in the public folder so I'm going to download them so I'm going to click uh download and the other ones as well and these three projects are actually projects of my JavaScript course so if you want to be a professional developer it is really important that you have mastered JavaScript so check out that course as well so then we can click and drag this here into the public folder right so just click and drag them here Corp command as well all right so that was a bit of uh hassle setting setting everything up but now we can close the GitHub repo and we have all the things that we need all right so I'm going to close everything here and so if I go to data now these images are being imported now we'll talk about what all of this means including what this at forward slash means right but we we don't want to write out everything here I've also talked about typescript right so we have as const here this is a typescript thing right we'll talk all about we'll talk all about that let's let's close everything here so we're still at our page here now let's continue by adding the header right so if you look at the header has six links and you can click on them and you will actually go to that section and there's a very cool and I'll actually zoom in a little bit more right so if I click here you can see there's a very cool background uh thingy or color that will actually move very smoothly with us as we go through the sections right it has even like a little bounce at the end of the animation and this is a typical animation that you can easily Implement with framer motion which is a very popular library for implementing animations and transitions it also works here by the way if we just manually scroll to a different section you can see that if I go from let's say uh this this project section to scales or about the scales it now becomes skills if I scroll down a little bit more and it's because I'm zoomed in that it's a bit uh confused back to 100 the project section is working properly as well right so this is very cool I think it looks a really nice header so let's implement this now I should mention it's also 100 responsive right some very small viewport it's gonna become this full width uh header and it still works the same way right very cool background effect blur background effect also very popular design drag now it also has a really cool intro animation so as we load the page you can see it sort of comes from up here down here and there's a bit of a bounce and this is really easy to implement actually with frame or motion alright so this is a component now where are we going to put components we could put them in the app directory but I think it's a bit cleaner in terms of project structure that we only keep the files that are actually directly related to routing in the app folder and then all the other components we're going to create a separate folder for them so let's do that let's create a new folder called components and here we're gonna have a header component header.tsx now you can use Snippets here so I have installed an extension here called es7 plus react Snippets so you can install it as well and then you can just type out RFC for example for a react functional component right so then you get this and then you can immediately change the name into proper casing and maybe you want to change that so if I save here I'm using prettier by the way so it will automatically get formatted for me so we don't want to return a DFA we actually do want to use the header tag that we have in HTML alright so this header is actually going to be two parts so we're gonna have the actual white background there's going to be one div and then we actually have a separate part which is the nav with the links and the text itself we need to do it separately because of the animation all right so here this header this is going to be the container that holds those two things so this one will only have a z index because we always want this to be on top we'll just use a custom value and we will also give this position relative because the other ones in here will be actually the ones in there will actually be position fixed but we need to make this relative to make the Z index work right it has to do with how the Z index works all right so let's start off with the device background and I'm going to now let's start off with that white background um it's actually just be an empty div but we're going to style it as follows so this will actually be fixed because we want both the white background as well as the text will will also be fixed we wanted to scroll with us so Zero from the top 50 from the left and this is actually going to be on small screens so right so we're going to have a breakpoint uh soon and that will be for the wider screens so rounded none it's gonna have a border border white border opacity of 40 right so quite a few classes here if you don't want to type along maybe you're cutting along and this is a bit too much for you you can also go to the GitHub repo and just copy it for the header and we're going to have a bit of see-through right so if we scroll down here you can see the backgrounds here is slightly see-through and has a bit of a blur effect this is a very popular design technique as well these days so to do that we just have to make the background white so we say BG white and then we can just change the BG opacity to 80 percent we're also going to give it a shadow and we're going to change the shadow color so we can say shadow black and then it's forward slash and then square brackets point zero three so three percent opacity now for that blurred background we can use a backdrop blur and then it's 0.5 Ram alright so then for wider viewports from smaller and bigger we'll say excuse it should use top six and then the height should be 3.25 Ram and the width should be 36 Ram and we'll have rounded full okay so that's quite a few uh quite a lot of styling again check out the CSS course if you want to know what all of this is I want to explain everything but we just don't have the time right but I mean position fixed means it's going to scroll with us right so now it's here and we'll scroll with us all right so I actually added some height to the body here so we can scroll uh this is just temporary right so quite a few classes here and if we go now back now you can see we have this now let's just add some Heights here so we can actually scroll down so here in the body I'm just gonna say height of let's say 5000 pixels we'll remove this later but now we can scroll down and you can see it scrolls with us all right now if you do this this won't work yet because we need to add this to the page right so remember the root is the layout here and here we have this children prop and this will basically be the page right now typically what you're going to have is this header is going to be the same for all pages and here we're only going to have one page but typically you have the header here and then the page main content here and then a footer here will add the footer later so let's just add this header here and you also need to import this right so here we're saying import header from ads components header right so why is this at well this ads is just uh an easier way of writing these paths because sometimes you're gonna have like dot overslash dot dot to go up a folder and then go up another folder so to prevent all of that we can just have this add and this is just an alias or well in this case you can see is if you go to TS config next JS has automatically set this up for us you can see here that this add forward slash is basically an alias for DOT forward slash here so that's that means the root here so that means when you see add it means start from the root then go into components the components folder and then it's this header file right and it's a it's a default export so it's export default function header so we could import like this without curly braces if it was not a default export but just normal export a named export now we get an error so you have to add the curly braces in that case and then the error disappears again right but let's keep it the default export so we can import it like this all right so now when we do this we see this rectangular rounds Corner shape on the page it scrolls with us but of course it's not sitting in the center so what we can do and the reason is that we're saying I should set 50 from the left here so that means it's going to take 50 and then it puts the element there but that's not what we want we want the center of this element to coincide with the center of the page so we have to put it back a little bit so what we can do is we can use transform translate and we want to use a negative value so you can use a minus in front translate X and then it should be half that's going to be half its own size it's going to be pulled back by half its own size so now it's perfectly in the center all right now let's try to animate this before we add the text let's just try and see if we can get that cool intro animation and we're going to use something called framer motion this is a very popular library and as a front-end developer you definitely need to know this so we need to install that it's a it's a package so we can go to terminal again and I can install this here just leave that running and just open up a new terminal right so you can click on this I have this running now I can click on plus and I get a new terminal window so we're going to say npm install framer motion right so maybe you've heard of framer that's a design software and they've actually published this package and we can use that so let's install that all right so now it's installed I can close this this is still running and what we can do instead of having a normal div element like this we're going to make this a motion div so let's actually import this manually so we can say Imports motion from framer motion copilot already suggests for me and then we can use this motion it always works like this you just write motion dot in front of it and also make sure you get the closing tag right so instead of a normal div it now becomes motion.div and this gives us some special props that we can use right so all of the normal props of the div still work but now also some additional ones and those are going to be the following so we can say initially and actually we already get some suggestions here from Copilot so here we can say the initial position of this uh thing this element should sit let's see negative 100 that means 100 pixels higher and the opacity initially should be zero that's the that's going to be the initial position and then again I get some suggestions and this is actually what we want so I'm going to I'm going to press tab here right so copilot by the way if you don't have it yet definitely get it it's so worth it it's easily worth the money so uh yeah it's not even a debate in my opinion like you can make the ROI calculation but it's easily worth it I think it's like 15 per month or something like this but uh what you get back for that is much more than 15 in value all right so here um what we're gonna say is this animation should make this a y should be Simply Be zero again so no movement so that means it's going to start off higher and then it's gonna go back to here and the opacity should become one all right let's actually see what we get so let's save here and now if we refresh and actually we get an error ah I already clicked refresh yeah so we're gonna get an error here because this motion.div is using use effect when we don't see that here but in the implement this is a component and this is using use effects and that's a react hook and we can only use that in so-called client components so we need to make this header a client component you can do that by going up here and say use client right so ideally we could keep this a server component because there are certain advantages to that so um by default everything in the app folder is a server component and so if you import something from the components folder in there it's also going to be a server component but here we actually explicitly made it a client component so now this is this this is going to be a client component and we lose some of the benefits but in a small project like this it doesn't really matter that much but now what we get in return is all of all sorts of client-side functionality so we can interact with the browser apis we can use use State use effect right so if you need to interact if you have some kind of interactive components that's going to be a client component and if you have a more presentational component that's going to be a server component all right we'll talk more about that all right so let's refresh here and you can see it's already working we have a really cool intro animation here very easy to set up we don't have to write any CSS ourselves and it has a little bounce in there right that's the default animation that motion framework motion has we can customize it but actually like it so let's keep it it's very playful and what it's basically doing is it's using CSS animations and transitions under the hood right so if you if you already went through my CSS course or you're already familiar with that this is going to be very easy to pick up so if you now of course the position here isn't correct and the reason is actually because it's using that transition here so here we actually manually set the translates here there's a transform but here we're sort of overriding that because it's going to create a new transform for that so here what we're going to do this is a bit Advanced and this is where it's really this is an example of where it's really important that you understand the fundamentals so here you really need to understand CSS animations and transitions so what framer is doing is it's going to create a new transform uh rule it's going to create a new transform declaration when it does this animation which will override this what we wrote here so instead of doing it ourselves like this we can just make this make framework just take this as well and so both initially and at the end it should just be that negative 50 so we can remove it what we just had and just have one transform basically from frame or motion all right so if I save Here and Now go back you can see it's positioned in the center and we have a super cool intro animation right and just to prove this to you here in the in the elements tab let me zoom in a little bit you can see here it's using transform right we aren't we didn't write this Transformers coming from framer motion here right so translate X that's it's what it's doing here and opacity one is also coming from here right so just CSS animations and transitions um this is super easy to pick up once you have Masters uh CSS itself so definitely make sure you uh you learn that uh properly now let's also check responsiveness here so if I make this a little bit smaller you can see indeed it's a responsive and also let's see if the animation works properly here yeah animation also works alright so nice now let's add of course the actual text here right so the actual links so ideally we could just write that in here right like normally however we're also going to animate these links themselves um and I mean the the background thingy right so you can see the background thingy changes right there's also an animation from framer and unfortunately I run into issues if I try to do that within this motion.div so the only solution that I could come up with is to Simply split it split this up in in a different elements here outside this div so now we're going to have that nav and that's gonna that's gonna hold the actual links or this should also be scrolling with us right so it's going to have some of the same style so set fixed I should sit a bit more from the top now we'll make that a custom value here it should also sit 50 from the left will give it some height we're gonna pull it back a little bit right because there's 50 from the left but that's too much so here we are pulling it back a little bit but we're doing it through frame or motion here we're not we're not going to use that on the nav itself so here we have to do it ourselves trans using negative negative Translate X one and a half and we'll add some padding vertically and then some responsiveness here so we'll change this to a 1.7 RAM and we'll reset the height and we'll remove the padding here right so we have to make our projects responsive you do that with these breakpoints it's a bit annoying until then that you have to keep writing SM instead of once you have to write it for each property that you're changing all right so that's the nav itself now in there we're gonna have a list of links right so this is a list so we're gonna have UL and that's going to hold all of those links now those links let's see we have copied that from the GitHub repo in here right so this is part of the data so these are the links that we have right so each link is actually just it's going to be a list of links so it's an array in JavaScript and each object represents one link that has a name or home and then a hash and so we're going to use if I make this not full screen if you look at the URL if I click here it's we're using hash for routing I'm not really routing it's basically just a section on the page and that will also easily make make this very smooth with the scrolling right so it is just a hash all right so we need to import this this is not a default export this is a named export so here in the header if we want to import that we have to use the curly braces so it will say import links from and it actually already suggests this for me but just to make it clear to you this lip folder is in the root of our project and so we can start from the root that adds forward slash go into lib and then in data right we don't have to provide the extension here the bundler will automatically uh okay so now we have access to those links remember it's an array of objects oops so here in this list we're going to map over that and you can see Copart already suggests this for me now of course these are the things that you may already know um I like to put it on a new line here so links.nap we're gonna get uh link objects and what we're gonna return for each link is the following I'm using parentheses here not curly princess so we got a suggestion here from uh copilot and we're not going to use that here we need to use uh An Li and remember if you're mapping here in react you have to give each element a unique key you could use the index here it's not terrible but here we're going to use link.hash because we know that the hash has to be unique now then in here you typically have the anchor tag the actual link now in next.js nextgens comes with a custom link component which has certain benefits and also has to do with like browser history so when you click on back and forth it it keeps track of all sorts of things so better to use the the component that nextgens gives us if we can so we can actually just write that so if we write link you should see some suggestion here for the next link if you press if you click on that or brush tab it will automatically import that for you if it didn't import this for you you can just import it like this right so that's the link that we want and actually it's not self-closing because we actually want some text in there right so then here what we will output in within the the link is the link name right link name is going to be home about all right so here we get an issue so this link needs an ahref right so here's where we're going to add the hash so here we can just say link does hash and I'm Gonna Save here and then let's see what we got it's gonna be uh it's not gonna be looking good because we haven't started yet but we can see the links are now here I can also click on it and indeed we see the URL changing right I'm gonna remove that for now all right so let's make sure that it's just positioned properly on top of this white uh element that we created before so this list these these lies that should sit we're going to use flexbox here right flexbox is so important make sure you uh have massive flexbox so we can just runs flex and it will already position all of these horizontally as the default layouts in the flexbox and then let me actually make this a bit smaller so you can see what's going to happen as I type these classes so we'll give this a width of 22 Ram will allow the flex items to wrap it's especially important on the smallest viewports we're going to Center them vertically and also Center them horizontally we're going to add a gap vertically but that's more important on mobile we're going to set the the text size to 0.9 Ram we're going to make the font weight font medium the color should be text Gray right that we talked about the color palette so you can just use text and then whatever that color from the color palette is or BG you can use that gray color right so whenever you can provide a color you can use that from the color palette the text Gray 500 now on wider viewports we're going to reset that width to initial and we're going to say it's not allowed to wrap on wider viewport so from small and up and also on small and up we're going to have both horizontally and vertically a gap of five all right so when I save here this is what we have now it's not perfect yet so we also need to style the Lis themselves here and also the links so here we need to give these lies a height of 3 4 so that will make it 75 percent height of their parents element and then we're going to Center the link in there so it's easy to do center with flexbox so we're just going to say Flex item Center and justify Center all right and then the actual link we're also going to Center the text within here so we're again it's easier to do that with flexbox so we're going to say the width should be full item Center justify Center uh padding horizontally and padding vertically and when we hover these items we want to change the color so we can say hover colon text Gray the default is 500 here in this list so here we're going to make a darker 950. okay so then we have this if you hover it you can see the color changes but it's not very smooth so to make it smooth we can just say transition which will make it a CSS transition a bit smoother alright so this looks good let's double check responsiveness here and here on mobile it's a bit uh the sizing is off here and I think we just missed one class here yeah so we just have to add one class here to the nav it also needs to be a flex container so when we do that and now go back yeah it's also responsive all right cool now let's add the animation so here in the example it should just follow the animation of the white uh div behind it now we could do it with it enough right because we could say motion.nav but we're going to have an additional animation here for these lies or the the backgrounds here basically and I found that it's better and easier to do this with the LI so if we just if we just make this the motion component right so this is just something that I found during development so we're going to make the Allies to motion.li so make sure both opening oops both opening and closing tags are motion components now and then we can access to the motion props so if I type here oh actually I copilot already gives me the right ones and actually this is the same as before right so here we can just press tab all right so if we try this if I saved here and now you can see if I refresh we have a very cool header animation right so it's pretty cool nice little bounce and yeah I think it looks really playful really uh really slick all right now before we implement the rest of the functionality here right so here we want to have basically we want to keep track of the active section let's actually add some sections before we do that so let's actually continue with this intro section so we will have a photo we will have some text and then we'll have some buttons here with some hover effects and of course this also has an intro animation right so we have an emoji here right so I think this looks pretty cool all right so uh here we have a pretty cool animation as well as also the default animation with a bouncy effect or a spring animation officially as it's called all right so we'll add some uh sections and then we'll come back to the nav to actually Implement an active section feature there's one more thing I want to mention about these links that we imported so if we go to data here and so we are importing this and it says links.nap and then we get the actual link objects now we're using typescript here so we're doing something here that's a typescript feature which is we're saying s const so if we leave this off and let's see what we get so here when I do this it's going to we're not explicitly typing this so typescript will try to infer what this is what these types are so here if I hover links you can see it's inferring that this is an array of objects with a name that is a string and a hash that is a string and this is correct of course right these are not numbers right we don't want to have numbers here right so then here when I go to links we can see it's an array and then we can see the link is indeed an object with name strain hash string right and this is this is fine but we can be even more precise and generally speaking typescript is about yeah it's a it's really about being more precise so we can be more precise because this is not not just going to be any string right so here we're just saying could be any string it could be any hash and here is since it's a constant this will this will not really change if we have to add another uh route we will just add that here but it will not it will not run it will not be any kind of random strain right so it will always be exactly what's in the array here so we can be more precise so not just any string we can say this should be exactly as it's written now right so it should be specifically these strings so the first link is going to be an object with name home and hash home so not just any string it's going to be specifically that string now when you do s const it will also make all of this read only right so now when you go back to this link it knows that this link is not just going to be any string but it's going to be specifically one of these strings right so it's it's a little bit more precise right so you can tack on S const and actually that's what we're going to do with these other constants as well because these are not going to be random strings right so these are only going to be the strings that we explicitly Define here so yeah we just make a little bit more precise and in return for that we get some better intellisense here here we we can see what the actual strings are going to be all right so let's continue with the intro section so we're going to have an image with emoji text and buttons so let me close this so where should we add that well remember we're going to use the app folder only for if it's a route now technically the intersection you you could see it as a route but it's not going to be a separate page or anything so we're just going to put that here in the components folder so we'll say intro dot TSX right because we're not going to use the actual app directory features like make this uh an intro and then make this a separate page.ts that's how you would do it and then you would get slash intro as the route right but here we're going to have everything on one page so we're not going to use that functionality all right so here to quickly scaffold a components I can use my extension just write RFC and this is what we get exchange it to uppercase intro but components need to be still need to be written with uppercase alright so then here instead of using a div it's better to use a section tag because everything in here is related to each other right so if if everything belongs to the same semantic meaning it's better to use the section tag if you're just using a div for styling or to quickly split up one part from the other it's better to use div right which stands for divider section is a little is basically the same as div but it has more semantic meaning alright so let's just add all the all the things that we're gonna need so in this section we're gonna have the upper part here which is just going to be this image so we're going to have a div but the div is going to stretch all the way so we're going to have another div that will just hold this image and the Emoji so we'll have that div that stretches all the way and we'll give this some class names we'll use flexbox again item Center and justify Center now this stretches all the way but this will Center the following div right so this Flex here is centering this div within it and in this div we will have the image and Emoji so next.js also has an image component so if you type image and for me it's the second option here so if I pick this one it will automatically import this image component from next.js whereas it's self-closing so here we need to provide a couple of things so if you hover it we now have an issue they have an ALT problem but we of course also need a source in the first place now the source for this image you can find that on unsplash so you can go to unsplash.com and you can find somebody's image or of course use your own image a photo of yourself so I found a photo on unsplash and you can find the link in description if you want the exact same this is the one I'm using and then we also need to provide an ALT property for accessibility but also for search engines so they know what the image is about so we can just say Ricardo portrait and if you save now we will actually get an error because this is an external image so let's see what happens and and actually nothing happens yet because we haven't included this intro component into our app yet all right so let's go to let's see the layout so there's a layout right now we have these two divs right there's a lot of colors in the background we added the header and we're going to add a photo later and then we have this children prop and that will just be the page right so we don't want to add the intro and everything else to the layout we just want to add this to the home page right so the home page will have all of those sections so here we just have an empty main here for now let's actually add that intro component so we'll just say intro and here to automatically import it you can put you can place the cursor here press Ctrl or command space and then it will already suggest this import all right so if I save here let's see what we got and we're going to get this error yeah so with next.js if you're using an external image meaning it's not here in your local file system right so remember we're going to have some images here these are local right and ideally you do have them local because it allows nextgens to optimize them a little bit better but here we're using an external image and when you do that you need to provide the width as all under width and height properties yourself so here if it's a local image next you as well it will actually add the width and height itself you don't have to do that but here is an external image we're going to set it to 192 ourselves now we actually can also set a quality prop so next year as we'll optimize this image and by default it will make it something like 80 quality now we're going to make it 95 so we still have some uh Savings in terms of size but it won't it won't really be a big difference in terms of quality and since this image is also above the fold and it's basically the the only image in the in the first image above default it's also generally recommended to add priority is true here so this will image will be loaded as fast as possible and actually you can see we get an issue here because we're providing a string here this should be a Boolean true all right so if we save here let's see if it works it still won't work because we have to do something else yeah so now what we get is it says something about invalid Source prop host name images is not configured under images in next config so what you need to do is go to the config file for next year s so when you create a next year JS project it will already have that file as well let's see here's next config.js so in this object we need to add so we can actually click here usually next.js has some information about a particular error so here you can see you they want you to add this so here in the config we just have to add images and then the domains it's actually suggested by copilot but according to next year asset should be remote patterns and it's going to be an array and then it's an object with uh let's see I think the most important thing is hostname so the hostname of this image is images.unsplash.com and we don't have to add port or path name now protocol would also be a good idea that will say https and now we can use this hostname with with secure protocol and when you use external links right so now when we go back and let's refresh so see if that works and that doesn't work for some reason my server stopped running so I'm going to restart all right so now I'm gonna load the page again and again yeah next chance is a bit slow with startup but also when you make a change so it's going to take some time all right so we see the image let's quickly style this image well we'll position it better in a second so class name needs to be uh it needs to have a certain height so we'll say h24 w24 this will make it a circle round full and we'll also add a border so we'll add a border and it's going to be of size 0.35 RAM and the color is going to be border white as suggested here now typically when you work with images they have a certain aspect ratio so when you start playing with the height and width I consider it a best practice to also use object cover which will preserve the aspect ratio sometimes you want to use object fit but usually it's object cover and will actually also give it a shadow so box Shadow so Shadow XL okay we'll deal with the positioning in a second now let's also add the Emoji so here after the image will use a span here and that emoji you on Windows I can press the Windows key and Dot and so Windows key period and that will give me this menu here with Emojis now I'm going to use this waving hand symbol just click on that and I get this here I'm actually not sure what the exact combination is on Mac but you can also just Google a hand waving emoji and you can just copy and paste that or you can go to the GitHub repo for this project and go into this file and just copy it Ctrl C command C and just paste it into your file right so you can actually you can also just Google this hand waving emoji and here's emojipedia and here you can just copy it right and then paste it here now this this emojis are actually just text so we can just style it like text so here we can say text dash for Excel so we're just setting a font size essentially and you can see it actually responds to that you can also select it like text alright so let's quickly deal with the positioning here why is it sitting below the nav bar isn't the nav bar taking up any space and actually the the header here it's it's all position fixed which will take it out of the normal flow as it's called so now when we add this stuff here it's going to act as if this doesn't exist so it's just going to be right at the beginning here right so this when you use position fixed it's not going to take up any space anymore so if you're using a fixed header typically the way to solve this is to go to the body element and here in the body we can just add some padding to the top to push everything down again alright so we can just add some padding on top of 28 and then on wider viewports we can make that 36. when you do that it will push this down again all right let's also make sure that this Emoji is on top of the image here I'm gonna close here so here we're gonna say this Emoji needs to be absolutely positioned so say position absolute now here we have those offsets again right bottom right and bottom top left right and when you use position absolute that's usually you also want to use position relative on some other element to which those offsets are relative to so zero pixels from the top but the top of what exactly well we'll make this div the relative element so relative to this element it should set so many pixels from the top for example right so now if we do this top zero it's going to be Zero from the top of that div so in this case actually we want Zero from the bottom and zero from the right and then it will be positioned right there all right let's also animate this so here right now only the navbar headers animators in the example if you just look at the image here we should also see an animation okay so the photo itself is actually not bouncy it's just animating normally you could say and then this this hand emoji actually has a pretty pronounced bout so we can customize these animations as well so let's see how we can do that now for this image here to animate this remember we have to use emotion.div or motion dot image now here we have uh you know the next Jazz image component and there are ways to do that a bit easier with framework motion there's a way to use custom to animate custom components but the easiest way still is to Simply wrap this in a div so I'm going to I'm just going to put a div around this image put the image in there and instead of div it's going to be emotion.diff oops motion dot div now here we can put the cursor Ctrl spacebar and actually we don't see we don't see the suggestion here for the import so here we'll just import and actually we get a suggestion here from copilot so we'll just use that all right so then to animate this and actually we get an issue here because this motion component is using some react Hooks and this is right now a server component so we need to convert this to a client's component we do that by just writing use client at the top and we lose some benefits right so we we lose some benefits of doing that but in a project like this these are very almost negligible benefits so this component your client components are still pre-rendered on the server so the initial request will still have their HTML it's just that on subsequent renders it will not come from the server it will be done on the client uh so here this motion component is using uh use effect and use state but that will that will that will take up resources on the client essentially but we we're fine with that because we get some nice animations in return so here we say motion.div so here we can use those props again that we got so we can say initially there should be something so here we get the suggestion opacity zero which is actually what we want but instead of Y we want to make this a scale and so we can actually also make it smaller or bigger and then the animate is going to be well just normal opacity and normal scale and actually let's see what we get if we do this we have enough refresh you can see that we have a nice uh into animation for the photo now this has That Bouncy effect again or spring effect but this time we actually just want a normal a normal transition so you can also customize this so we can use the transition prop transition and here we're going to say type spring is actually the default so let's get the bouncy effects we also have tween this is going to be a smooth non-bounce V1 and we can also set the duration to let's say 0.2 all right so now if I refresh you can see it's a nice quick smooth and you could say normal animation and the reason for the normal animation is so that we can now make this Emoji a little bit more bouncy because if you also make the photo bouncy it's a bit too much so we want to make this a little bit more subtle with just a normal or tween transition now let's go to the Emoji here and we can actually just use motion.span right so we can just say motion dot span and it will work the exact same but we get some additional props so here we're gonna say initial the opacity and scale should be zero indeed so we can actually just take the suggestion from Copilot animate should indeed also be opacity 1 and scale 1. and then for transition we need to customize this so here we actually do want a type of spring right which is That Bouncy effect and then we can actually customize how bouncy it should be basically it should be super bouncy or a bit more stiff so you can set some settings here so we can set the set the stiffness to 125 and we also want to add some delay here or we can also set damping but we'll we'll leave that we also want to add a delance and it shouldn't immediately start should start a little bit after the photo has already started to animate so we'll add a delay here of uh 0.1 seconds and the total duration of this one should be 0.7 but now if we save this let's see what we get all right that looks pretty cool I think and it's very easy to do with the framework motion now to be honest this would have not been super difficult with a normal CSS animations and transitions now we are using till when CSS and I always find the animations a bit tricky to do because you you can you can you know you you have to sort of Define them here in the Tailwind config um and there are other ways to do it but in plain CSS it would be easier to do the Tailwind in my opinion but this works uh even easier I think so uh yeah frame of motion is definitely worth it to learn as a front-end developer let's continue with the text below the photo here so this is just a three sentences or four sentences or so and it's a bit it's a bit of uh the mark appears quite a lot so I can actually just collapse this so here after this div we'll have the text that's actually just going to be a paragraph so we can say paragraph and we we got some suggestion here so our copilot probably found this on GitHub or somewhere else from somebody that's actually called the Ricardo now We're Not Gonna we don't have to write all of this ourselves you can just copy this from the GitHub repo right so you can go to the repo go into component intro and you can copy and paste this text or you can write it out if you want now what I did here is some of these and actually we get an error here or someone's rest quickly so let's see what we get yeah so here the issue is that we're using this uh apostrophe so when you use these apostrophes sometimes that can give an issue here so if you're in react in jsx and you're using these apostrophes sometimes you get these issues so the easiest way is to Simply make this a template literal so I will just use curly braces here so we can use JavaScript and we just we're just going to make this a tactics right so just wrap all of this in backticks that's a template literal JavaScript feature so we have to do that in these curly presence and let's see if I do that we get an error let's see why ah okay yeah I I put it at the end after span right so it should be uh before the closing tag of the span here and that's not gonna work because it's actually going to write out the inner spans that we have to spice up the text a little bit with for example make the folds a little bit bolder or make it italic it's actually going to make that literally span so it won't interpret this as HTML anymore or as RS jsx and so I'm going to undo that and save it we still have that issue all right now if you hover it this is coming from eslint which is a linter here used in xjs and they will actually explain why this gives us this issue right so a linter is just basically checking your syntax to prevent certain issues so if we click here they give some examples of why this can be an issue so here this this particular rule um they have some examples now I find the examples a bit contrived and I think if we make this mistake for example we'll it we will be notified in a different way so I think it's safe to ignore this rule so what do you want to do if you think the linter is being a bit too strict and you want to ignore this issue because the alternative would be writing something like um something like this so we have to uh you know for every apostrophe we have to use this HTML entity I think this looks really ugly and I don't I don't want to write this I just want to write it like this and I'm willing to accept well the risk I guess I don't think there's a real risk here but I'm willing to ignore this rule so what you can do there is an eslint configuration file here in your project and here we can say extends and we can say rules and actually we already got the suggestion make sure you write rules and double quotation because it's a Json file and then this rule is called react forward slash no unescaped entities you can write off as a string or assign number zero right so true would be one you can also write true or one if you want it on but by default it's on so it doesn't make sense so we can write zero here if we don't go back you can see that warning is gone all right so let's start this paragraph a little bit more right so you can get the text from going into the GitHub repo now about these spans that we have in here I think it usually looks a little bit better if you are spicing up text a little bit so here if we just had the same font weight no itemic no underline it would look a little bit plain so you want to break up the text a little bit by making some parts a little bit Bolder right so we made this a little bit Bolder this is italic this has an underline it just spices up the text a little bit to make it look better we'll also do that here in the About Me section so you can see some of these are a little bit Bolder we have an underline here we have some italic hair it just makes it look a little bit more interesting right so quick design trick so here we can add margin on the bottom and on the top and padding horizontal and text size the the default uh font weight here and what we're going to say here is leading this is basically line height now when you set the font size until when like text to XL it will actually also set the font the the line height so here we are trying to overwrite this uh by setting is with this lead is called leading I actually think it's a bit confusing leading but this will actually also set the line Heights but now we have to clash so here we need to over we need to force it to use this one so we can use the important role in CSS until when you just have to write the exclamation mark in front you don't want to do it too often but typically this is a use case where you want to override something from a library and then let's say attack should be a bit bigger on smaller and up all right so then we get this right so this already looks better I think by the way we also have these things in here and this is just to add space so let's see we have I'm a and then we have that full stack if I remove this it could sit next to each other so if I remove this yeah it's gonna sit next to each other so you sometimes you have to make it explicit that you want a space there and what what you can also do if you can actually remove it but then you have to put it on the same line here so and then add the space here now I'm using prettier so it automatically formats this for me so so uh this is what I get all right so it's currently aligned here to the left and also it's not restricted in width right so it should be centered here the whole section should be uh restricted in width as well so let's go to the section element and here we can simply that actually adds some margin on the bottom and then let's set the maximum width so we can say Max W will make it 50 Ram the any text should be centered and we want to remove that margin on the bottom on us on wider viewports all right so now it's centered at least within its own section but the section itself on the page should also be centered and all the other sections as well and it's better to go to the page here because here we're going to have all of these sections right so we're going to have about and projects we're gonna have all of them and they should all be centered on the page right they're all going to have their own maximum width but then from the perspective of the page here they should be centered right not aligned to the left so to Center something we can simply use flexbox right so we can say Flex now this will position everything horizontally so here we want to make it a column and then we can use item Center to uh Center all the sections we also want to add some padding horizontally for responsiveness so it's not going to sit right against the edge right so now it's centered all right now let's also animate the paragraph let's go to the intro and here we have this paragraph we can make this motion dot P right so now it's a paragraph element still but we get all of these uh extra props from framework motion so initial we can say uh well let's take this but then customize this to a hundred so it's going to sit a bit lower this time right so it's not negative it's a positive number so it's going to sit lower initially and then to animate this we're going to make this simply opacity one and zero movement let's see what we get all together all right so you can see the text is moving up and it's all coming together pretty nicely I think really cool intro animation all right let's continue with the last part of the section which are these buttons so we're going to have a contact me here button which will scroll all the way down actually it will just link to that contact Section with hash content contact and that will automatically scroll the the browser to that section we'll see how to implement that in a second we will also have this download CV which will actually download a file and then we just have two links right so if you click there it will actually go to Links in and this will go to GitHub right so you should add your actual links here so we're gonna wrap all of that in a div and then we have those four buttons now the first one is just basically a normal link right just linking to a particular section so for those ones you actually do want to use the link uh component from next to S so here we can write link and press here it will automatically import for me so make sure you are actually importing it and then here I will use the suggestion but instead of going to slash about it should be hashtag contact okay and then to close this the text in here should be contact me here and then we want to have an icon so let's see if let's see if we can automatically import that so here if I start typing BS Arrow right valve closing so now if I do control spacebar we don't get any suggestions so I have to import this manually and actually uh well copilot already suggested for me right so these react icons is just react icons and then whatever this prefix is it's going to be forward slash BS in this case okay I'll save here to see what we got okay now we have this we'll style this in a second ah actually let's style this right now so we can just add a class name here and it should get a background color background gray 900 it should get text of white padding horizontally of seven and we'll use padding vertically three let's see what that gives us all right so it looks uh not so good um we'll use flex here and then item Center to Center everything including the uh icon vertically I got some suggestions here from copilot but I don't want these so I'm not going to accept we need to add some space and since we're using flexbox here we can use the Gap space between the icon and text right so text is actually also treated as a flex item here right so we essentially have two Flex items here that's how a flexbox works and I think I can remove this I don't see why we need that so I can actually remove that yeah we also want to make it rounded so we'll say rounded full all right now it's stretching all the way but I think that will be solved when we add the other buttons let's just add the other buttons now so now we're gonna have that download CV button and actually I will deal with the hover effects later so let's add the anchor tag here this is going to be a normal anchor tag because now we actually want to download something so here we'll use the a tag and this will say download CV and in here we want to have an icon it's going to be h i download enough closing and we don't get the suggestions so I'm gonna quickly copy or import this here and again we get the suggestion from Copilot right very easy all right so class name this one is actually going to be BG white that's not a design tip is usually you want to have one primary button and then you can have you know more secondary tertiary buttons so typically you do want to have a way to de-emphasize the secondary button so here we just make the we just make it a little bit different so the background color is going to be white which instantly de-emphasizes them compared to this primary button and actually it's using a lot of same Styles we might as well just copy everything from the other button and then we'll just change it a little bit so I'm just going to paste everything instead of BG gray it's going to be BG white here and the text should not be wired because now the background is white so the text needs to be dark and the text can just be the default color on the page and we can just remove that all right let's see what we guess all right so now we have this button here and again prettier is adding this space for me but I think we don't need that all right so then we get these other two links now these are actually going to be external links so they will actually navigate to a different website so in that case you also want to use the normal anchor tag right and the only thing in here is going to be the logo for LinkedIn so we said BS links in and this time if you go here with your cursor press com control spacebar command spacebar we actually do get a suggestion for Auto Import so we can just click here or pay or Tab and it will automatically import this all right so for styling we can actually use most of this so let's copy everything from the secondary button there but now we will use P4 instead of PX and py and the text should be a little bit more de-emphasized so instead of the default color we're going to make it it's going to be 950 We're gonna make it 700 here all right so then we have that now the width will be restricted once we make their parent elements a flex container in a second let's copy this entire icon here or the other link as well which is going to be the GitHub link so that's going to be F A GitHub square and we get a default import suggestion so I'm just gonna accept that and save the file and now we get this this one needs to be a little bit bigger you can see the icon is just a little bit smaller so he will add a custom size 1.35 Ram and now it looks a little bit too big but let's uh let's work on the layout first maybe uh this will automatically be solved once we start playing around with the layout all right so these buttons now are all sitting in this diff right so with flexbox you always want to identify the parent element that's this div here so then we can just make this Flex right and a default layout is that they're all going to sit on the same line horizontally now on small devices it should be a vertical layout so we can say Flex call and then from small and larger we it should be this default X row right so till the end is mobile first so it's always a bit strange to you know I mean for me at least because I like to develop from desktop first but what we're doing here is we're saying on the smallest devices it should be column layout so vertical and then from small and larger it should be row right so that's what we see here but if I make this if I save here we're gonna get we're gonna get row right but then on smaller viewports so we're going to get that stack layout okay all right we'll just Center everything justify Center and we'll add some space between them and we'll also add some space on the sides we will increase the default font size in in this div and we'll make the font weight medium all right so now it looks a little bit better yeah now these icons are also the same size because that's actually going to be text LG for the LinkedIn icon all right so let's actually quickly add the intro animation for this entire section here of these buttons so again very easy just make this motion dot div right make sure you have the closing tag as well and then we have initial and I will just accept this this is actually exactly what we want and indeed opacity should be one at the end and just zero movements right so Y is zero now it usually looks a little bit better if you stagger or if you have a small delay for the outer elements so it really feels like they're flowing in one after the other so here we want to add a small delay so you can customize this with transition and just say delay of 0.1 and now if I save here and if I refresh to see everything together all right I think that looks really cool yeah all right so we need to take care of some details here so also hover effects so let's uh go back to the first button here now when this button becomes focused so if I click here and then press tab you can see we get this outline and instead of having that outline we're going to have a different uh Focus indicator usually this outline we don't really want that doesn't look so good now you do want to have some kind of focus indicator for accessibility so here though we want to remove this default one so we can say outline none and then we can say Focus so then in the focus State we'll have a different one we're gonna just make it a bit bigger right so now if I do this and now if I click here just a little bit next to it and then press tab in the focus State it's now going to be bigger so it's still a good indicator that this is focused now of course we also want to have a hover effect and we actually want the same in the hover state so we can say hover scale 110 as well now in the hover state so another one we also want to change the background color to BG gray 950 and we also have an active state which is when you are pressing down on the button oh we can say scale should be a little bit less okay and now you hover it and when you click it you can see there is some scaling I think that looks pretty cool and then so when you click on it it really feels like you're you're clicking on it because of that active uh to the class all right now it's not very smooth because it's all instant so we want to have a CSS transmission until then you can just write transition or transition all it's a bit annoying because now for this one little change I save here and I have to wait almost like a full seconds before I can start oh yeah I have to wait more than a second to start checking it so I really hope the next JS team can speed up the dev server right so now if I click here and press down it's all very smooth right in a focus State it's also very smooth and so with DCS as transitions it means any any change actually we can hover at any change in these properties so color background color shouldn't happen instantly it should happen in well 1.5 seconds and it's a particular timing function that they have right so scale is actually part of transform it's also a standalone property in CSS these days but uh for support it's better to have transform so transform as a scale and also translate and rotate and skew all right let's also style the icon a bit because I always think there's another design tip it usually looks a bit better if the icon next to the text is a little bit it de-emphasized or is like a bit lower opacity or has a more de-emphasized color because here it's it's the exact same white right so the easiest way is to go to that icon here and just reduce the opacity a bit so that we can make it 70 opacity and now let's see because now we have to wait a full second again right so it's very annoying during development but you know team is working on that so now you can see it looks a bit better I think and how to make it really cool is when we hover this button we want the icon to move a little bit to the right right so here it's not just hovering right so we cannot just say hover uh uh and then you know move to the right because it should be hover on the entire button not just hovering the icon but when I hover this entire button I want to move this to the right so how do you do that until wind well you make this a group hover so you add the group class to the element that actually should be hovered right or is the target of hovering right so we say group here and then when this group gets hovered so now you go to the icon in this case and now you say group hover right and now we can do whatever we want so we can say translate x one and that should be smooth so we're also going to add a transition here right save wait a full second and now when we hover you can see there's a very smooth uh animation or a transition of this icon to the right all right let's uh let's do the same for this other button we can copy a lot here so let's copy all of these from outline none to well transition here let's copy all of that and I'm going to add some space here so we can distinguish these individual buttons so now for this secondary button I'm gonna paste this let's actually save here and now yeah so now we get a different background color which is not what we want so we can remove this class we don't want to change the color on Hover background color now here we're also going to add the the group class because we want to move this element this icon down a little bit when we hover it so let me save here I'm gonna as a group here and then here for this icon when we hover it it should move down a little bit so we'll actually also make it a little bit uh de-emphasized I think that looks better so here we'll actually make it 60 opacity and then when this entire anchor tag I'm saying button but it's actually an anchor tag right so buttons can be an actual button tag right so we actually have an actual button uh tank and HTML now and therefore also here in jsx but if the goal is to navigate to a different route it's better to use the anchor tag right so button is better to use if the goal is to interact with something on the page right so maybe it will open up a modal for example and an anchor attack is really meant for navigation now in this case we need to use the anchor attack because we need to download this UV and that's we can do that with uh the anchor tag not with button the button tag but it's still stylistically a button so group hover it should move down a little bit so Translate Y in this case and we'll also add transition to make that smooth okay so now if I save here we get an issue while doing an issue didn't make a typo okay let's see what we get why am I getting this issue so here for example I don't really know why we get an error so it's saying something with Section so it feels like uh feels like a typo somewhere just ah yeah so here we get the rest quickly so we are missing this anchor tank here right so now it should work again let me make this a little bit smaller again all right everything animating and very nicely all right and you can see this one also doesn't have the the cursor right so I actually can see it works now with the uh the icon as it moves down a little bit I think that looks pretty cool so we also want to get a different cursor right like here like a pointer so we can just add cursor pointer and then we have the pointer all right so when we click on this button you can see the URL changes which is what we want now when we click here we should actually download a CV file so the way to do that is pretty easy you need to add the CV uh you need to yeah well you need to put it somewhere so we're going to put it locally here it could also be an external link somewhere on the internet but here we're going to put it just here in the public folder and then we can just add the href here the href is going to be forward slash cv.pdf right so here you need to specify the location of that CV CV file now in next.js the you can access the public folder by just using forward slash initially so the the static files will automatically they will already look for it here in the public folder if you use forward slash but that's not enough we also need to specify the download property so here if we add downloads and we can make it explicit when I download is true or the way it works is you can actually do if it's a Boolean like true or false you can actually just specify it like this and it will automatically be inferred as true so now if we do this and now click here you can see we are downloading this uh file right so very easy for somebody that's you know a recruiter or maybe you know a team lead who's looking to add another person to their team very easy for them to just you know get all the information they need right contact me here maybe they want to contact you or they want to see your CV your resume uh very easy all right now here usually it looks a little bit better to add a little bit of a border as well so another design tip is if your background color doesn't deviate enough from the color that it's sitting on so here we have a blue Asia you know background color for the page and here we have a white background color for the button you can see it's a bit similar so to add a little bit more contrast between the button and the background of the page here we can add a very subtle border so here we can say border so until when you say border which is just going to be like a one pixel border by default and then we can set the color by saying border and then black which is actually the default but here we were specifying it because we want to reduce the opacity so you can just say forward slash 10 which will be 10 so now we have a very subtle uh border here around the the the button all right now we actually want the same for these other two buttons so let's actually copy these two uh these two classes and actually let's copy let's copy even more let's copy everything including this focus and hover uh classes so I'm just gonna paste all of that here and also for the GitHub icon and make sure you don't get any syntax issues like I got all right so now I'm saving here let's see what we get all right so now we also get a nice animation here for these ones or transition now you can see these buttons have are scaling a bit bigger so here we can make this a little bit bigger as well just to be more in line with the other buttons because these are smaller so this uh these numbers need to be a little bit bigger so until when they only have 110 and 120 they don't have 115 which is actually what we want so here we need to specify a custom value it will be 1.15 and we also want that for the folk for the hover States so let's see hover scale also 1.15 now when we hover these uh icons we also want to get a darker color for the text so we say in the hover state the text should become text engrave 950 instead of that 700 so let's see yeah it looks a bit better I think and we need to do the same for the other one so let's see change the focus and hover to 1.15 and then this hover class for the text color actually better to put it right after this one right so now we have nice hover effects and also nice Focus States and nice active States all right now these are going to be external links so let's actually make this work so the href this one is going to be and actually here we need to include the full URL gonna be linkedin.com and then we want to specify that it needs to open in a new tab so what we can say is Target underscore blank right so then we can copy this and paste that here for the other one and here it should be GitHub right so make sure if you want that at least that you actually put your own GitHub link here and your own LinkedIn link that's enough I click here it will actually open a new tab and go to Links in all right looks really good I think and we're really starting to uh come along here and fill allow this page really nicely alright let's continue with the section divider that's just this little bar here and I thought about maybe adding this bar between every other section as well but for now I decided to just add it here because I think it looks a bit better to have a bit more space after the intro but you can also decide to put it between every section right so sometimes you see this so we're going to create a separate component for that we're going to call that section divider dot TSX and here we can just use RFC and I will call that section divider this will actually just be an empty div and we will style that as follows so it's going to be a background color of gray 200 it's going to have margin on on vertical sides of 24 gonna have a h16 with one rounded full and initially it's actually going to be hidden and then from small and bigger it's going to be let's say block all right so if we save this let's see if we can spot it on the page no because we haven't added it to the page yet right so here we go back to our page now here we have the intro and now we want to add our section definer as well so if you just start typing here I get the suggestion press Tab and it automatically Imports it for me all right so now if I save let's see if we can see it and indeed we see it and actually it's already in the right position so as well as very easy now let's actually also animate this because we we want to animate everything that is initially visible so let's also do that here for the section divider because otherwise it's going to look a bit strange if this one is sort of static while everything around it is moving when we load the page so we're going to make this emotion.div I can not import it automatically let's see I get the suggestion from copilot here so let's see now we can use those properties again um let's see we have initial and we have animate now we actually don't want these default suggestions we don't want scale we want opacity zero and also it should fit 100 pixels lower initially and then here it's going to be opacity one and Y zero now we do want to add a d-lane right so remember we added some delay to the buttons here and now we're going to add even more delay to here so it sort of staggers um all the animations right so the lower here is going to start a little bit later so we can say transition duration well that's not what we want we want delay I'm going to say 0.125 okay so let's see what we get if we now oh yeah so now we get the issue we're using this motion component and that's using use effect so this needs to become a client component and now if we save and refresh and see what we get all right so now everything is nicely animating in to the page all right so let's continue with the about section so it's just going to have a heading of about me and then just two paragraphs now remember just like here we're gonna add some special styling to some parts of the text just to spice it up a little bit make it look a little bit more interesting so let's see we're going to create about about not DSX and I'm going to write RFC and I'll capitalize this okay so here we're going to use the section tag again and because everything in here is related to each other and now we're gonna have a heading so this is actually going to be in H2 and we will call this about me now since we're using an H2 here you start wondering why don't we have an H1 yet or do we already have that so we don't really have a heading here on the page that makes sense as an H1 we could technically make this an H1 but it's more of a paragraph it's not really a heading so you could opt for making this in H1 because it is it is the most important well piece of text I guess on the page so technically you could make it maybe we should make it an H1 now that I think about it also for search engine so that they can see some hierarchy in the text so maybe this should be in H1 that's uh let's actually make it an H1 but it's pretty close let's go to intro and here we are using we're using motion.p but we can just make that as an H1 motion.h1 so make sure that the uh the closing tag is also H1 and let's see if it changes anything no it doesn't change anything okay so now we have an H1 and now let's see we have this H2 about me and then we're gonna have two paragraphs and paragraph one and paragraph two now we're not going to write it out all by hand or maybe you can if you want but you can go to the GitHub repo you can go into components and then the about and you can just copy the uh the actual text there right so I'm just going to copy and paste that text here to bunch of text and also for the second paragraph I'm gonna copy that and paste this in here okay now we don't see anything on the page yet because we also need to add this right so every section we need to add that here to the page file so I'm going to press tab here automatically import it and now if I save we should see something yeah all right so let's start off by styling this uh H2 last name we're going to make this text 3XL Bond medium and that's it actually we want to capitalize it let's also do that okay then these paragraphs let's see class name they should this one should get margin on the bottom of three and actually that's all so just add some space between the paragraphs now let's also give this heading some margin on the bottom so it pushes away the content below it and let's actually make that margin bottom of 8. right so again this is just a bunch of text with some spans font medium to make the font weight a little bit heavier italic to make it look a little bit more interesting we have some underline here all right let's also style the overall section A little bit better because right now it's just spanning the entire width here a section margin on the bottom of 28 and then restrict the maximum the width to 45 Ram and will Center the text and will also looks good as a design to have another one is to increase the line height a little bit because now you can see it's quite close together the lines so until when it's called leading and we can increase it to eight so when you do that you can see there's more space between the lines I think that looks a little bit better and then we also want to have we want to change the margin on the bottom from small and upwards alright so that's for the next section so that our space between the sections alright now about this H2 heading when we look on the page you can see for each section that comes it will be the same so we have my projects my skills my experience it's going to be the same heading and it's also going to have that margin on the bottom to push away the content a little bit it's going to be the same for all of these sections except maybe the last one but we can add a prop to customize that so what we can do is we can extract this H2 into its own separate component right so let's actually call that a section heading and I'm gonna write lowercase here and so I'm using uh a babcase here I've seen some members of the next JS team do this and it seems like it seems a bit like a trend or it seems like a new standard so I'm just going to keep everything lowercase and with a dash or hyphen so let's see so let's say RFC and let's call that section heading so what this will do is it will be in H2 right and let's actually copy these classes so class name let's copy that and the text here it's not always isn't always going to be about me right so we want to be able to replace this now with Section heading so if we write section heading here and press tab you can see it Imports it automatically for me now here it's actually importing with and without the ad because this about section is also in the components folder and this one is sitting here so you can still import it like this as well right this is not wrong but you can also you know you can also be consistent and only use the add Alias but we'll keep it like this and so what we want to be able to do is just write our section heading here and in here we would like to have the actual text so here we want to be able to say about me for example now when you do that we're going to get an issue here so if we hover this so here it knows this is going to be the children right so in react if you have your own component and within the opening and closing to actually have something there that's going to be a prop that you're going to receive here that's called the children prop okay and if you hover that let's see so if we get two issues it's not it's not used so here we're not always hard coding about me so if I save here it's going to be about me but not because I wrote about me here because here later we should be able to use it for projects and so if I run projects here it's still going to show about me because it's always hard coding about me now now we want to use those children instead so here the children variable so here we can just output the children variable and now when you're gonna get this project right so whatever you write here now is going to be assigned to children so in this case it should be about me okay now and we're using typescript so if you have a component with props we need to type those props so what we can do you can write it in line here but it starts to look a bit messy because you have all these girly braces and it's especially if you're not familiar with typescript it looks very confusing so we can also write it somewhere else so we can just call that section heading props and you can just create a so-called type in jar in typescript so you can say type adding prompts and here we can say and it actually already suggests all of this for me because this is quite standard so what we're saying here is that the props of this component well it's only going to be the children prop and that's going to be of something called react react node the names like this you don't really have to remember if you're using copilot often it will suggest them for you but a lot of these things are quite standard so if you Google for this you'll see some of those typical types that you get from react all right now let's quickly animate this section as well this will be the last section that we're going to animate as part of the intro right because it's still visible if you load the page so let's see we're going to say motion dot section oops motion dot section and we need to import that so import motion and let's see we can say initial uh opacity shouldn't be zero but also to start 100 pixel pixels lower then the animation is opacity 1 and indeed y should be zero now this should have a delay NS even more than the previous one so when it starts the the last one so here we're gonna have transition but not duration but DeLay So 0.175 now if we save here and yeah we get this issue here it needs to be client components so use clients all right so now if I load the page you can see we have all of our animations uh you know animating in unload and I think it looks really cool really playful uh brush design and yeah I think I really like it really cool and I want to keep refreshing to see the animation but we'll have to move on at some points all right so let's take a look at the next uh section here so here we have the project section so it's pretty cool because as we scroll down and this becomes into this goes into view it sort of grows into the view here as I scroll down here all these projects one by one very nicely animate into the view and also when I scroll up again they disappear again I think that's a pretty nice effect right so the individual projects here they have a title a description some tags and an image right and as we hover the cards or projects they have a different background color and the image animates a little bit right and also um here we have three but if you have more you would see it better but what we're doing here is every every next card is on the different side so if if it's even right so this is card number two it's gonna be the text is going to be on the right side and the the alt the odd numbers will have the text on the left side all right so let's create a new component for the whole section projects dot TSX and we'll say RFC and we'll say projects and here we're going to use section again now here we can use that component that we just extracted so it is called section heading we can just use this and I actually already got a suggestion for me for import and then actually also for what we actually want this and actually it should be my projects and technically you know we're capitalizing it here in the jsx but typically if you want to be strict that's a stylistic thing and you should do it with CSS so let's be a bit strict with ourselves here all right and let's actually add this to the page so let's go to page and Below about we're gonna have projects okay so I can put the cursor here and control spacebar and I get this suggestion to import it it's right here okay let's see if we see something now yeah so now we see this heading all right so then we're gonna have those three projects so let's wrap that in a div and let's see where we can get the data from so we actually already copied that from the GitHub repo into our data file here so we already use this for the nav bar the link so I'm going to collapse this hair and we also have items for the experience section but now we're going to use this project data that's also a list so we have an array in JavaScript and then each project is going to be represented by an object right so we have a title a description tags is an array again and then we have an image URL now this is actually coming from an import so here let's see we are you can actually import images right so we have put those images here in the public folder right so if you haven't done that yet you can go to the GitHub repo and just download them and then just put them here and right so I can just open this up it's this image and you can import that looks a bit strange you can import an image like this and what you get is basically a reference to that image and that's what I put here as image URL right so we have three projects here you can add as many as you want now here I'm using ask const again so let's quickly remove this to see why we do that so if I do this and now I hover project data you can see is in you can see it in first types right so we're not specifying the types ourselves it's just inferring it so here it's saying it's an array of these with these objects right so it's going to have a title of any string description of any string tags is going to be an array of strings and then an image URL well that's just because we're importing it's something called Static image data right so this is fine this is not the end of the world but we can be a little bit more specific we can say it's not going to be any string for title it's only going to be these strings and so if we just leave it like so if we don't use S columns let's actually leave it like this here now we're going to Loop over this right so we're going to use projects data so project data you can see I got a suggestion here to import it dot map and so now if I hover this project here you can see it's telling me it's going to be a project it's not going to be is this is going to be an object it's going to be any string any string right it could be any string but we can be a little bit more specific because we know that this is not going to be any strain this is actually just going to be the actual data that we're going to use right so in the real world you know this data would maybe come from a back end and then you can actually leave this off because then you don't know what it's going to be but here we're hardcoding all of these days now so we know that this is this is going to be it so I will actually leave as const and now when you hover this project you can see it it actually tells us what the exact string is going to be and it's not not that useful in our case here but technically it's a bit more strict and it's a little bit safer all right so here we want to create it we want to go over all the projects and just have one uh sort of card for each project so let's see so I'll use parentheses here so we don't have to write the return keyword so what we actually want to do is we want to have a separate component or an individual project right so below here we're going to get an issue now but let's create another component here that will say function project and it actually gives me the suggestion but that's actually uh let's actually just return an empty deal for now just so we got rid of the issues here so if we do this we get an issue so I need to provide the closing parenthesis here all right so now we get an issue because it wants the it wants us to add the key prop right so here uh we're mapping so we need to add a key now if the projects had had an ID or something I would use the ID here they don't really have something I mean technically the title is you know most likely going to be unique so we could use the project title or just use index the key doesn't really matter if the key starts to matter once you start shuffling around a list right so if you start if you if you add the ability for the user to sort a list or to remove items from the list when you add those types of features you want to make sure that the key is actually unique right so in our case here it's not really an issue because it's just going to be a static list right so it's not really an issue now here we're adding it on our custom component this key right but now we need to accept the key we don't want that we don't it's just well for this map here we don't really want to accept the key as a prop on our custom component so this is actually a good use case for a react fragment so if you know this you probably notice a react fragments it's just a lot it's just an empty element essentially just sometimes you need to return one element and you don't want to clutter up the markup with an empty with just another div so you can use this reacts fragments so here we can then here we want to put on the key right but you can't you can write key or something on this so here you actually have to write out react dot fragment and then on here you can provide the actual key right so just say index okay now this project what should it receive then well it should receive all of that data right so you should get data description title description so that's this this object project we want to pass that to this component so how do we do that well in jsx you can just use curly braces and then just spread it like this so it will take those objects properties and values and now we can access that here as props now it's complaining this is a typescript complaining because here we haven't specified the props that H that it can receive but let's uh do that now so here we're going to say this this project X component is going to receive a title right we have description tags image URL description tags and image URL I'm using uppercase and then two lowercase for URL so not all uppercase just URL okay and let's see let's just output the title here so just so we can see something so I'm going to put output the title here and here indeed we can see three projects these projects are from from my JavaScript course by the way I really think it's beneficial as a react developer or next year as developer that you have mastered the underlying fundamentals Things become very easy including typescript for example typescript also becomes very easy Once you have mastered JavaScript alright so here now we have the props but we haven't typed these props yet right so here we could do that here right so here we can have a colon curly braces and we can go one by one title string description string or it looks a bit cleaner to extract this into its own uh separate type here so we say projects props I like to use the name of the component and then props and we can add it at the top of file or just right here where we're gonna use it so we can just say type project props now what we could do is we can go one by one title is going to be a string we can be more precise than this right so description could be a string but again just like we saw here where we use as const which helped us when we then Loop over that because now it knows that this individual project is going to be very you know it's more specific we can also be more specific here right so this project component is not just going to receive any string as a title right because we know we know the exact strings that it's going to receive so instead of going one by one like this what you can actually do in typescript is you can actually just say type off and here we are importing this so This Project's data we are importing this and we can say this this these props are going to be a type of let's say project data and let's say it's the it's the the first projects if I save here prettier at these parentheses for me but I don't think that's necessary so here it's gonna we're basically saying this these project props so what we're going to receive as inputs to this project component are gonna be very specific this type so with this specific title this specific description so now if I hover project props you can see it's going to be title descriptions it's going to be the exact same as here right now that's not entirely true because that's true for the first one right that's true for the first object that's looping out that's mapping over but the second one is going to have a title of remote depth for example right so then it's gonna get this one and actually you you can actually just write a number here in typescript which means it could be any number of these right but specifically these objects and so now when you hover it okay you see you see the same but or you see something similar but now it's not just a specific one of those objects but it could be any of them right and this is pretty cool this is you know this is about as specific as we can get okay so let's uh start adding this project properly but which tag should we use for something like this okay so the the tank that we should use in HTML for something like this is probably going to be either section or article because everything in here is related to each other so it's not going to be just a div there's more semantic meaning than just a div so it's it's going to be a section at least and there's also the article tag in http so we also have article an article is basically the same as section but it has one more condition which is basically we should be able to take this out of this page here out of this website and put it somewhere else and should still make sense so if I put if I pull this out of this project here and I put it for example on another website that actually the other website could be about something else does this still make sense like is this still self-contained is this still if you see this is still clear what this means and you could make the arguments I think it's pretty close so you could make this an article tag I still think it's a it's going to be a bit too unclear what this exactly is I still think you need the surrounding context here to properly interpret this card here but you could use the article tanker you could definitely make that argument however I'll stick to section alright so indeed we do want an H3 so thank you uh copilus I'll just accept the suggestion here so we have the title then we have that description actually already gives it for me as well and then we have those tags right so let's see those tags is actually an array so we need to Loop over the array and actually uh that's going to be a list right so here we have a list and you can see copilot is really smart so indeed we want to map over those tags and each tag should give us indeed An Li right I could write this out as part of the tutorial but to be honest like in the real world I wouldn't write it out I would actually just accept you know whatever the suggestion is press Tab and move on so let's I want to give you the a more realistic view into how it works in the real world so I'm just gonna accept copilot suggestions even in a tutorial if it makes sense okay so if I save here let's actually see what we get okay so at least uh doesn't look good but at least the data is correct and then we also want to add the image so we're going to use next.js image components so there's a second suggestion here press tab it automatically Imports it for me now here copilot actually makes a very tricky uh problem for us so if you don't know much about the image component you're going to accept this but actually since we are using local images here we don't need to provide the height and width ourselves and actually it's better if next to S does that because it can it can more it can optimize things a little bit better than if we start hardcoding things here so it can actually just look at this image file see what the height and width should be or depending on how we style it and it's going to be a bit better that way okay so we have source and ALT now we can provide some other things because next.js will try to optimize this image by reducing the quality a little bit so we can actually fine tune that so we can add a quality of let's say 95 or 90 I think 95 looks fine 90 is also fine so alt um alt add to title could be title or description even or more generic uh let's say let's call this project I worked on Project I worked on all right so if I say fair let's see what we get and now we get these images we need to properly uh size them style them all right so let's do that now let's let's this overall project card let's start there so let's see let's give this a background of gray 100 and we should restrain its width right shouldn't be all the all the width it should be at most let's say 42 RAM and we're gonna add a border gonna be a black border with five percent opacity we're gonna say overflow hidden because we're going to hide part of the image that overflows it so we can position it more in like on the side and we'll add uh padding on the right but only on wider viewports those small and up alright the title let's see the title here should get text to XL so much bigger and it should be semi bolts all right and then the description should get margin on top leading relaxed so instead of hard coding like uh some specific line height the two wins also has more of as some of these words like relaxed means a little bit more line height but not too much text Gray 700 we want to de-emphasize the description a little bit compared to the title all right and then let's quickly style these tags so each individual tag should get the following a background of black but with 0.7 opacity some padding horizontally and a vertically should be quite small should be up guys and we're gonna set tracking wider which is letter spacing so spacing between the letters not line height but between the letters and the texture should be white and then we also want to make it a pill shape I will say rounded full and actually when we do that we don't see it so there's something going on with the background color and that's because we cannot write it like this so we need to wrap the 0.7 in square brackets okay so now they're stretching all the way so there if you want now we can use flexbox to properly uh create a layout for them so with flexbox you always want to identify the parent element instead of these allies are going to have this UL as parent elements so we're going to say Flex to make this the flex container and we will allow them to wrap let's also adds some margin on the top I will also add some gap between them and actually let's see what we get if we do this okay so then we have this so this card right now is uh not the proper layout right so what we actually want is this image should sit on the right side and all the text here you should set on the left side so that's a layout problem so we can use Black Box again right so whenever you have a layout issue most of the time you want to use flexbox sometimes you want to use CSS grids we'll talk about that in the CSS course as well but it's going to be like 90 of the time flexbox alright so what we want to do is uh this image should simply sit in the corner and right now it's stretching this card all the way because it's taking up space so what we can do is we can use position absolute so if you make it absolute it's taken out of the normal flow meaning it doesn't take up any space and so if I just do absolutes you can see this cards yeah so this card now collapses and the other cards are right below so the images are all positioned absolute now so they're all going to be uh like this now position absolute you usually you want to specify relative to what so if we go here to this section we're going to make this relative so that these images are going to be relative to their section right that's their cards I'm calling it a card because this type of design is often called a card okay but now it's not visible and at all because they're Precision outside the project now and we have overflow hidden so what we're going to say is you said we will say top 8 and negative rights 40. all right so then they're sitting um in a corner okay let's actually keep the image like this and let's actually work on the other side now so this other side is all of this so let's actually wrap that in a div to make the styling a bit easier so we have an image and then the other div so we just have two parts all right let's give this some styling let's py4 px5 and let's actually see what that gives us all right that looks better and actually we want some break points here but we'll say PL 10 and PR2 and also betting top 10. okay let's go back to the images because they're a little bit too big we can actually just set a width and it's going to be 28.25 Ram why these very specific numbers by the way well that's just because I played around with the sizes a little bit and usually I use pixels while I'll test things out and then once I find a nice nice design I just convert that to Ram right so sometimes you get these ugly numbers but it is what it is if you want something uh perfect or very specific all right we'll also make the well let's actually see what we get if we just make the size smaller all right so that already looks better we're also going to make one of the corners around it so we'll say around the top and actually both on the top both ones we're also going to add a shadow also Shadow to excel all right and now this left part is too wide so now let's go back to this div which holds the left side so we need to say on smaller and bigger we need to restrain the width so we can set a maximum width of 50 I think you can also write one and a half until when all right so when we do that you can see now it really starts to come together and we actually uh we should actually just set a height on this overall section so we can say on uh normal viewport right smaller and bigger we'll just set a height of 20 Ram alright so now we want to have these tags sit at the bottom of their card right so this is also the sticky footer problem if you've ever had like a footer at the bottom of your page but it doesn't go all the way to the bottom but this is very similar so what you can do um let's see so this div holds the title description and then these tags so what you can do is use flexbox actually right it's a layout problem so the parent element here is flexbox so we can make this a flex container and a default layout is horizontal so it's going to be all wrong now but you can make it a flex column so Flex call and now all these items these all these elements are now Flex items and one of the things you can do now is on this list you can say margin Top Auto and so margin is not specific to flexbox but it has some special behavior in flexbox which is if you have Auto it will put as much margin on top here as possible which will push itself down now this only needs to be on small and bigger so if I save here and let's see okay this only works if this div is also um all the stress there's also this only works if the if the this div is also tall enough so that it actually has a space here right so we had to set a height on the section here but now we need to make sure that this div in there also needs to be that also has the same height so we can just say h pull so if you do that it will stretch all the way and then we have this list which will have all the margin on the top which will push itself down here now that I look at it I think it's actually sitting a bit too close to the bottom here so we have pyf4 well let's keep that at the top so pt4 but I think at the bottom it should it should be a little bit more so let's let's try six okay that pushes it up a little bit I think we can still push it up a little bit more so pb8 yeah I think that looks a little bit better so we'll keep it at pb8 petting bottom okay so now these these project cars they're sitting right against each other so let's see here in this section what we can actually do is we can give each one some margin on the bottom and actually that's for mobile so then for wider viewports we're gonna add margin bottom of eight so you can see it as some margin now when you do it like this it also adds the margin to the last one so now we're also going to have some random margin here but we don't want that for the last one so what you can also do in Tailwind as you can say last and then just say mb0 right we don't see it here but that could cause some issues later if you have more content here it could give some issues and actually let's uh let's reduce that space actually a little bit more so we have the tags here and I changed my mind I want to have it so instead of pbas I think pb7 is perfect let's see yeah I think that's perfect so uh let's make it pb7 I'm fine I'm quite uh I like to be precise with my styling all right now what we want is this second card and actually every even card so number two and if we had a four and six here we only have number two but this should be flipped right so what we want is that this image will sit on the left side if it's if it's an even number so project here let's see till when it actually gives us um some other uh pseudo classes so it also gives us this even pseudo class so we can say even then we have we have right right now we have right negative right 40 so we need to uh reset that so we'll just set that to initial now we can say right and then initial and then we can say even and then it should be negative left 40. so if we do this let's see what we get okay so what happens is this image is always the second child here right so this image is always a second chance here well second is even so now all of them will always have this so here we don't mean the image itself it should be this section element that should be even right so here we can actually just use group again so we can just add group group and then where we have even right now we can make this group even right and this should be group even right so now if I refresh here or save and now you can see the images are positioned correctly now we also need to make sure that the text here when it's even should actually go all the way here so we'll just add a lot of padding to the left in that case so here we will just add this padding to this div that holds everything so here we can say group when it's even we should add a lot of margin actually margin on the left of 18 Ram so if we do margin left 18 Ram it pushes all the way to the to the other side and actually that's not enough it should be 26. okay now it's still sitting a bit too close to the image I think so we can actually add some more padding or more margin so for this section here if it's an even section right we don't have to use a group because this is actually the outermost elements here so even in that case we want to add padding on the left of eight resonance push even more and I think yeah this looks uh correct right so I think this looks really cool now obviously the heading is not the centers so let's see we can actually just go to that component section heading and we can just say text Center because it should always be centered in our project here that's not centered all right let's also add a simple hover effect to this project so here they have a background color but we can also say when we hover it the BG gray should become 200 and that should be smooth so we're going to add transition all right so now if we hover this we can get a simple over effect with the background now it looks kind of cool I think if we also move this image when we hover this card so let's see we can say when the group hovers that's another when we actually hover the image itself but the overall card so we can use group again and I will say group hover or we're just going to move it a little bit so we're going to move it to the left here so translate X3 and then we're also gonna move it vertically now we're gonna say translate Y3 and we're also going to rotate it a little bit so group hover and it will actually rotate the other way so I'll use a negative one that should be smooth so let's also add transition I'm just adding transition and saving let's see what we get all right that looks kind of cool now it's it should be cooler if we if we also make it bigger so it sort of scales up so let's also do that group hover scale 105 it gives me as a suggestion and actually I was a little bit more pickier than that so I made it 1 1.04 so now you can see we have pretty cool effects now here on the second one it it sort of moves away from us so here it should be the opposite right so uneven it should be the opposite right so to make it work the other way around for this one uh let's see so scale should be the same but translate X as y let me actually undo this translate X and Y and also rotate should be different so let's just copy these three and I'm gonna paste that below here and I'll add some space and now we're going to do it the opposite way so remove the minuses and add the minus to and actually now we'll leave that for that for that one right so there should basically be no minuses and then we are saying group hover Bliss for all of them right we only want to do this these ones for the even ones so we can actually combine this so we can say for the projects that are even right we can just add group even to them so now let's see if that works and now you can see this one is the opposite of the other ones right that's a pretty sophisticated stuff here with that till when CSS it's very powerful and very easy to pick up once you've mastered CSS itself alright so now let's take a look at what else we need to do with the projects here so what we want is this scroll animation which looks really slick and so what happens is as we approach this section and we scroll down they sort of grow into the view here right so both their opacity as well as their scale is animated based on scrolling and we can also very easily do this with framer motion so what we can do I'm going to make this a little bit wider we need to go to the project individual project components not the whole section and here we're going to use framer motion so frame of motion has a hook called use scroll that we can use and let's actually import that let's see if we get the suggestion here control spacebar no so I will import it manually here and actually copilot also doesn't know where it should come from well we'll say import scroll from framer motion okay okay now we need to give this hook two inputs actually just one options object but with two uh properties so it needs to know the target element and it needs to have the uh the actual HTML reference so we're gonna have we're gonna have to use use ref as well I'll just leave this as a string for now and then also an offset property so this offsets is going to be an array what that means is when when we actually want to start animating right so we're gonna have a Target so the the individual project is going to be a so-called Target and then we also have a container and that's actually the viewport right so the viewport is whatever you see here of the of the page and so what you have to specify here is at what point do you want to basically start the animation so here we want to start as soon as the end of the container end of the viewport reaches the top of the Target right so that's what we can specify here so here we can say uh in a string zero and then one so that means when the bottom of the viewport crosses the top of the target which is the project that's when that's when the animation should start and when should it end well it should end when the the bottom of the viewport has has has gone 33 beyond the end of the project that's what we can specify like this takes a bit to wrap your mind around this you don't really have to understand this you can always look up the documentation but that's how this offset property works okay so then we need to provide a ref here to the actual project here this section element that actually should be animated so here we're going to use the use ref hook right so here actually a polar copilot already suggests this for me we're gonna say is use ref and typically we'll start off with a value of null and let's actually import this I'm going to place my cursor here and actually we get used ref Snippets but that's something else it's from an extension so I will import it manually here use ref okay so now we um we get some issues here if we look here so this should be a client component and now it gets interesting because if we look at the overall projects section this is not really doing anything interactive this is basically just presentational markup here it's only the individual project here that now we start to use these Hooks and we really need to at least have this as a client component now what what will happen is if I make this use clients here both of these components will now be client components so even though actually technically only this project one has to be a client component and then ideally we can we can keep everything or as much as possible running on a server only right so a server component so here what we can do is instead of using use client here at the top in which case if we do that this will also become a client component which is not necessary because this is not really doing anything interactive it's just mapping over data and then using the project components in which actually does need to be a client component because here we need interactivity we need a client-side functionalities here so I propose that we actually put this in its own file so we're going to create a new file here simply called project singular and then we can just copy this right so let's just copy the entire component into that new file so and actually also the type above it right so make sure you also copy the type or the props and I'm going to paste that right here and we get a bunch of Errors because uh we need to import the proper things here so let's see if I put the the cursor here Ctrl spacebar command spacebar you should be able to import everything automatically actually because now it's already imported here so it should be able to deduce from that actually use refer is not importing for me so I'm gonna type it myself actually we got some suggestions but I won't use ref okay you scroll I'm going to put my cursor here also we have to actually we can also just copy as here um actually we need everything except the the top three all right so we can remove this okay so now we have all the necessary Imports now remember this needs to become a client component right so the only thing we have to do is say use clients and now this is a client component um but we need to export this I'm going to make this the default export here so we're going to say export default okay so we're we're making just a default export and we can import it here and we can also remove we can also remove these Imports because we're not using that here anymore also they use ref and then we need to import the actual project and that should be easy right we can just import it automatically like that and it's a it's a default export so we don't need to use the code braces all right so now if we save here and see if that works or at least if we can get rid of the error Okay so the loading and looks like it's working right so it's still working here and so now it's a small optimization of course but if we look on the page everything in the app directory is a server component by default so here we're importing projects projects itself does not have used client so this will now also be a server component but this is importing a client component and we're using that here right and the client component will have the actual you know functionalities and client-side features right so the way to think about it is basically anything that is presentational is going to be a server component as this is more presentational just mapping over some data we have some Divine section and a heading it's quite static now then we have this component which is more interactive right so the interactive components are going to be client components usually right and you want to put you want to use as many server you want to keep components server components if you can sometimes that means refactoring the client components to a new file and so if you look at if you imagine a react three so three of components you want to keep the client components more towards the the edges of the tree right so really at the leaves of the tree now sometimes that requires some refactoring all right so let's continue here in the project component now so it needs to know the targets right so that's why we created this ref now about the type of this graph and let's actually just add the ref so we can just go here and you can say ref is ref okay now if we hover this you can see it's trying to infer a particular type of this reference but it's not it's not really showing us that it's actually going to be this section right so here we can we can supply the type ourselves so we can use these angled brackets and we can specify this is going to be an HTML section element okay and actually that doesn't seem to be familiar to typescript so cannot find name HTML section elements okay so it looks like there is no special HTML section element type we should use the more General HTML element type so some of these HTML elements they have their own types like HTML div exist but not HTML section so they only create new types if the type needs some special behavior or special property so the section element didn't need special type typing properties so there's no special type for that but for some elements like this there actually are because they need some special stuff for some reason okay so I just Googled that actually I don't know that by the top of my head sometimes you need to Google it okay so now we can see that this ref is going to be ref objects and it knows more specific now that's gonna be it's going to be an HTML element okay so this that's going to be the Target right so we have the targets here we can just provide the ref not the ref current we actually need to provide the whole ref all right so that's what we need to provide to this use a scroll hook now what do we get back from that hook what we get back is the pro scroll y progress so scroll why programs is what we get back so basically an indicator of How Far We've scrolled and that's what we can now use to animate this so we do have to make this a motion component so I'm going to make this a motion dot section component let's make sure that the closing tag is also correct yeah we need to import that let's see if it finally Works nope so we have to import this manually motion okay and then the trick is almost finished here we can use the style prop so just like CSS styling and we can just do scale for example as well as opacity let's see if no opacity should also be confirm the progress of the scrolling that's a bit of setup here but now the scale and the opacity CSS values will depend on how far we've scrolling at least that's the theory let's double check if it actually works you can already see that it seems to work right now you can see it's not so smooth but at least we're on the right track here now it's not very smooth and I actually didn't know why it's not smooth sometimes it happens with frame or motion that things don't work as smoothly as as you think they should so what I tried here is to just wrap everything in a div here and just animate that div so let's actually do that so we'll keep the section it's just going to be normal section element and we're just going to wrap everything in a div we're going to put everything in a div and that's the idea that we're actually going to animate and that usually solves the issue if it's not smooth in frame or motion for me so here we need to copy the ref and the style to that div now and now is uh let's see yeah so now it's not just a general HTML element now we can change the type to HTML diff element right so make sure you change that now because we change this we also need to change this margin on the bottom right so now uh let's quickly change that as well so class name so here we added some margin on the bottom yeah so margin bottom three SM mb8 and thus last pseudo class that should now go to this div and then actually uh there's some space between them and then let's see what's going on here why is this not working uh yeah so here it doesn't work because this is still a normal jsx div element but we want to make it a motion component so we'll say motion dot div make sure that the last closing attack is also motion and now if we save here let's double check so now you can see it's very smooth right really buttery smooth for me I hope it comes across the video as well because I'm recording video here so I'm not sure if it's as smooth on the video but from my perspective here it looks very smooth now the only thing I don't like is it's a bit too much so so what I mean by that is the scaling basically starts from a very low number like zero and maybe it's a bit too much so maybe it should start already a little bit bigger so it's a bit more subtle and the same with opacity it starts off almost invisible and immediately goes to like completely one opacity so that's a very large range that it's animating basically and it's it's not really it's not as subtle as I like the animations to be so we can this scroll why progress that we get is actually a special motion value and we can change that a little bit so that the scale and opacity here that are using that are animated a little bit more subtly and actually what we also want sometimes is that the scale is is animated slightly different from the opacity right so that's we can do that immediately here as well like this so what we're going to do is there's another hook that Premier motion gives us is use transform so we can transform that scale y progress that we get from you scroll and actually I already got a suggestion here so you put in the scroll why programs right so that's what we need to provide and then there's two other values so this skill the scroll why programs will go from zero to one unless that's what we're putting here and then what we actually want the transformation to be is that for the scaling here that it doesn't start at absolute zero right so it it doesn't start from an actual scale of zero but maybe let's say 0.5 and goes to one right so what this will give us let's we'll use that for the scale so we can just scale progress and we need to import this no suggestions use transform from framework motion make sure you import that and then we can use this value the the transformed value for scale so if we do that let's see if that works so now you can see that it doesn't start off so small it starts off a little bit bigger and it's a little bit smoother I think more subtle nothing it doesn't it doesn't travel such a large range during the animation now it's the same story with the opacity I don't want it to start at such a low value so we're also going to transform the opacity so let's duplicate this line I'm going to put my cursor on this line and then hold shift alt down arrow key to duplicate it and we can say opacity progress right now maybe we can even change it here we'll make this 0.6 so this should start not at zero but at let's say 0.6 and actually let's change the scale because it's still a little bit much let's actually change this to 0.8 oh well now actually we should still change this value so opacity should get opacity programs right so I change the value for scale as well to 0.8 so now it's going to start off you know significantly bigger but I think it's going to be more subtle yeah this looks better right so now it's ways to learn right so you can play around with use transform to transform that scroll y progress value that we get which is just basically a raw indicator of how much we've scrolled in you sometimes want to transform that right it's a bit more advanced but uh I think we have a nice result right so really uh slick I think yeah I really like this effect I'm going to use it much more in my design now that I've learned this so uh I hope you like it as well and there's one issue here now which is that this we've lost that even odd difference right because we now added this diff here so this one is now sitting on the right side image so that we should we should uh change that so we just have to change this group to the to this div here so then that will be the reference point basically and then also this even pseudo class so even we can add that here as well so if it's even it's going to add some additional padding on the left and actually that doesn't work so now it's adding the padding actually to the to the left like this so we actually want to keep the padding here in this section so what we're going to do is here we can use the group so here I'll say group even and then add oops so then add the padding on the left right so a bit of shuffling around with the Styles here let's see that actually works and actually that doesn't work yeah it actually works yeah so you have to wait a little bit before the uh the dev server has caught up but now we have this uh even out uh difference again okay now I just noticed that these cards are quite pointy so I think we didn't ask the Border radius so let's do that let's make this rounded LG and let's see if that works yeah so now it's a bit more rounded all right so that basically concludes the projects section well done for making it this far we already looked at quite a few Advanced topics frame emotions on typescript stuff uh some CSS positioning stuff flexbox so don't give up now let's go it's coming along very nicely now all right so now let's actually continue with the header here and let's actually implement the complete functionality here so if I click on about we actually want to go to the about section if I click on projects we should actually go to the project section and I'm actually not sure yeah so if we click on home we should go here right for some reason if I click on about it already Scrolls down here I'm not sure why but that's of course should also be much smoother so you can see when we click on it the URL already changes so that's already taken care of now the only thing we have to do is go to these individual sections and just to add an ID right so here on the on the outermost component so for here for about we can just add an ID of about and then when I do that and now try this out yeah so now when I click here I immediately go to this about section now that's not very nice because it's sitting right at the top of the viewport and we have this header here awkwardly overlapping now so um ideally it would basically put us something like right here or something like this so a little bit lower and there's actually a special property for this this is pretty Advanced but um when we click on about we just want to add some basically some some extra space here so the property that we can use or the in in in until winter at least is called scroll margin so we can say scroll margin top so if we do that and we'll make the number 28's so now when I click on about yeah so let's I had to refresh here now when I click on about you can see it's a bit there's more space here between the top of the section and the top of the viewport which looks much better so that's what we want to add to these other sections as well now so now when we click on projects we want to go to projects so let's go to the projects section here and here we'll add an ID of projects without the hash right so let's see if that works projects about projects let's see if I refresh click on projects yeah and now I'm immediately scroll to this project section here also right at the top so here we can also add that class name not an ID class name scroll margin top 28 okay so now if I click on about it's it puts me right here when I click on projects it actually still puts me too high here so let's see let's double check if uh if I refresh here let's see if that works now so I click on projects and yeah and now it positions it properly right for both sections all right let's also do the intro or the or the home page we'll make the intro section here home so we'll just add an ID without hash of home all right let's see okay so now when I click on about and then home it puts me it puts the home right at the top of the viewport as well now here that 28 is not going to be enough so here we actually just want to scroll all the way to the top right not just not just something like this we actually do want to get all the way to the top so here we can actually just use a larger number scroll empty and just use 100 just a very large one so it Scrolls all the way to the top all right so now if I click around I have to refresh so now if I click around about home and that's actually too not not high enough yeah so actually and actually it should be a custom value here so just 100 Ram very large number just so it's always scrolling to the top all right so now if we click around about home yeah so home now takes us all the way to the top right all right and this is not very smooth obviously right so all of this is instantly so how can we make it smooth well we can actually go to the root here the root file and we can determine for the whole page that edge should be a smooth scroll and we can we can actually just add that here on the HTML element so we can actually just say scroll smooth now there is some uh default behavior from tailwind and there could be other issues with this as well it make conflicts with other settings so here I'm gonna add an exclamation mark which will make this which will add the important role in CSS so um this with this one will always be applied essentially and when you do that it should be smooth yeah so now you can see when we scroll it's a very smooth scroll right really nice and we'll do this for the other sections as well as we get to them right projects still nicely animating in really cool and yeah you can see it's really starting to come together right now of course we also want if we look at the example and let me actually zoom in a little bit we have this we have the active section indicator so if we are in the about section it's actually indicated like that here and when we go to projects oops when we go to projects it's actually animated right so you can see that the background thingy very nicely goes to the other audio other one and to make that work of course we need to know the active section right so as I scroll down it should also change so as I scroll into the the another section the about section here and if I if I scroll through skills I'm zoomed in so it doesn't work for projects here but if I go to skills here and then experience it should automatically move as well right so it should detect that so we basically want to keep track of the active section that we are in okay so we want to keep track of the active section and let's actually start simple let's just start off by making the home the default one right because as we load the page obviously the home is going to be well the most in the view here so let's make that the default so let's see how can we keep track of the active section well here we're going to use state so let me reposition a little bit here all right so we want to keep track of the of the active section and I think let's start it off easy it makes more sense to make the home section the default one right so we we need to keep track of something and when you want to keep track of something in your application you're going to use state so let's see where should we put them what makes the most most sense to start here in the header itself so here in the header we will simply use States right and we're going to make the default home right so we're going to use the same names as what we have in the data here and so here for the links we use name home name about so with uppercase so we're gonna we're gonna try to use the same names okay so use state will give us two things it will give us the active section and then a Setter function right set active section and don't forget the equal sign all right so we need to import use that from react okay so now the default is going to be home right so let's just style this a little bit so what we want to do when it's active is we want to make the the color actually the same color as when we hover it so let's see if we go to these links here here we can set the color but this is for all of the links so here we want to we we basically want to add the class text Gray 950 but if we do it like this all of them are gonna have that darker color now but we only want this for the active uh section so we don't we don't just want to add it here we want to add the stillwind class conditionally and this is quite common that you want to add some Styles conditionally right so only if some variable some State um is true or false you want to add some special classes this is very common all right so there is a very popular package for Tailwind here that is called clsx and this helps us with conditionally applying uh class names right so this is what we're going to use then for that so let's quickly install that I'm going to open a new terminal and I will npm install clsx okay then I can close this terminal again and I'm gonna import that here at the top import CLS SX from clsx and let me actually make this a little bit less y like this okay so now we are importing this so now we can use this in here so here we're gonna say class name for link we're going to wrap this in curly braces so that now we can use JavaScript features in here because what we want to do is we want to use clsx as a function and it receives this input right so let's wrap this in parentheses right so now we still have the same string but we're going to pass that as an input to the clsx function so we have this this is what we want to apply always so without condition but now the cool thing is you can have comma and then an object and here we can apply something when when you know active section is true and here it actually co-pilot already suggests this for us I'm just going to accept this and it's basically saying we want to apply this string and we can have multiple classes in here in this case only one when this condition is true so if the active section is the same as the link.name right because we're mapping of these things so if active section is home and link.name is home for example we're going to apply this right so let's see if this works so if we now save and you can see you can see now that home is actually a darker color now right so make sure you have all these curly braces and parentheses correct but if we change this from home to let's say project right so if I save here you can see the project is now the darker color right so now at least for the color we are doing all right and now we also want to display like a background thingy background color for the active section so let's actually do that here in link we'll just use an empty span for that so I'm just going to span and let's see we'll give that a background color of BG grade 200 and actually it should be 100 it should be rounded full and it should be below the text so here we need to do some absolute positioning now when you use absolute positioning usually you also want to Mark the element that should be the relative the reference point so we're going to make this motion.li relative okay and let's see we have absolute and then usually you can say top zero right zero or you can set it for all of them we can say inset zero which will which will do zero for everything so top zero right zero should set zero from the from the bottom Zero from the left so basically it will stretch all the way and then it should sit below the attack so we can also use the Z index and a negative number I'll just say negative Z10 let's see what we get all right so now they all have a slight subtle grayish blob in the background right but it of course this should only be applied to span here if if if it's the active section so here we're mapping over these links right so link has name so we can just check if links if the link.name right so we can say link.name is that the is that strictly equal to the active section right if that if this is true then render the span all right make sure you get the parentheses here and so now when we look again you can see it's only the home link that has that blob in the background Okay cool so the home page is the active section by default but now how do we change that so if I click on about for example it's still the home page that's active so now let's start off by changing the active section if we just click on this so if I click on about obviously the about section should become active alright so when I click on about for example it should be if you become the about section that becomes active and so on click you can already hear it it's going to be an on click Handler now we could add it to the LI or to the link but when we click the link that's when we will actually scroll so it makes more sense to add it here so it's going to be on click and here we can just provide a function and actually it already suggested for me um so we're going to say set active section to whatever link.name right so we're mapping over these links they have a name about projects so when there's a click that's what we're gonna set it to so if I click on about it's going to be about actually I can hover this and touchgrid will tell me what this is right because right because we are mapping over these links and we have specified this as const right so link.name can ever can only be any of these names here not any string but only specifically those strings right by the way we're writing it in line here right so we're doing this here we could also extract this into you know a separate function and then Define that up here but if you only do one thing or maybe two statements I think I prefer to do to do it inline and if you do multiple statements multiple things I think it's better to extract it into its own separate function right but here we're only doing one thing no I think it makes more sense to just inline it here all right so let's check this out so I'm going to save here and now when I click on about you can see it's the about that becomes active and then projects skills we don't have skill section yet I don't know why it Scrolls up but this is what we have now right so it works and it looks alright but it's not very smooth right so now we're going to take it to the next level more advanced level is when I click on about this gray blob thingy should animate to that very smoothly it shouldn't just instantly go there so it's very easy to do actually with frame or motion so here we have the span as the blob thingy and we're going to make this a motion.span so motion.span make sure you also get the ending closing tag correct and then we only have to specify two things so we're gonna give it the layout ID and actually already suggested for me the layout ID is necessary here and then we can just specify how we want that transition to go so the type should be a spring animation it's going to be that bouncy animation and then we can customize it a little bit so stiffness should actually be 380 and damping should be 30 right so you can basically customize how bouncy it should be so let's actually try this and then I'll explain how that works how frame motion is able to do that so here let's Now set the active section to about and you can see it animates to the other nav item now right it's not instant anymore and you can even see there's a little bouncy effect in there how cool is that that's why I think this looks really cool and you can see it wasn't even that difficult to implement right so you can see how powerful framer motion is and the waveframe emotion is able to do this by the way is because um here we're mapping over these links um what's hap what's going to happen is when I click on about here this span for the home is going to be removed because home is not the active section anymore so this will be removed and the about the span and the about here will be will get into view because now about is the active section and frame in motion can pick up on that that one that one of those spans gets removed and the other one goes into view because they all have the same layout ID and framer motion will be able to automatically animate that right so now we have a really cool advanced um nav bar here or header and of course we still need to implement these other sections but yeah I really like the header here all right and there's one more thing we need to do which is that as we scroll down and here now the about section gets into view of course it should pick up that the about section has now become the active section and then it should switch it and so basically what we need to do is as we scroll down or up and one of these sections gets sufficiently enough into view that should become the active section so not only when you click does the active section change but also as you scroll up or down so the way to do this is with something called the intersection Observer ABIA API so in browsers you can detect when some element gets into view or out of view so in react that has been implemented with the react intersection Observer package very popular package and that's what we're going to use so let's install that I'm going to open up the terminal here and I'm going to say npm install react intersection Observer so let's install that all right so I'm going to close this terminal now and let's see so the way to do this in react is and we're going to use that package but just thinking about it we can just attach a ref to this overall section this about section and we give that reference to the the hook that we're going to get from that intersection Observer package and then it will tell us when that section goes in and out of the view if it goes into the view we're going to make that the active section all right so now we have to think a little bit about that how we how can we do that so if we look at the structure of our application so far we have a layout this is the root component we have a header and then we have the page component here which holds all the sections so what we need to do is in the intro and we'll not in a section divider but about some projects in about here then we need to add a reference to this outermost element right so we're going to use we can use use ref right so we get a ref and then we can add ref as ref right that's a bit difficult now because the header is in this part of the of the three of components and then we have this page here which then holds the other sections so you can see it starts it's a bit difficult now because we are keeping track of the active section here in the header right but now we need to be able to set the active section also from the about section here right so how can we get this set active section from the header here into this page and then into about right so the fundamental problem that we have right now I'm going to undo that so just remove that the fundamental problem here is that we're trying to keep track of something so we have some kind of piece of state which we now need to share with other components in our application but but the components are too spread out basically so usually you can do prop drilling right so you can just pass set active section to some other elements right to some components and all right so you can say set active section and set active and then you can sort of drill down but here it's too spread out so now typically to solve this you want to use something called the react context API so here we're gonna instead of keeping track of the state here in the header we're now going to create a context first so we're going to use the context API first actually I'm going to close everything except the header file so typically it's a bit cleaner to create a separate folder for your context so I'm just going to create a folder called context and then we're going to create a file called active section context dot TS X so it's DSX because we're still gonna export a react component and that that's actually a so-called provider component so we can say RFC react functional components and this will be active section context profinder bit of a long name but this is how it's typically called and so then this component will keep track of the state so what we're going to do is we're going to copy this this state here instead of keeping track of that here from the header we're going to keep track of it from this component right so just paste it here and here we need to import the use States okay so here we have now removed it and now we have it here in this file and we now get an error here because active section is not defined right let's go in header now we don't have access section anymore so this is going to give us an error but soon we will have it again so just let's continue here all right so let's see so we it's just it's just basically you can think of it as a normal component that's now basically a more centralized way of right so now we're just going to keep track of the state in this component with this weird long name now let's think about the the type here actually so we are setting the use state to a string called home so now if you hover active section you can see it in first the type to be a string and but we know it's not just going to be any string right so it we we can be more precise than that right so here we can uh we can tell typescript what type it's going to be with angled brackets here and we can say for example it's going to be home or about right then we can give like uh this six or so links that we have so we don't want to write um you know home as like a a union type as it's called home or about we can be a little bit more efficient than that because if we look at the data here we have these links here and we already made that as const right so that's all it already contains some type information this so let's actually bring the links into here I'm gonna import uh links from that uh file and then I can specify a type separately here right so you don't you don't have to do it in line like here you can also just extract it out of here right so that's a bit cleaner so just like we did with the props for example we we created a separate time for that so let's do a separate type for this as well and we call it section or actually let's call it section name so now we have type section name and actually we already get a really good suggestion from typescript so let's actually accept and see what we get so now if I hover section name you can see you we already get the exact names of our sections right as a union meaning it could be any of these right but not other ones not any string right specifically these that's now we're telling typescript we're going to keep track of state and not just any string but specifically uh these section names out of type section name right so here's using type of so basically it takes links so we have links it could be any of them that's basically what number means and then specifically the name property and that's what we do here and we're saying type of type of that so whatever that name property is of any of these that's the type that this should become right so you can see copilot helps us out a lot as well okay so that's about types and now we still have a basic use State let me close the sidebar here okay so now um let's let's see how we are going to use this in our application so this is currently a default export so now um let's actually see how we are going to use this so if we go to the root of our app in a layout file now we can wrap the part of our app here that needs to get access to that state so typically what happens here um is we're going to wrap the the parts of our app that need access to the state so that's going to be both the header as well as the page right so the page is what will be placed here the page contains all the sections so what you can do is you can just write an active section there's a components active section context provider it automatically Imports this for me like this all right so make sure you import it and I can put all of this in here right this is how you typically format this now this will not work this will give us an error of all sorts of issues now um and why does this not work because now we're putting this in here so remember that's going to be the children prop and currently we haven't specified that so here we need to say this element will have children so let's see screwing up the parentheses here and let's see yeah so here it's going to be children right so children that's that's going to be whatever is placed in between the opening and closing tags right so then we have the children we don't do anything with the children right so not right now we're always returning some DFA with text but of course we actually do want to just return uh the children so here we can actually just write the children right so um whatever the children are whatever we place in between here that's what this will give us again so it's not like it breaks anything in the tree it's basically now sort of acting as a pass-through component it's not really doing anything right now it's just getting some children immediately returning that so so far nothing interesting but let's continue here so now um we need to do something with the type of the children so let's we can write that in line here so we could say children react as a react node right we could type it in line like this now we can be strict with ourselves and have a consistent system so I'm gonna I'm gonna have the name of the component I'm gonna paste that here and then just add props to it and that's going to be the type here you can use interface as well but I like to be consistent so we will call that props and we'll Define it separately here right so then um we are separating the the the the type from the components here right I think it looks a bit cleaner all right so this is what we have so far now we have wrapped the header for example in this provider component but do we now get access in the header to that active section right so can we now use active section here somewhere because that's the state here and the answer is no right now we are not passing the state here that we have in this profiler component to anything else we're just immediately returning the children but not with the state and now we need to actually use the context API from react so here let's keep the types at the top here so here what we will do is we will create an active section context and here we can see that react react.createcontacts we can do it like this right we can use the reacts variable here or we can import it like this we don't have to type react dot you can just use create contacts and so now we can just use create context and here initially you can have a default value so if you have another component let's say we had a component here and we try to that's outside the provider component if we try to access that value right outside the provider component you would get the default value that we that we can pass here now we don't really have like a we don't really have we could we could use home here but typically I use null because we don't really want to have we don't really want to access or try to access that value outside the provider component there are only very rare you know some few use cases for that but that's not really important here so we don't really have and we don't really have a meaningful default value that we want to use we actually we actually want to see an error if we try to access that value outside the context provider component so we don't we don't really want to deal with with the default value here so we're just going to use null as the as the default value all right so now what this gives us is this variable now that we can now wrap all the children with so everything that's in here is now going to be wrapped with the following so we can um actually let me just delete this so now we have the access section context and now you can say dot provider right so this is a component and actually we need to use angled brackets here right so this is now going to be a component that we get from this variable that's why we use create context and then of course we pass along all the children in here right so this is how it's structured now I'm gonna get a bunch of errors in the background but that's okay for now um so now this now this provider is wrapping all the children so whatever you put in between here this provider component that we get since it's it's named a bit strange dot provider looks a bit strange perhaps but that's what we get from create context right so first we need to wrap everything that needs to get access to some value like this and then we can use it now it still doesn't know what value we specifically want to use now right so obviously we have to find used States here with some active section but could technically also be other values so we do have to make it explicit so value what is the exact value that you want to pass along right so we're going to say the value here is going to be an object with active section right if we could write it like this active section plot in JavaScript if you have the same name as the property value you can just leave it like this right so again make sure you have Masters the underlying fundamentals especially JavaScript but also CSS all of this will be much much easier and what we also want to pass along is the setter function because in the about section for example we're going to check if if it's in the view and then we want to set the active state so we also need to pass that along we not only want to read the active section in the header for example we want to see what the active section is we also want to set it from other components okay so let's uh let's um save that now we're going to issue here from typescript so typescript is complaining type active section blah blah blah is not assignable to type null so here when we created the context we specified no so it inferred a type from that so if I hover this you can see it in first at this react context is just going to be some null value and that's not true right so here we can use angled brackets to specify what this context type is going to be so basically what the shape of this value object is going to be right so let's actually call that active section context type and then we'll Define it up here so we'll say no actually it already suggested for us so we're going to have an active section and that is indeed going to be home about you know projects that's actually the section name that we already defined here so we can use that type here as well then we're also going to have a set active section and yeah copilot actually is just a perfect suggestion here so this looks very strange because set active suction is actually a set better function that we get from you state if you hover this variable you can actually see the type right so you don't have to memorize this sometimes if you know if you don't have copilot for example let's say we don't have copilots and you don't know okay so set active section is what we're passing along but what's the type of this this Setter function you can just hover it and it will tell you what that type is and so it's something like react.dispatch and then it's a generic so here in the angle brackets we have something else which is also generic it also has a generic also a generic so then you can pass in another uh well variable or type essentially here right so here um I'm gonna copy all of this that's how you would do this and you would say this is the type now here it's actually it's actually using these values of all the links here we don't need to do that we can just use section name all right so we can just say section name right so this is basically the context type we already specified that here and now we get an issue so we say argument of type null we basically just told this create context that it's going to be of time of this shape but now we we also all of a sudden we are passing in null null is not defined we haven't said that there's going to be no here so now say oh you can't pass no it's gonna it's not part of the shape so we can say it's going to be of this type or or Union type and typescript or no imagine the net Arrow disappears so initial to the default value could be no right so the value could be no if we are using it outside that provider component okay so that's enough about types the touchscreen is a bit tricky to wrap your mind around especially if you're just getting into typescript but if you have mastered JavaScript I keep repeating it if you've mastered JavaScript it's very easy to pick up typescript as well so I know some of you are very excited to build you know very Advanced applications but you're gonna run into many issues if you haven't mastered the fundamentals all right so all right so now we have properly typed all of this and now we don't see any issues any errors at least from typescript here all right so let's actually see what the error is that we're gonna get here so here we're using Create context and it's telling us you cannot use context in a server component right so here it says is you're importing a component that needs create context so it only works in a client component and so sometimes the error matches are a bit strange so I'm importing a component but we're not really importing a components here and so it means probably here is in the layout in the root file we're importing a component right so that's a bit strange because it doesn't link to that layout file and actually uh here it does okay but it only works in a client component so this contacts provider needs to be a client component right that's fine we will just make this use client that's another provider context provider component is going to be a client component and then here we are importing that client component active section context provider all right so let's see if that works and now we get some other issue I'm just going to refresh because I don't know what this is about let's refresh and see if this works all right so now at least we got rid of that um client components issue now we just have the same issue in the header which is of course here we're trying to read active section right the read the extra section value here is still here and we have now wrapped the part of our app that can access that but now we still need to access it here right so that first you need to sort of provide it and now the second part of the context API is to actually consume it to use it right and about server and client components by the way so I just said this context provider is now a client component here right so this layout root file is a server component we're importing you can import a client component into a server component and then use it here now you may think if we put it like this this is a client component so so now everything in here basically our whole app is now basically going to be your clients component as well right so everything in here is now also going to be a client component and that's actually not true right so this is a bit tricky but luckily because these provider you know components often that's high very high up in the tree in a react 3. um if you if you use it like this so basically with the children prop right so if you if you have a client component you can still have server components wrapped in there and as long as you basically use it through the children prop right so this this could technically still be also this could still be server components in here right so this it only becomes a CL they these things only become a client component if you have used clients like this or you are importing them in a client component so if I would import another component into here that would automatically become a client component as well right it's a bit tricky there but um it makes sense when you think about it because you know this is such a typical called pattern in react apps these provider components very high up in the tree and they need to be client components because of react context API so it would be kind of strange if then everything immediately became a client component it would basically undo a lot of the benefits but that's not how it works alright so now we need to consume it right so here it's complaining it doesn't have access to the active section variable right that's now we now have abstracted that away into this other components but we're passing we have provided that now for our app through value so now how do we consume it how do we consume a context well we have another we we have a hook for that and let's just use it here so we can say use context right so reacting gives us this use context and then it needs to know which context because we could technically have multiple contacts in our app and actually we'll see we're going to have dark and light mode as well so the theme is often also something you want to put in context so here once now here wants to know that it's going to be the active section context right so we will have to import that from here let's see so this variable basically we would have to export that import it here um and typically you want to write a separate um book for this but let me just quickly show you how this works so here we have this active section context we need to export that so I'm going to say export I'm just going to write export in front of it so it's a names export so here we can use it and I can I can put my cursor there and import it like this all right use context as well I'm going to import it like this right so now we get the actual context the actual value of the context I should say all right so we can say active section context value adds a bit too long right so we could call this some something like because what are we actually getting here it's a value isn't it's going to be an object let's just call it value and so we it's going to be some object right so here this is the value it's an object right so the first the auto curly bracers are just you know in jsx so we can use JavaScript the second curly braces then are for the actual object literal right so that's in JavaScript object that's what we're getting here right so that's going to be an objects right and then we can use object Dot all right we actually already get the intelligence active section right now it's easier to just immediately destructure this right so we get active section and the setter function but we don't need a set of actually we do we do need to set a function here as well so set active section that's what we get now from uh use context and let's see we got an issue here active section does not exist on type active section context type that's interesting so all right so here we get a weird issue because it says active section does not exist on this on this context type right so here um let's see context type and we have specified the active section here actually so it should work so here when we create the context we are saying this context is going to be of that section context type or null and that's actually where this issue is coming from we're saying it could also be no so here we're trying to extract or destructure active section right but it could be null as it is used context could give us null and so here we're trying to use active action so it's going to say well yeah you don't know if it actually exists right so you're going to have to deal with that you're gonna have to right you can you can't just assume that this is going to exist it could be null so typically a better way of dealing with consuming this is not to do it here like that is to have a custom hook that takes care of that null value and then we'll use that custom hook in there in here so we don't have to worry about that null value right so we're just going to write a custom hook in this file as well so it's just going to be a function a custom hook a hook is actually just a function that starts with the use word and we'll call that use active section context not just a function and then we can use use contacts and actually we get all of this suggested for us and let's see let's actually accept this and see what we get so first we're gonna use the context this is the react hook that we get and just like we saw before I need to import this now so I'm going to hold Ctrl spacebar press Tab and it will import that for me right use context the instantly which context you want to consume what's the active section context which is already defined in this file okay so then we get that objects now this is going to be this value object or it could be null right so we have specified here could also be no so here we can check if it's actually null it's going to be null by the way when you try to consume it in a component outside this provider and that's that's when it's going to be null now if it's no we actually want to throw an error right so it's going to say use active section context must be used within well let's have some correct grammar and active section context provider component right so then we'll throw an error and the application will stop working so if it's not node though we just return the context right so then we just we will actually just return this value here and we know it's not going to be null right so now we can just use this one let's actually export this so we're going to export this hook we don't need to do anything here so now we can consume it in the header so let me remove the previous import so now we can use that custom hook we can say uh use active section context and automatically Imports it for me I also don't have to provide the context variable here right so that's also a bit easier and now we can just grab the value right so finally we can grab the value the active section from this hook and now you can see we don't get any issues because it's not going to be null here because if it's going to be null it's going to be an error will be thrown right so once it's actually returning something here is when we actually can destructure it and we know it's not going to be no right so if you hover it you can see everything is working now with the types we also get that Setter function so also say active section we also want that one okay so now let's see now let's let me save this file and let's see we still have this error and the error should be gone because now active section is actually existing here right and that looks good and now if we click on about it still works right so everything is working now so active section here is what we're using right so active section is now just coming from different components essentially right so we have abstracted this away into well basically this this context API setup the context API looks a bit tricky also with the types it looks a bit complicated so you know react and also next.js I will have a react course very soon highly recommend you go through that check out the links in the description it's not released yet I'm waiting for next.js to make some of the other features more stable but you know the context API is something that we will definitely discuss more in depth and we will practice with that more and more in that course so you know if you're if you're watching this video I highly recommend you you sign up for the email list because you will be notified when the react next year escorts full stack will be released and you'll get a discount code right so make sure you are on the email list right I really think it's going to be the most valuable course in the whole uh software web development space okay so we have active section here and when we click on this link we are using set active section right so these variable names are the same right but they're just coming from somewhere else now and they're coming from here okay okay so that's cool but this was already working for us so what we now want to do so what we now want to do is when we scroll down and when I scroll in in this about section gets into the view it's the about section that you become active right so now what we can do and I can actually remove this here from the Imports here in header we don't need this anymore so now we can go to for example the about section let's go there about so here we need to know when this about section is being scrolled into the view and we have just installed the react Observer package right reacts intersection Observer is what we're going to use for that makes it very easy for us so if I look at the package Json you can see we have installed the react intersection Observer package so it gives us a hook that will tell us when this section is in in the view so let's see it's called use in view is what we get you can see I already got the suggestion and automatically Imports it for me so if we call this function it will give us two things that we need to use the first one is a ref that we need to attach to the element that we want to keep track of that needs to go in and out of the view and the second is just a variable that will tell us when it is in the view right so now we just need to attach this ref to this element here to the outermost element because this is the element that we want to know about when it gets scrolled into review right and that's basically it and so now we can use in View and so now we can check if this about section is in view it will be true and then we want to set the active section to about right so let's actually log this variable to see what we get so I'm going to log is this in view variable all right so I've zoomed in a little bit so currently it's true so if I scroll a little bit further down it becomes false if I scroll up again the about section is true again if I scroll down it's false all right so as soon as the viewport right so here if this as soon as the viewport shows even a little bit of the section it becomes true right so this in-view variable becomes true as soon as we scroll a little bit outside this section um oh yeah so now it's still in view right so it's still in view a little bit here and now it's false all right so this in view will tell us true or false when it's actually in the view all right so what we basically want to do is the following so if in view right so if this section is in the view we basically want to set the active section set active section to about that's basically what we want to do here now set active section we don't have access to that it's the setter function but it is pro it's provided for pretty much everything in the app right that's what we've done here right so now we just want to consume it we've created a custom hook for that so it deals with the null value so we can assume it's not going to be null it's a clean way of dealing with it it's very professional way so we want to basically use this hook I'm going to copy it uh to to get this uh Setter function right so we can use this I'm gonna import that and this hook will give us two things it will give us the the currently active section right active section but we don't really want that we only want the setter function in this case so we only need access to the set active section function right so here is the about section is in view we just set the active section to about and that will automatically make the active item here and this will automatically make this animated and everything because everything revolves around the active section state so as long as that state is in in is to have the correct it has the correct value right all the animation all this stuff is taken care of right so you just have to make sure that this this state that we prefer that we added here is is correct right so if this about section is in the view we make that the active section now here we are setting State basically in the render during rendering here right so basically this component body in react is what's being rendered right so if you were if you've worked with class components the the function body in a functional component is basically the render method in a react class component and it's not recommended that you set State during rendering so this is not if you if you do this you will actually get some errors and warnings and so instead we should probably use the use effect hook here because we are essentially trying to synchronize some external system right so you want to use the use effect Hook when you want to uh well they also call it side effects but the the more typical way is when you want to synchronize the state with some external system so we have basically created an external system here of keeping track of the states and now we want to use use effects to synchronize that with this infu variable value right because in view tells us the current state and now we need to update our external system basically of that update so that's how I think about for use effects people tend to overuse the use effect hook so you wanna you wanna try not to use it but I think in this case there's basically no other way so we need to import it here from reacts usfx and then it also has a dependency array so basically these this function this user fact will only run if one of the variables in this array changes so that should be the in View and technically also the setter function here now these Setter functions you don't really have to provide them because they are stable values and now when you leave it off though we do get an issue here with e as a lint so eslint is a bit more strict here we could remove that we could remove that rule just like we removed the other rule with the apostrophe or just added here about this files let's just add it here so basically this use effect will now run every time in view or set active section changes so basically it's more about in view so if interview becomes true we're going to run this function if it becomes false we're also going to run it but then this if block still checks if it's true only right so we only want to do it if it's actually true all right so this was a bunch of setup so now I'm going to refresh the page I've saved the file so I'm going to refresh the page and now let's see what happens if we scroll down to the about section actually it already works because the about section is already into view and you can see the about section is actually um is already made active for us right let's see let's see what happens if I refresh on this part of the page so let's see what happens now you can see the about section is not active but now if we scroll up a little bit now you can see as soon as some text here of the about section gets into the view it becomes the active section right and clicking still works um there's a small issue here yeah so here when we scroll up to home we'll deal with it in a second right so you can see that's working now and it's only for the about section that it's working right so now let's also make it work for the project section so I'm going to open up the projects section and let's just copy everything here because it's going to be the same so we can just add that here in the projects section as well and now we're going to run into an issue here with the project section because if you remember maybe we we were able to keep this as a server components right and then the individual project is going to be a client component right so this is still a server component but now we're trying to use these hooks right so these hooks are using context API here we're using use effects these are client-side features so now we actually do have to make this a clients component as well right so that's okay though it's not it's not a it's not a in this case it's not a huge deal but uh typically you only want to use a client component if you actually need to right so in this case it's fine so then we need to import a bunch of stuff actually we don't get uh suggestions here so here at least I do get this and then let's see here as well and so use in view is coming from this package so I'm going to copy that and I'm gonna paste that here now we need to attach the ref because this intersection Observer needs to know which element it needs to keep track of in the viewport and so this section just going to be the reference element and here when this project section gets into the view we don't want to set it to we don't want to set the active section to about but you'll actually become projects of course okay so let's see um I'm gonna refresh here yeah okay so now let's see what happens about is now active because it's in the view here and now when I scroll down a little bit you can see it switches to projects and let's see if I scroll down sufficiently so that about is out of the view and then scroll up a little bit you can see it's the about section that becomes active again if the project section is out of the view and I scroll down it's the project section that becomes active again right so now this is technically working but it's not really as smooth as it can be because for example when I just load the page here the about section immediately becomes active right and that's not what we want so ideally what we want is maybe the about section becomes active when like 80 percent of its content is in the view right not a little bit but when it's 80 of the whole section then it should become active so we can actually customize that here with using view from this package so we can provide a options objects here and it can we can provide thresholds here so we can say when 75 of its content is in the view if if 75 of the element is in the view then we want to have we want to say yeah okay it's in it's in view that's not just when it's a little bit it's like just one line of text now 75 so quite a bit needs to be in the view and that's when the about section is when we consider the about section to be in view and then that's actually when we want to set it to be the active section right so we can also change that for projects here because project is a much bigger section here so we can customize this a little events so here we can say the threshold should not be 0.75 but let's make that 0.5 so when half of its section because it's a bigger section and let's also add this for the intro right so that's actually uh copy everything from the projects component and let's paste that here in the intro component so we need to do a bunch of imports here again I'm just going to hold the controller command spacebar and use in view still doesn't automatically get imported so I just have to copy and paste this from somewhere so using view we this hook gives us the reference I guess it gives us this ref that we need to attach to this section here and here of course when this intro becomes active that's actually just the home section here right now by the way we have typed this properly by the way so if you actually make a mistake right if you type something like home it will actually give you the warning here right so this is one of the benefits of typescript because we have very specifically types all of this so even a small subtle mistake will now get picked up and you can fix it during development it's also nice because you can hover this and you can double check what values it accepts basically that's one of the benefits of typescript okay so that's a safe here because now we have all the three sections that we have so far and we have customized with the threshold as well so we'll also keep 0.5 for uh for the intro all right so now when I load the page let's see just to start from a clean slate all right so now the home page is active right even though the about is also in the view we still uh are on home which is actually what we want because we don't immediately want to jump to about so now when I scroll down a little bit you can see it it does jump to about very quickly but that's fine and then let's see when we go to projects here yeah so when project is about half interview it it jumps to projects right so this looks good this is what we want let's now let's scroll up and see if it's something similar yeah so now it switches to a bus right and eventually it should switch to home yeah okay so now you can see we have a really Advanced uh header here you know we've used context API we've used some custom hooks from react intersection Observer we've used some third-party hooks or some third-party packages here for the intersection API so quite a lot of uh quite a lot of setup actually but once you understand that it's quite easy to work with right so I highly recommend that you check out my react or next.js course as of recording it's very close to releasing so get on the email list so you can get the discount if any of this seems a little bit intimidating that's completely normal and fine you know take some time and react to get to get to get used with a lot of stuff and these days you know typescript has really become mandatory almost to use with types with react if you look at the job applications a lot of you know a lot of job applic job vacancies mentioned typescripts right so it's really becoming a standard and it's important that you understand typescript as well it's also part of my course react next to S course all right now we have one issue that we need to keep that we need to solve here if we now click on any of these sections so if I click on Project you can see it sort of switches so if now click on a home it first switches to about again and the reason it happens is because if I click on projects it will also show the about section in the view and so as the about section gets into the view we are setting this active section to about right so when we click on projects it's it's first uh sort of sets it to about again and then projects so that's a bit annoying especially as we go from home to contacts it's going to switch between all of them so to to solve this what we can do for example is because there's basically two ways now that the active section changes is because we click on it we click on something on in we click on a link here or it's because we are scrolling this section into view right those are the two ways that we are setting the active section and when we click now we don't want to have that scroll based active section right we we only want to have the section that we clicked on be the active section so when we click when we click on the link we sort of want to disable that scrolling functionality that we just implemented for like one second or so so the way that we can keep trying we need to keep track basically of the last time that we clicked on the header so as soon as I click here I want to disable that that scrolling uh section feature or whatever you want to call that we want to disable that for like one second or so so we need to keep track right so here um here as we as this gets the ad as the about section gets scrolled into the view it's gonna set in view to true and we're setting that here right even though that's not the end destination for us it's not the end destination but it will still do that intermediately um and we don't want that so here we basically want to check if if we just clicked on an item in here we don't want to do this right so one way to solve this is to Simply keep track of the the last time that we clicked and then we can use use that to disable that we can disable this for basically one second all right so maybe we should just implement it and it will be clear so what we can do is I have another state variable and this will just be the value 0 initially and we're gonna call this state time of last click and also the setter function set time of last click but this will be a number type this date and you states can already infer that from here right so here we actually don't we don't need to write number although we could do this right we could do this but it actually already infers it so it can already assume how it's going to be a number right so if you if you hover time of last click you can see it's going to be a number right that's fine all right and that's actually just what we're going to pass here as a value so whenever we consume this context we can also get these now so time of last click and set time of last click and we get an issue here because we have not we have not specified here for the context type that does that that is allowed right so here we only have active section and set active section so now we also need to add time of last click that's a number and of course we have that Setter function again which is this insane type so again if you don't if you're not using copilot you can just over this and typescript will tell you what type this is right because we're getting it from you stand so typescript already knows what it is so you can just copy this and paste that here right it's going to be a so-called dispatch function but more specifically a set date in react action and that's going to take and that's going to be or it's going to take in a number right so that's how you can read this but that's not really important okay so that's not what we are specifying here so now we can also consume these two so what we can do here when we use this uh when we consume here we can check the time of last click so here we can check before we set this because we don't want to do it we don't want to do this basically when we just when we click that so we can check if um we actually already get a suggestion so what we can do is n when and actually this sounds this looks about right so what we can check we can take the current the current time we can do minus the time of the last click and if that is more than one second right so one uh 1000 milliseconds so basically it's been more than a second that we clicked then we will actually set this section and now we we also need to supply these values here so time of last click so we'll add that here okay so now we also need to actually keep track of that by setting this time of last click and that's what we do in the header let's go to the header and when we click when we actually click on home for example um let's see yeah so let's see we have the on click so here we are currently doing one thing um so let's actually add curly braces here and another one at the end so now we're gonna do not only set the active section but we also want to set the time of last click and we can use date.now if you hover this it will give us a number we get an issue here let's see cannot find okay so here we need to import that right so here we don't have access to that value so we can use this context right so we can just import that layer set time of last click all right so now when we click we are also setting this time so then let's actually just try it let's see what we guess all right so now when I click on projects you can see that it doesn't stop at about in between anymore right so now when I switch between projects and home it's never stopping at about or do having that weird uh squiggle right so basically what we're doing is when we click here we disable that other method for like one second let's actually just I will just write a comment here you don't have to write this but I will write this I'm going to upload this code to GitHub after recording so we need to keep track of this to disable The Observer temporarily when user clicks on a link all right so uh I'll save here right so we just did this for about so here for the Observer API before we set the active section to about we're first going to check if the time of the last click has been more than a second ago right so then we have we are just essentially just disabling this for a second when we click on something here and we want to do the same for the other sections so let's just copy this so projects before we set it to projects we want to make sure that basically it's not it's not uh disabled or tune before we set it to project we're going to check if the time of the last click has been more than a second ago so we need to import this we can import time of last click from this uh section active section context so time of last click just press Tab and we need to provide us here in the dependency array as well all right and then also for the intro so here let's also paste it here actually let's copy that um all right so for intro I also need to oops it should be home and here I will paste this here that's a time of last click I will add that here and then also in the dependency array all right so this is a bit confusing perhaps but uh this is the real world in the real world you're gonna have to do these quirky things sometimes right and it's okay if it's a bit uh if it's a bit confusing as you get more experienced you'll uh you'll build an intuition for how these things work all right now we are pretty much finished with this header now just to take our react level to the to a more advanced or senior level if you have a lot of or even just a little bit of duplication and that's just that's true in general for programming you may want to you may want to refactor that so you are reducing the duplication so here we have quite a bit of duplication here for the intersection we're doing this uh use in View and then we you have to use effect talk we're doing pretty much the exact same thing in the about section right and then in the project section we are basically doing it as well right so this is this is quite a bit of duplication we're going to have more sections after this so it would be a cleaner way of of refactoring this basically all of this into a custom hook that we create ourselves right so just just out of convenience just out of you know clean code principles so what we're going to do and typically what you want to have is a separate file for your custom hooks as well so let's go into this Library folder and let's create a separate file called hooks.ts so here we're going to create a hook that will just replace all of this stuff here so remember we're using this all of this is for when we scroll a section into view so that we can set the active section that's what we're doing here right so what we want to be able to do is just copy everything here I'm going to copy everything here and now we're going to create a custom hook so let's actually call that something like it's going to be a function right it's just a normal function in JavaScript but it's going to use hooks so typically so you you would use the use keywords at the beginning of the name use section in view let's call it like that so that's just going to be a normal function and then we can paste all of that stuff here right so here again we need to import it so let's see use active section context Ctrl spacebar use effect use in view let's see using few comes from this package so I'm gonna copy that and paste that here and we want to export this not as the default because we can have other hooks here as well so you know this one shouldn't be the default so what we need to do here is basically so the way that when you are refactoring here what you want to be able to do the best way to think about it is what do you want to be able to do here so instead of typing all of this stuff out for each section right one instead would look cleaner like what would be the ideal way of of replacing this well that would be if we could use this custom hook this custom hook right so we can say we can just call that custom hook and actually we can already import this so I'm just gonna import it like this and then we still want to have the same functionality here right so we do still need to attach this rough here so this this hook should still give us a ref and so we should still get a ref from that um hook that we should attach here and so this hook should at least return a ref right so here we want to return an object because we're going to return multiple things not only a ref but you can see at least a ref right so now we know okay so at least a ref is what we should get back from our custom hook all right so we have a ref here because we still need to attach that here now the in view variable we don't really need that and we don't really use that here so we can we can just use the in view here just internally and so we don't have to use the in view anywhere here this hook can then just set the active section now we have hard code at home here right so now if we want to use the same hook for the about section as well we're going to have a home here that's not what we want so clearly this hook should also should also take an input right and the in what we want to pass here is home right so in this case it should be home in the about section if we're going to use this hook that's actually just right so here in the about section if we use this hook we want to pass about right so this hook should receive an input right so we can call that section name and we had rats quickly let's see what we get yeah so we haven't properly typed this yet so we get Section name so this is just a function so let's actually just uh type this so this name section name is going to be home about blah blah blah right and we actually already dealt with that here so we have uh in this section context we actually already have a type for this section name so we could recreate it but it's a bit cleaner to have a separate file for types that you use throughout your application so we're going to add another file here and we can call that types.ts so here where we have type a section name instead of just putting that in one file we're going to put that in a separate file here and then export this type okay now here it doesn't know what links is so we can still import that here actually just use control spacebar and by the way a I use prettier prettier automatically adds these parentheses for me I'm actually not sure if that's necessary but uh that's why I have these parentheses all right so I've imported that here right not using the Alias it's just using a DOT forward slash which means in the current directory take the data file or use the data file and then import specifically the links okay so now we actually don't need it here anymore in the context file so let's actually just remove it from here and now it's gonna complain doesn't know what section name is yeah because we just removed it from here so now we need to import this so let's actually see if it can import this yeah actually it can import this so it's importing section name that's it's a type but you can just import it like a normal JavaScript value even though it's a typescript type but you can import it in like a normal JavaScript value now typically it's a bit or maybe a bit clearer we can specify that we are importing a type here right so that's just uh for extract Clarity and there are some very small uh safety benefits to this as well so we are now importing type section name okay so now we can also import that here right because here we're trying to create a react hook that takes in a section name right because here I want to be able to call it at home and another component I'm going to be able to code with about right so it's getting pretty complicated here so bear with me so section name um should be let's actually copy the name of this function right so let's just extract this into a separate type like always type use section in view props so section name is going to be of type section name right which is what we defined here so we can import this and I like to add type here right okay so now we know that this hook takes in a section name with this type so basically it should be any of these so now when I try to call this with blah blah we we will get an error now here when I try to use it with a home it should actually work so here it's a bit strange because here I'm we're using the function with the home and here we have just typed this this could be home so it should work the touch cut for some reason it thinks this is any string now sometimes you you just need to restart the typescript server so I'm going to hold Ctrl shift p and this gives us an interface to write commands and so what you can do you can also go to view command palette and then you can say typescript and here it says restart typescript server so if you do that it's going to restart typescripts here and sometimes that actually uh will fix the issue because sometimes nothing is wrong it's just typescript hasn't updated yet so in this case actually we see that there's still something wrong and the reason is wrong is because we are trying to destructure this right so that works if you actually pass in an object right so if you actually passed in an object section name and so if we would do this now you can destruct your section name here right so that's actually a typical format for react component so that's why I was a little bit confused here so here we're not passing we don't really want we don't want to pass an object we just want to pass a string so we can't really destructure this right so just you we can still call this section name and instead of extracting this into its own uh type here we I I prefer to actually do it in line if you are not accepting an object but just a string I think it's just a bit easier to just do that inline so we can still say this section name is going to be of type section name and now we can pass home and we don't get any issues right so I hope you're still with me this is quite a bit of refactoring here that's the real world right and actually get more experience a lot of this will be more intuitive all right but don't worry if some if something is unclear alright so now we're calling you section in view with for example home or about projects so the section name should now go to that active section should become whatever we pass here as soon the home should not home should not always be active section should be whatever is the section that gets scrolled into view so now we also need to add this to the dependency array all right so let's see what we have now so far so now um we can pass in home and it will do all of that stuff that we did before but it's now abstracted away into its own function that we can now reuse in other sections as well now there's one other thing that we're hard coding here which is this threshold right this is also should actually also just be an option when we call that function we should also be able to customize that so we can call that threshold and we can actually set a default value right so in JavaScript you can set a default value so if we don't pass anything for threshold it will just take the value 0.5 and we actually want the default value to be 0.75 so I'm going to change that and so here when we call this use in view hook we don't want to hard code 0.5 it should be whatever that threshold is right so and again in JavaScript if you have same property name and value you can just pass threshold right so make sure you master JavaScript itself check the links in the description and also now that we are using this default value we don't have to specify a type for this threshold because it typescript can already infer the value from this default value which is going to be a number right so if you hold threshold you can see it's going to be a type number all right so now this intro here previously we were actually providing a custom threshold so we can still do that now so now I can still say 0.5 right and that will still be the threshold only if I pass nothing will it be 0.75 if I try to pass a string we will get an issue typescript will complain because it should be a number right so touchkins helps us out in that case all right so this is quite a bit of refactoring now I'm just going to remove what we had previously you can see how much cleaner it is now in this component of course we're still running the same code essentially here but now it's a bit more reusable so we're not repeating ourselves as much and the components themselves are going to be much cleaner right so you can see how much cleaner the component is now now we can also remove these Imports here from the intro component also this use effect import and yeah you can you can reason about it right so you can see it's just a custom look is just a function normal function in JavaScript that is using uh some react features at the end of the day right so like user Factor use state or other Hooks and you can reason through it right so we have two inputs home and threshold right so it's going to be section name and threshold and that it's just gonna it's good it just it will just set up the things the exact same way as before right so it's just a replacement it's just refactoring it's just in terms of Aesthetics essentially that it looks better right but you can just replace this function call with all this stuff in here right but it looks better and typically in programming if you're repeating yourself right the dry principle don't repeat yourself so if you find yourself repeating try to refactor it right not always doesn't always always make sense but usually it does all right now we also want to do this for the other section so we still have all this stuff here in the other in the about section so let's just copy this and let's replace all of this stuff here with this custom hook that we have you can see how much stuff that saves us you can see how much uh how big of an improvement that is here in in the in the component so we can remove these Imports right much much cleaner here in the component now let's see for the about section right now we should remember what we call this with all right so now we can replace all of this let's remember this is 0 0.75 threshold we can replace all of this with just one line now you can see how much cleaner it is we have to import this hook we can remove a lot of imports as well and now of course we need we do need to change this so now we don't want to set it to home it should be about and we actually want to have the default value for the threshold so here we don't want to have a custom value or threshold right ref should still we should still return a raft so we can attach it here to the relevant section okay and then let's do the same for the projects the projects also has a custom value for threshold so let's remember that I'm just going to copy this line and we're going to replace all of this stuff here with this and then let's change about into projects and we need to provide a second argument here 0.5 and we'll just import this hook and remove the Imports alright so you can see the components now get much cleaner now we still have to this still needs to be a client component right so here we're still using a hook and this Hook is using cleanse side features right so this is fundamentally nothing has changed it's just the rewriting so now if we scroll up and down you can see it still works right so everything is still working then the header is still properly working the sections still get into view and out of view and now we can still navigate like this as well right it's properly disabled that's uh scrolling active section it doesn't go in between or anything like that so now we have a really Advanced sophisticated professional header that is taking care of some of these that's taking care of some of these gnarly issues with uh scrolling and yeah this is pretty advanced stuff so it's okay if if you aren't completely comfortable with what we just did here alright so that was probably the most difficult part about this project so now let's continue with the next section which is going to be the skills section so if we look at the example we're gonna have a bunch of skills here and the cool thing is if I reload this page the first time that you scroll this into view it's going to have a very cool staggered animation also very easy to implement with framer motion alright so let's uh actually let's close all the files here I can hold the right click close all and let's create a new component here this will be the skills dot TSX component I'm gonna say RFC press tab and uppercase this skills or capitalize it alright so this is going to be a section again section and we will use our header header or a heading router section heading components all right and the text should be my skills all right so below the heading we're just gonna have a list of skills so where did we put the skills well that's also part of this data file right so we've used the links here we've used the projects data and we'll use the experiences and after this one but now we have this skills it's just an array of strings right I'm using as cons here as well so we can uh just map over that so it's going to be a list right so let's first create a list and then in the list we can take the skills data skills data so you can set skills data we can import that dot map and what we want to create is an Li for each of them so I will say Li with the key I'll just use the index and then in there we'll use the skill dot uh this just the actual skill all right so it's just a string all right let me close out of here okay all right so um let's see what we get nothing because of course we didn't add this to the page yet so let's go to our page component here and below the project we're gonna have skills and I can automatically import that so make sure you import it and this is unstructured so far okay so then we see the my skills section here all right cool let's style this section we'll give it a margin on the bottom of 28 we're going to restrict the width a custom value 53 Ram and we're also at that scroll.mt8 class that uh when we when we click on the header it will scroll to the section but not right at the top right so there's going to be some more space and we'll say text Center and we'll say margin on the bottom of 40. okay so that doesn't change much much let's also style this list yeah that's going to be a flex component I'm just saying that it's going to be flash component we've already placed them horizontally next to each other right now it's going to cram everything on one line so we need to explicitly allow them to wrap with flex wrap and then we say justify Center We'll add some We'll add a gap some space and we'll add some uh we'll make the text LG and we are going to slightly de-emphasize the text a bit okay so then let's actually style the individual lies we're going to have a border or a BG of white actually and it'll have a border and the Border color is going to be border black with 0.1 opacity so 10 percent we'll also give it some router rounded corners comparing horizontally and some padding vertically alright let's see what we got all right so this is what we have does this look similar yeah it looks about right so we need to add some margin on the bottom for this SEC for this other section so we don't uh so we're gonna get some space so there's actually some space between the sections so if we go to the project section we will add some margin on the bottom here of 28. all right so we can close this again all right so this looks about right and what we want now and actually let's uh let's add that hook that we used for the other sections as well so just to because now if we scroll in the skills you can see it's not working in the header here right so now it needs to identify that this skill section has come into view and we've created a hook for this and that we've also used in the projects uh section here so let's actually copy it from the projects section and we can use that hook here as well okay now here we need to change it because here is not the project section here it should set it to the skills the active section to the skills right and also we will remove the threshold here for how much how much of the section should be in view and we'll use it we'll just use the default so we have to import this and I think we're going to run into issue here yeah because here um we need to make this a client's component right so we'll say use client and let's see what happens all right so now let's check it out in the in the header let's see if that works so this works and skills is not working because we haven't attached the ref here right so we do need to attach the ref here because under the hood we're using that react intersection Observer so it's going to check if a particular element has come into view but it needs to know which particular elements right so that's why we have to attach a ref all right so now let's take a look yes for now you can see it switches so now it switches back to projects now it switches to skills right very smooth all right so almost finished actually so the last thing we want to do here is get that cool uh staggered animation but only one so only the first time you scroll past it so let me refresh here now when I scroll down we have this cool staggered animation very easy to do with with the frame and motion so we just have to convert this Li into motion dot Li whoops motion.li and let's also make sure the closing tag is correct you need to import motion and I don't see it here motion config is something else so we need to import it manually and actually copilus helps me out here okay so um if you remember we've used initial and animes before so we've set initial is something right and then animate now we can write it in line here but often in this case in this scenario you're also going to extract it somewhere else so that's what we're going to do here so we're going to create a new variable here we go we're going to call it fade in animation variance so you can also have so-called variance in framework motion and it's basically going to be very similar so we're going to say initial is going to be well opacity zero indeed so they should all let's take one more look they should all sort of fade in from from below and in terms of opacity as well as in terms of the position they should start off a bit lower right so opacity should be zero and Y along the y-axis that should start 100 pixels lower initially right and then the animation animate will put the opacity at one and Y at zero right we're not going to say transition okay so then we have this so let's copy the name fade in animation and actually this is wrong it should be animation variants not animations now make sure you have the same name fade in animation variants so then we can go to this motion Li component and we can say variance that's going to be those and that object so what we're going to say here is now we're going to say now we can say initial and instead of doing it in line here we can just refer to the object Keys here so we have initial and animate so obviously for the initial prop we actually do want initial as needs to be a string and then before we set animate and this will animate it if we do it like this it will animate it as soon as we load the page we don't want that it should be animated when we actually scroll it into the view and we can also very easily do that with with framework motion all we have to do is say while in view is animate right so this should happen this animate should happen when it gets into the view and we also don't we don't want to have it happen every time because I always think it looks a bit cheesy if you do it if you also have it when you scroll up so we only want to do it once so what we can also say is viewport is and then here an objects we can say once true okay so let's see what we get if we do this I'm gonna refresh here a little bit higher and now when I scroll down you can see it's not exactly what we want so if I refresh again you can see it's it it is the type of Animation that we want but not um not in the order that we wanted so they should all come one after another right so in the example they all come one after another and here they are all basically going at the same time right so what we need to do is for each one of these lies because we're mapping over all of them every one every one of these should get a delay that's a little bit more than the previous one now it becomes a more advanced framer motion situation how can we make sure that this Li because what we can add here is basically a transition so in animate here we can actually also add transition so it's in the animate object and what we can do here is we can add a delay right of let's say 0.05 but now they will all get that delay right so how can we make sure that each Li gets an additional 0.05 seconds of delay that's what we want so we can actually pass something into this object here so here if you go here if you if you set custom here you can pass a value and here's going to be the index right so actually we're going to use the index here because as as the index goes up we actually want more DeLay So the index makes sense to use here so we're going to pass index and then we can access that here so the animate instead of just have instead of this being an object we can make this a function now that returns an object right you can write it like this in JavaScript so very quickly you can if you write an object like this you can just wrap this in parentheses and now you don't have to write the return keyword right so if you don't have parentheses this won't work right so now it's like the opening of of the function body right so then you have to write return like this right so you can do both you can do this or a bit faster to write is instead of using the return keyword you just use parentheses here and then we also have to remove another one here yeah okay so we have that custom index and we get this here as as an input so we can call that index and typescript wants to know what kind of value is going to be so we can say it's going to be a number and then we can just use that here so this delay is going to be 0.05 let's do times the index so if it's if the LI is for example index 20 it's going to be 0.05 times 20 which is going to be a bigger delay than an index of two right it's going to be 0.05 times 2. so you're going to have a staggered like animation so if we save here and now let's see what we get I'm going to refresh here and now we have a very cool animation here for the skill section all right let's also check if it works if I scroll down so I'm going to refresh here and now I'm going to scroll down to the skill section and we get a super cool intro animation as we scroll down for this section as well so well done if you made it all the way here all right let's continue with the next section this is what we have now let's take a look at the example so now we're going to have to my experience section also with some cool animations as it gets scrolled into the view so we're actually going to use a third-party component for this because it's a more complicated component and often in the real world you're going to have to use third-party components now so this timeline component is a very popular Library actually for this called react vertical timeline component right so you can see it solves a lot of issues for us and that's what we're going to use so let's install this we have to npm install this so I'm gonna open a new terminal window here and we're going to say npm install it's a react vertical timeline component react vertical timeline component and press enter here and it will install it for us okay I'm going to close this terminal window and let's close these files and let's create a new component here about experience dot TSX RFC experience we could call it experience section but let's continue with uh the format that we've done it in so far and actually we forgot to do one thing with the skills section because now if we click on skills we don't go there right so we need to add the ID for the skills section as well so here go to the skills component and here actually we can just add the ID it's already suggesting it for me so now when I save here and I click around here let's see if I refresh and that doesn't work it needs to be lowercase right so uh easy mistakes you may make sure it's lowercase all right so now yeah now it works right pretty cool intro animation again okay we can close this and this is going to be a section okay let's also give it the ID immediately now let's call it experience all right so then we're gonna have a section heading and we'll say my experience all right and then below there actually we need to import that and then below there we're going to have the actual component that we just installed now if you look at the documentation we need two things so we need two components and then it also we need these uh we need some Styles now I'm just going to copy it from here I recommend that you go into the GitHub repo for this project and you can go into components experience and you can just copy that from here alright so let's see what we have we have an issue here all right so here it's a typescript is telling us um it it can't find a declaration file for this package so basically everything has an any type which is not what we want try npm install save Dev types reacts vertical timeline components so often with third-party libraries they may not include all of the types or sometimes even no types at all so there isn't there is a general project at Types on GitHub which tries to call all of these types for third-party libraries for the most popular third-party libraries and then we can just use that so let's actually do that so I'm going to copy this and I'm going to open up my terminal window again and we're going to install the types here I'm gonna install it right here okay so now those types are installed and this error now this issue now is gone and so now when we use that component and we pass props for example it's going to be properly typed so we we will not be able to attach Google varnas if we give this component a prop that doesn't exist or is in the wrong format Etc right so then here we can write vertical timeline and a closing tag that's going to be the container you could say and then it's going to have this vertical timeline element so we have an overall container and now each element here is going to be the vertical timeline element right now we want to have data here again right so here we have data we have skills the last one here is experiences data so I added some data again it's just an array of objects with a title location description and also an icon right because if we look here you can see in the middle we have an icon um another date now about this icon what is this weird react create element right so very quickly why did I do it like that well um we have these icons so we have Lu graduation cap so that's a component it's a react component so I could also do this like this in jsx format but when we do this we get an issue here because we are in a DOT TS file not in a DOT TSX file so if you write jsx like jsx in a normal Javascript file is incorrect syntax you're going to get an issue that's what we get here now if I would change this data into Data Dot TSX now the issue is gone so in a TSX file I can write jsx elements components now there's some very subtle differences in it in TSX files and TS files generally speaking it's it's good to be very precise and try to use just TS TS files so we do want to try keeping this in normal typescript file but in a normal typescript file we cannot write you know a component or an element a jsx element like this so there's another way though that we can write that and that's like this so we can also say react dot create element and this is actually what react is going to do behind the scenes anyway right so if you have a page you're writing here we're rendering our components right so what react is going to do it's going to go through this code here and it's gonna it's gonna do a bunch of react.create element right out of each of these right so we can actually just write this so you can react create element and then pass the name of that component right and then we can keep we can we can uh this can stay a TS file or if you're not using typescript that can stay a normal dot JS file so you don't have to make the jsx file all right so that's the side note right so this is the shape of the data and it's used as const like before right so now what we want to do I'll open this up we want to map over this again so experiences data we want to create an element vertical timeline element for each of these experiences experiences data experiences data dot map and I already got the suggestion here and indeed we do want a vertical timeline element okay so this is going to be a vertical timeline element now we need to import this constant so I'm going to use automatic import like that okay so let's close this out let me make it a little bit wider all right so now we get an issue let's see that's missing the key prop right so here we're mapping so we need to provide a key prop and here you know we can use the index but it's not really the ideal way right because we don't know if this if this component accepts a key prop in the sense that this is a key that you use in a in a in a mapping or in a map like this or if it's actually a key prop for like uh a graphic element okay now we can just use a key actually here and uh we we know that because time scripts helps us out here so it's telling us that attributes that key on this component is going to be react.key so not just not right so this key is not going to be used for like some some output on the page all right so this key prop will not be used as some kind of uh you know element that's going to be rendered on the page it is it's just meant as uh as a part of a loop that being said I don't really like that that we use key on a you know third-party component because we don't know we don't really know the inner workings perfectly fine so I do prefer to wrap this in a react fragment again um react.fragment and just place the key on there right so reacts fragment will not take up any space in the I think this is a bit cleaner right so in this um in these elements then we're gonna have all the data so indeed we're going to have an H3 and here we will have the actual experience or actually let's call that experience item makes a bit more sense let's call it experience item and actually it's called item let's call this item actually a bit shorter so item dot title and then we're going to have a paragraph with item dot location actually and then we're going to have another paragraph with item description okay so we need to add this because now we're not going to see anything right let me close out of here so now we're not going to see anything because we haven't added this to the page yes let's go to our page our home page and here we're just gonna have uh experience and we need to import that controls spacebar press tab save the file let's see what we get and let's see we don't see anything yet and we got an issue so we cannot read properties of undefined so this is a strange error but we know that something would react vertical timeline so my guess is that it has to do with server and client components because this needs to be a client component and most likely because this this library is using some client-side features right for example it's using um right for example it's using an intersection Observer itself internally just like we've used it actually but it's that component itself is also using it because it's animating here as we scroll uh the component into view so most likely this component is using some client-side features internally so we need to make this a client component so let's try that it's a very difficult error actually to deal with so if I didn't know about this use client I would have been totally lost but yeah you can see that is that was indeed the issue right so now if we go down here we can see we have a timeline timeline now it's not really styled nicely right so let's quickly add some Styles here now unfortunately we cannot use Tailwind here right so some of these third-party components they don't have Tailwind support so you cannot just use class name and then you use Tillman classes you have to do it with with the props that they they give you so the props that they give us here for example is content style right so we have to do it like this so we can say background and the background color is going to be a hashtag F3 F4 F6 we don't want to have a box Shadow so we're going to say box Shadow as none and we want to have a very subtle border one pixel solid and then we're going to use rgba for some lower opacity my transparency oops should not miss the uh closing parenthesis there so they have border and then we have text align we want to align the text to the left and we will have some padding of 1.3 RAM and 2 RAM alright that's the content Style if we do that now we have this okay now we also have we also want to have like a little arrow basically like a little pointer so that's called content Arrow style and this is going to be border rights and actually I'm already getting these suggestions now it should be different it should be in Ram so we're going to say 0.4 REM solid and then this hex code all right so if I save here you can see we now have these this pointer but also has a date and we can actually use the date string that we have now we should see some dates yeah all right and then also icon style so we can say icon style and actually let's actually just add the icon itself so we can just say it icon it's going to be item. icon now let's see and now we have these icons and now we can style the icons a little bit better we're just going to add a background of white and a font size of 1.5 Ram right so icons are treated like text so you can size them with font size alright so this looks better all right let's style the uh the text in here a little bit better so this H3 should get font of semi bolts and we will also capitalize everything and then this location oops location should just be font normal and there should not be any margin on the top so here we need to override a third-party style so typically you want to do that with the important role so we can just use exclamation mark in front so it will always win any kind of clash basically alright so make sure you have mastered CSS all right so same here here we also need to override some stuff so here we're going to set margin on the top and override uh the third party style there and also font normal and we also want to de-emphasize the text a little bit so we'll make it 700 and not 950 which is the default all right so now I think this looks a bit cleaner now I ran into one issue with this Library if I inspect here and I go to console I get this error so X extra attributes from the server style at HTML now I had no idea what this was about until I inspected the elements Tab and I saw here HTML style is dash dash line color so this line this um this library is adding a CSS variable to the HTML element now and there's probably going to be an issue with server versus client component so on the server it doesn't have this style and then on the client side it actually has this style so the the HTML structure is different on client versus server that's my best guess here and actually we are very it's very easy to solve that actually so we can actually just go to Vertical timeline here and we can set the line color ourselves to just an empty uh an empty string so it doesn't it doesn't cause any issues now we do want to have a line in the middle so we do want to set that line color and we're actually just going to set ourselves in our globals.css file which we haven't used so far right so if we go to the globals file in the app directory here on the HTML elements we can set our own line color and we can just set that to E5 e7eb okay let's see if we get a line and we get a line right and let's also see if the animation works as we scroll this into view right we don't do that ourselves that's coming from the library so let's scroll down and see yeah so very cool as we scroll down we get those uh very cool intro animations right and it goes without saying you can of course go into the data file and you can just change anything here right and it will work the exact same right so you can just change this to whatever your own data is now you can also add more and it will automatically add more and Alternate between the position as well all right so we're almost finished there we're getting to the last section now the contact Section all right so uh we're almost finished here we're getting to the last section now which is the contact Section so we'll have a heading we'll have some text here and a simple form okay so let me close out of everything here and let's create that components we'll say contact dot TSX RFC and there will be contacts and we'll use another section here section let's add the ID contact and actually let's double check whether the experiences works yeah how that works and actually it's uh scrolling a bit too far right so here let's quickly add that to experience as well so here we can add some styles to the section so we don't want it to scroll so close so we can say scroll mt28 and we'll also add some margin on the bottom so we'll say mb28 and then for wider viewports mb4d let's say okay so uh what we can now also do by the way is we can remove this height on the HTML element or body element so we can close out of here let's go to the layout folder so we added some height here so we could see the scrolling but now we have we have enough content so we can remove this right so we can remove this height from the body so let's remove that all right so now it's it's the height is determined from the content on the page okay so here in the content section we're gonna have another section heading action heading and this time it will be contact me okay and Below there will have some text let's take a look please contact me directly at your email or through this form now when the person clicks on this it should actually open up their default email client so we can say please contact me directly at and we'll have I will use example gmail.com feel free to replace it with your own email or through this form now to have it open up the default email client that the user has on their computer it needs to be an anchor tag actually so I'm going to wrap this email in an anchor tag and then we're gonna say well for styling let's quickly add an underline and then we need to use href and in the href here we can use mail tool and then the actual email that it should open uh the email client with through email client will be opened and then it will automatically you know put it in the view of sending an email to the following email address right so make sure it it's the same because that makes the only that basically makes the it makes the only sense because only that makes sense okay then below there we're gonna have a form and actually just let me just add some space here so then we have a form and forms have uh some innovation in next.js so we'll see how that works these days so we're gonna have an input so just a normal input and then we'll have another input but a text area so an HTML if you have a single line it's better to use input but if you have multiple line inputs it's better to use the text area tag so here we'll use input self-closing we'll make it a type of email and then we'll have the text area okay and we'll also have a button of type oops of type submit submit and this button will say submit now we want to give this a icon as well so when you hover it it has a cool uh like sort of flying away animation or transition so here we'll have a icon it will be a react component f a paper plane so here it already suggested for me all right so I'm Gonna Save here and let's add this to the page so it's not the last one because we're gonna have a footer after this uh but that's almost it's pretty much the last major section here so we'll add contacts here and we'll import it as well all right so now let's add it to the page let's see if we can see something and no we don't see anything and now we see something yeah okay so let's style this section A little bit so we'll give it some margin on the bottom because we're going to have a footer after this as well so it should be some space and we'll say and for responsiveness so maybe more advanced CSS trick so what we want in a wider view it should be the form should be this width right now what we want is that if the viewport is smaller or gets smaller if you look at the form it should stay this with this width but if there is not enough space for that width it should just become progressively smaller like this so basically it should be a hundred percent width instead and so here it's going to be a fixed width but then as soon as the viewport is smaller than that fixed width it should become a hundred percent right so that's a really nice responsive so we can actually very easily do that usually do that with CSS or with Tailwind so here we can set a width on the overall section and the form will just take up whatever the width is of this so here we it's going to be a custom value so we have to use Chrome brackets that's going to be a minimum function actually so in CSS you have Min and also Max and let me make this a little bit wider so the second value is going to be that fixed value right so an actual absolute value so 38 RAM and then the other value is going to be a hundred percent so basically what we're saying here with Min is pick the small dollar of these so on a very wide viewport you know I have a I have a I'm gonna on my computer I'm gonna have a viewport that's like 1920 pixels uh wide which is more than this one than this value so on a wider viewport it's just going to be this 38 Ram but as soon as the viewport gets smaller than 38 Ram 100 is less than that so 100 will be the new width right so this is a a nice way of creating a responsive components and sections it's more more of an advanced CSS trick but very powerful right so we don't even need to use any media queries all right let's continue styling this um let's style the paragraph here we have text Gray 700 which should be de-emphasized a little bit and then let's time the form the form should get margin on the top of 10. okay and then the inputs let's see input should get a height of 14 h14 we're gonna make it we're gonna give it a border radius a very subtle border border border black and then we'll give it an opacity of 10. okay all right now we've used this border black 10 opacity quite a few times and until wind there's a way to make that a little bit more uh dry and don't repeat yourself so what we can do is we can go to our normal CSS file and we can create a custom class name for this so we can call that border black let's say and here we can add those Dylan classes but you have to use the at apply rule here and here what we can say is border border black 10 right so here we can just use these Tillman classes now here in my CSUS file I get these issues unknown rule at rule until when CSS but this is not an issue right so I get the same issue here but that's not a problem so if we do this and now we can use border black instead of these two classes so here if I type border black and save the file and let's see I think this is the input but we we have to know where the input actually is it could also be the text area so let's style the text area a little bit more and then we'll see so h52 the margin vertically rounded LG yeah and here we want to use the same border so here we can use border black again we'll add some padding for and let's see what we get yeah so now the layout is incorrect but you can see they have a border right so that's working now so let's actually work on the layout let's see you can see by the way this vertical timeline component is automatically responsive as well right so that's pretty cool okay so here in the contact me section we're going to use flexbox so Flex by default we'll put them on the same line horizontally which is not what we want we want to keep this vertical flow so we're going to return it to flex call and by default it will stretch the cross axis as cards on flexbox so this is actually what we want okay let's style the button a little bit more so it will have a height of 3 RAM and a width of 8 Ram the background is going to be gray 900s the text is going to be white we'll make it rounded full for a pill shape we want to remove the outline right so if you focus a button you're going to get an outline we want to have our own outline we have transition all and in there we need to do some layout styling for the text and the icon so we can just use it with flexbox so we can just say Flex we'll make a flex container and the text will actually be treated as a flex item and this component as well by default they're going to sit horizontally on the same line and we could use item Center to Center them vertically and then justify Center to Center them horizontally and for some space we can just use the Gap property all right so then we just need to style the icon here so let's see this is going to be a smaller icon so we'll say text Xs and I think it looks better if the icon next to text is usually a bit de-emphasized so it's easy to just change the opacity we'll also say transition or transition all all right now we also want to have a hover effect for the button right so you can see it becomes bigger the background becomes even darker and the icon moves a little bit now we don't want to do that only when we hover the icon also when I hover this part of the button we want to animate the icon as well and so here we're going to use that group trick again so on the button uh element we can write group and then we can style this when that group is in Hover so group hover so we're going to move it horizontally a little bit so translate x one and also group hover move it vertically up a little bit so negative Translate Y one right so now it sort of Lies away as you hover it and we also want to make this button bigger and we also want to have those Focus Styles as well as the active styles now we have already implemented this before in the intro section so if we go to the intro section we should be able to just copy that so let's see we have contact me here and download CV so here we have a bunch of styles for Focus over active and I propose that we just copy that from here and just paste that here for this button as well now here we also want to change the background color to even darker so he will say in the hover States the BG gray should become 950. okay all right that looks pretty cool also when we click and hold it it's the active pseudo class so really feels like you're clicking something alright so we also need to continue with the input here we need to add a placeholder so here that's the input you can say placeholder and that's just going to be your email and in a text area we also want to have a placeholder and we'll just say your message now the placeholder here is sitting against the edge so let's add some padding horizontally PX4 all right so now we have our input and text areas and by default in the focus State you're going to have this outline but I actually think for these elements it looks good so here I want to keep the outline right all right so then we have some issue with the text here so this is left aligned actually so if we go to this section we do want to make sure that text is centers so here on the sections I'm setting text Center and then there's obviously too much space between the section heading and the text below it and that's because in the section heading we are hard calling margin bottom of eight right so it's always going to have this right now now we could give this a prop right a prop so that we can customize that but it's a bit of a hassle so here we're going to use a bit of a dirty way but it's a bit faster quick and dirty so here we have pleat this one is this this paragraph now what you can do in CSS is you can have negative margins so here if we try negative empty let's say three or so let's see what happens yeah so you can see it actually moves itself upwards right and actually this is not a hack or something whereas DSS actually uh this is the intended Behavior right maybe it should be six five or six both looks good I think yeah so let's keep it at six and now um with right so margin means space between elements so if you have a negative margin it means well less space between elements all right now what we want this is the example as we as this section Scrolls into view we will just have a simple opacity animation so uh let me do it one more time so if I scroll down you can see the opacity nicely fades in right so nothing crazy here just a subtle opacity fade in so we can do that with motion right so let's make this motion dot section oops motion dot section make sure the closing tag is correct too we need to import this and copilot Pro no it doesn't help me out here yeah now it does and we need to make this a client component right because that motion component is going to use some client-side features and then we can just use the typical framework motion props here so we can say initial and now we actually only want opacity so opacity zero and then the end the the um well I want to say animate but what we actually want is while in view so as we get into view it should take the opacity to one and we want to increase the default duration a little bit so we can also say transition well duration should be a little bit longer so we'll say one and we also need to make this work with scrolling into the view and then it should become the active section so we're going to use our custom hook actually and we forgot to do that for X The Experience section as well so let's actually go to the to the skills section the last section that we did that in scales and I will also open up the experience section so this skills section we are we we still use this hook so let's copy this from the skills section and then for the contact Section let's paste that right here now here it should become contact right so not skills and we need to import this hook as well and we need to attach the ref to this element here that's a ref is ref RS for the contacts now of course we need to do the same for the experience section right so here instead of contacts it should become experience and we need to import the hook and we need to attach it so say ref is ref all right so that's actually uh let's actually see if everything work because now we also added the animation for the contact Section so I'm just going to refresh the page and let's pay attention to the header for the experience section we will have skills and then we'll have experience yeah so experience also works and now let's check the contacts section uh what works in the header here yeah and let's see yeah so the animation is also working so it's doing it every time it's it goes into view so let's uh let's just do that one time so I'm going to close this one let's actually make that just a one-time uh thing so we'll say viewport is once is true all right so now here that's once and it's still doing that so let me refresh here to double check now scroll down it Scrolls it's it fades in because this is the one time and now I go back and it doesn't fade in anymore right so now that's working properly all right now before we implement the actual functionality of this form I want to focus on one other thing that we should fix so if we click on this contact me here button it will take us to this section here but if you look at the header it's going to jump between all of those sections again right it's a problem that we had before as well so previously we solved that by so if you click here in the header and projects for example it will sort of um disable that scroll based active section uh for like one second right so we need to go to the intro section and here when we click on this contacts button Let's see we will add an on click uh Handler so we'll say on click and we will do this in line here we'll just uh run a function so we need to set the active section so just like a click here in the header and actually we can look at the example here so in the of the example being the header so here in the header if you click on any of these links what are we doing we are doing set active section and set time of last click right so we just need to do the same thing because it's the same functionality so here we can say set active section and now it actually needs to be the contact right so this is going to be the click on this that the contact should become the active section and then also set time of last click will be just uh This Moment now we need we need to get these from somewhere so where do we get these functions from here in the header so we got them from the use active section context hook now we also created our own custom hook now we also created another our own custom hook in the hooks file right so but that one is not returning it's only returning a ref right so that's not returning that's active section let's set active section and uh set time of last click and so on although we could make it return that but um we also have this other Hook from our contacts which just gives us everything that we need anyway so let's not complicate the other hook and just use this uh this hook as well we can just uh we could just use that here so we'll say uh use active section context importing that automatically and we want to actually we want to destructure those two functions from there so so set active suction section and set time of last click right so now this should not be an issue anymore so if I go back to that button yeah the rest quicklys are gone and now when we click here we don't see that jumping between uh sections here right so now here if I click doesn't it just goes immediately to that part right and this is the benefit of having uh you know clean count it's very easy to tack on additional functionality or if you need to if you need to do something similar in a different part of the app it's very easy to um customize it even further right so this is really important that you have clean codes well structured codes and uh you can see how easy it was to solve this issue all right so one other thing we should also do now is we used this at apply rule in our globals.css file right so let's apply border border black so we actually have some other instances where we can use this class so if we just search our code base here we can actually check where we have this other sequence of classes as well so if I just search for border and then border Dash black I can already see here in the intro file that we have the exact same here so let's replace that here by border black all right I'm going to copy this class border black and then I have some other instance here yeah so here we can also replace this with just one class border black and here we have another one border black and here we have border black but it's five percent opacity not ten percent now maybe we maybe in the future it will be possible to turn that into a function so you can sort of give an actual number as an input but for now we'll leave this leave this here so then let's see what else so here in the scales section uh okay so here we did it with a custom value so we can also just replace this which is because it's the exact same thing so now if I go back and let's double check everything on the page so here we installed those borders and this these cards still have their border these skills as well so everything still has a border and so everything is working now all right so now let's make the contact form actually work and what we want is of course that we actually receive a message in our own email inbox so first we also need to think about uh validation so we want to make sure that the user for example in this input actually inputs an email and not some gibberish right and maybe also have like a maximum length and so on so typically with any form you want client-side validation but then also when it gets submitted to the back end you want to validate the data again because people here in the browser they can bypass the client-side validation right technically so typically you want to do the validation for sure on the back end but here we can also easily add some validation on the on the front end we're just going to keep it relatively simple we can go to our contact form here and what you can do is you can just use the native HTML5 validation here so here for example we've said that this input is a type of email all and we can also say required now so there's a required property here now you can specifically say to true but in jsx if you just say required it will automatically make that required is true so we can also set a maximum length of let's say 500 that's at most 500 characters and let's do the same for the text area now this is just the HTML5 form validation it's a very quick and easy way of adding some validation to your forms on the client side only okay so now we have some validation so let's actually try and see what happens if we don't do the correct format so if I just write some gibberish here and here I mean here we don't really have anything except maximum length let's say I don't fill this out that's required that's enough I try to submit this we get this warning and also with the text area so if I fill something out here in the inputs here in text area it's emptiness there are no spaces or anything else empty so neither admit this it will also say well it's required so you have to fill out the fields right so very simple HTML5 native validation of course you can customize it if you don't like how does you know warning messages look you want to make a different you know there's ways of customizing that but that's beyond the scope of this project okay so let's actually fill out an actual message so now we have you know we have inputs here that conform to this validation so now if I click submit how do we get access to these file what will actually happen and this is actually pretty cool this is new and next js13 but on a form what we can do here is we can type action and maybe you've maybe you already know about the action attributes on forms right so in in plain HTML what used to happen is that you would submit the form like this right so you would pass some URL here and then on submitting the form the browser would send the data to this address and for a long time in react we did not really use that so instead you would do something like on submit and you had some kind of submit handle submit right and then you would handle submit and you would extract the values from there and that you can still do that but what's going to happen is there's a new feature in xjs called server actions and these are basically going to take over that whole flow of data when you deal with forms and also other instances where you want to submit data to the server or you want to do anything on the server so it's called server actions it's currently in Alpha as I'm recording this video and if you are have installed the exact same nxts version as me it's also going to be in Alpha but it's probably going to work very close to this in the end when it's stable so we can actually already use this and there are already people that have that are using this in their apps so what we can do is we can say action instead of having like a string we can actually provide a function and and next.js will actually give us access to the form data as that's going to be the input right so it's going to be a function here and we can actually just log what we get so we because I form data as let's actually see what we get so if I save here and this is not something you can do in HTML right plain HTML this will not work that's the action attribute exists in plain HTML but if you try passing a function like this you're not going to get this is going to give an error and also on plane react by the way but if you try to do this outside next.js you can also not do this right so this only works in next.js this is actually also works something similar also works in remix this is basically the answer of next to us to what remix is doing with the action attributes in the form um so maybe you've you've worked with remix a little bit you know a little bit about that so let's go into the console here let's see what we get and we get an invalid value here so it needs to be in async actually an async function and such it can be a plain function needs to be asynchronous let's try that again and I'm going to refresh all right so if you try that you will get an error so the error will say something like invalid value for prop action right so you can actually pass a function it only works in xjs but but also what you have to do next year is for now is you have to go to your next config file and you have to hook into this so you have to say experimental server actions is true let's make sure you add this to the next config file and when I change this file sometimes the dev server May uh yeah the dash over here shuts down for me so I have to restart here npm run Dev so make sure the server is running I'm going to close the config file here and now we're gonna see if this works so I'm gonna refresh here we'll wait until the dev server has has started again alright so now my Dash server has started again and there's no error anymore so now let's try to submit something here so we can say at the gmail.com hello world now I'm gonna try to submit this let's see what we get and we actually get something called form data and it looks like an empty object that's how it's always presented here in the console but this form data is basically um it's not from next.js it's just a general data structure that you deal with with forms and it makes it a bit easier to deal with the data from the form now to actually properly deal with the data you usually also want to give your inputs a name so that you can refer to that when you deal with the form data so let's give this a name of sender email and let's give this a name of just a message search right and then the idea is that here with form data you could you can't just do from data.center email right so it's not just a normal JavaScript object you have to do form data.get and then for example sender email and I'm going to hold shift alt down arrow key and duplicate this line so we can also check the message field alright so now I'm Gonna Save here and let's go back and now let's try to submit this again so it still has this here in the form now I'm gonna try this there's some other warm in here we can ignore that for now now I'm going to try to submit this and you can see I get T at gmail.com and hello world so I can now access these values here within the action attribute as this is new this is not something you could do before now all of this is still running on the client side by the way right so we haven't actually implemented a server action as it's called yet all right so now let's actually Implement a server action so what you can do we can scroll up here and then here within the component what we can actually do is we can create a function we can call that a send email because we actually want to send an email right and that's going to be an asynchronous function that's going to take in that form data right so we're going to pass the form data here and let's actually log this so let's log from data.getcenter email I'm going to hold shift alt and down arrow key because we also want to log the message and this is going to run on the server right so very important what we need to do here is in the function here we need to add use server and so this is going to be running on the server only now we got an issue here for typescript texture wants to know what type of data this is going to be well this is going to be of type form data which is uh this interface that we can just use okay so now we have these console log so we can actually log here running on server right this is going to run on the server and we're defining that here we can do that now so we can even have access to any variables outside here in the in a client component but it was only going to run on the server but it will take some time to wrap your mind around this so that should bear with me so now we have that sent email server action and we can still log here um running on client and that's actually also add that interface here actually I think it can already deduce it yeah it already infers that this is going to be of typeform data because it's in the context of this form action here so we don't have to specify it here here when you do when you extract the function we lose that context or typescript loses that context so you have to provide the type or interface yourself okay so this will run on the client right and now we want to use the send email server action so we can call that and we're going to pass the form data now that's an as an async function so what we want to do is we want to put a weight in front of it but then this also needs to become an async function right so it's really important that you have Master JavaScript right so uh highly recommend you uh check out the links in the description there's async await promises you really need to have it have a deep Mastery of that okay so here we are just awaiting this so now let's see what we get actually I see some errors let's see what we get okay so with this server action we cannot do this in a client component so here you can see that at the top it's gonna it's a client component so we cannot do this if this was a server component we can do this right so we can access variables outside of the function here but in a client component we cannot do this so what we may what we what we're going to do is we're going to create a separate folder here for these server actions I'll just call that actions and then the one that we're going to put here is called set email.ts right so let's actually copy this this function and let's put that here in a separate file and instead of putting U server in the function here what you can also do is just put it at the top of the file and all the functions in there will be server functions right so we'll only run on the server right so we have extracted this to a separate file in the actions folder so now we need to import that here because we're still we're still using that here right so we still need to import that especially if we can do it automatically yeah so I'm just going to hold Ctrl spacebar press Tab and that didn't import it for me so I have to import this manually and let's see it gives me a suggestion no it shouldn't be ad-lib it should be at actions send email okay and why is that not working we are not exporting it right so we need to export this make sure you export this and now it should work right so now we're importing send email from sent email which is a server action it's going to run only in the server because we have used server here in the in the file right so we can run a server action in a client component but we just cannot Define this in here right so we have to uh put that separately okay so here on the form um we have one piece running on the client so whatever you see here is still going to run on the clients but then as soon as we call that function this is going to run on the server right so we don't have to we don't have to create a whole separate API you know work with graphql or anything like that next.js is going to take care of this forearms behind the scenes right so this is really a big simplification of the flow from or between server and clients um so I'm Gonna Save here and let's see what we get all right so now I'm gonna go down here I have my console open in the browser that's the client side I'm gonna hold my console open here in the terminal here there were some errors but uh now that's gone so now we're gonna see what happens I'm gonna say t gmail.com hello world so now let's see if I click submit what's gonna happen so what we see is here we see running on client so the form here let's see the form this is running on the client right running on client we have access to the data on the client of course and then we have send email which is running on server so here we have a running on server and we also have access to this data now right and we don't even need to construct like a separate API or route or anything like that next.js automatically takes care of this for us so you so how's that possible how can it go from client to a server well you can actually inspect the network Tab and here you you'll see an actual fetch request being made we have not we are not fetching ourselves manually but this is what nextgs is doing for us behind the scenes and it's bad crashing along this as a payload that's passing along that form data right so it's going to say something like sender email and message it probably uses some kind of identification to know where the data is coming from and to which form it's connected and so on um so that's actually taken care of for us right so now we can deal with the form that we can remove this because we don't really actually want to access these properties here on the clients we are already doing validation here so no point in accessing it here what you can even do by the way is just put sent email like this right so you can even do this if I save here look how short this is on the client we don't have to write any you know fetch on submit just one server action this is what we want to do and we want to execute this on the server so now if I do this I submit again let's see I get another log here so this also works how cool is that it really simplifies a lot of things now the downside of doing this is we have to think about error handling because we're gonna send an email we'll talk about that in a second with recent and react email but that could also go wrong so you also need to be able to Output some error message here and I found that here if you try to do it like this with just passing the server action name it becomes a bit more difficult so you do want to have some logic additional logic here to deal with possible errors so we can say for example uh email field to send try again or some specific error message so here we do want to have a uh some data here so we can pass a function here that takes from data as an input we can send that email right we will still keep this and this is async so we're going to make this a ways and async and we'll deal with the errors later once we are actually sending the email so let's so now let's actually talk about sending the email right so what we're going to do is we're going to call send email this function here now in here we actually want to send an email right so now we need to use a third party to actually send the email and the third party that we're going to use is called resent and they are actually the same the founders are this is the same team as react email which is a popular library to make your emails look good but this is for styling emails this is for actually sending emails right so let's actually start with just sending it and we'll make it look good later so we do need an account for this right so I have already created an account if you haven't created an account here you can create one here so I'm quickly gonna log in alright so I have logged in and I see this over a few dashboards now what we need is an eight we need the API keys so we're going to install the packages and then we need one of the API Keys now I've already played around with this a little bit so I'm gonna have some more keys here I'm going to create a new API key and you can give that a name I won't give it a name full permission all domains okay I have to actually give it a name tutorial for tutorial or tutorial okay so I have to copy this key and I'm gonna paste it here for now be careful with these keys I'm showing it on video I will remove it after recording this is not typically what you want to have in your code base right so what we're going to do do is I just copied it here and typically what you want to do with these API Keys is you want to put them in your environment variable so next.js helps us out here we can very easily create a file here.env.local and here we can we can say this is going to be for recent we can say recent API key and then the actual value here so I'm going to copy this remove it from here and paste that here right so you don't you don't need quotation marks here in the environment variable file here right also no spaces necessary so we can just write it like this and now this file will not be included when we we will push it to GitHub at some points but if you look at git ignore you can see that it's not it's going to ignore the dozenfeed.local file right so this will not be uh this will not be you know publicly available on GitHub right so make sure you put it in an environment variable it also means that we have to go into for sale when we host that we don't have to put this in the for sale hosting platform as well right but we'll see how that works alright so now we know how to access that API key now we need to actually download the recent package right so I'm gonna open a new terminal here and we're going to say npm install and recent actually has been changing something so here we need a specific version so we're all in the same version so we will say 0.16.0 so I'm gonna install this okay so now we have the recent package I can close this now we need to import it here so import recent from not types just recent and then we need to instantiate a uh an object here with this recent Constructor so what it looks like is we're just gonna we're just gonna say cons resent and it's going to be an instantiation here the only thing we have to pass here is that environment variable that we just created so to access those variables we can use process.env dot resend API key like make sure you have the exact same name as a as a newer.infill.local file so now we can use this recent variable to send an email so what we can do here for example is we can say resent dot emails dot send and then in here we have to pass an object where do we want to send it to and from where so we can say from now here we are going to send it from the from the recent uh server or domain right so they actually provide like a default domain that we can use to test make sure you don't spam because you're going to get blocked but they use this reset.dev domain and we can just use that to send an email to us or to anybody actually but you don't want to spam because you're going to get blocked so here we can say where should it be sent to so I will use this I will use my own email address here and this should be your own email address and then the subject of the email we can say subject we can just say message from contact form and then what we can do is we can say text and we will just have some text hello hello world all right so here let's just keep it like this let's just see if this works right so um we have this form this form is going to invoke This Server action send email which we'll call this funk method here from recent to actually send an email so let's see if that actually works so I still have this text here so I can simply click again and now let's go to your email right if you're using and I can see right if you're using uh your own email I can see now that I have received an email hello world right so of course as coming from the at recent.dev domain and you can you can connect your own domain it's a bit outside the scope of this project people can actually fill out a contact form it will actually be sent to your email and of course we are hardcoding hello world here it should be the message right so here let's actually log this but actually assign it to a variable so we can say in the message is going to be form data dot get and then the message right so make sure this message means the name right so we've given this text area a name right so that's how we access it now and we also have a the sender email right so here the recruiter may leave their own email actually they have to because it's required and this field here and we can access that here send our email form data dot get email and so now we don't want to hard code this text here it should just be whatever the message is right so you can say message and now we get an issue because here it says form data entry or null so this message could technically be null according to typescript even though we have specified that it's required but it's coming from this form data.get method right so here we're saying form data entry value or null so this method has just that's how it's typed and typescript is just using that so it's a touchscript sometimes not as smart as we think it is so here we can just check it ourselves right so if we we have to do some server size validation as well so here we can just check right so if uh if the message doesn't exist if it's null we want to return an error object let's say so we'll we'll just return an object with error in fallot message right so the cool thing is whatever we return here from a server action we will be able to access that here so this makes it easier to do with errors it's basically like an API route right so uh but just without actually creating the the boilerplate for the API okay so now let's see now we know it's not going to be null right so now let's see why is this still not working so now it says form data entry value it's not assignable so it needs to be a string or undefined now it's the problem here is that this build of the form could also be like a file so form data entry value could also be a file right we know we know it's not going to be a file but technically it's possible right so here we can add some additional validation so we want to return an error on objects with an error message if it doesn't exist or if it's like a file right so touchscript at least is smart enough to know that once we check for this we know after that it's not it's not going to be null right so we just solve the null case now we have to solve the font the the situation where it could be a file type file so here we're just going to check is this message of type string so if type we can use in JavaScript we can say type off message if that is not a string then we also want to return this object with an error message right and we will deal with the error message in here later right but you can see now that typescript issue is gone right so now once we pass this if block we it's a saver now because now we know it's not going to be null it's not going to be anything else but a string so it's actually going to be a string and we actually want to do the same for sender email but we're not using sender email right now so where would we use that well we could actually put that here in the message so we could say something like uh the person who sent this message hasn't emailed this one now what you can also do because in my message it would be nice if you could hit reply and immediately send it to that person right so whatever email they put in here I wouldn't be able to reply and just send the email to them but now it's not possible because it's gonna be sent to this recent domain but what you can add here is a reply to field so reply to and that's going to be that sender email right so now we'll see that you can hit reply and it will be actually sending a new email to whatever the email is that the user filled out all right so here we're gonna get the same issue where form data entry or null so what it means is reply 2 needs to be let's see type no it's not assignable so this needs to be a type of string or an array of strings or indefined right but sender email could potentially be null we know it's not going to be null because we make it required here although technically you know people can circumvent that on the client but you know it's safe enough here to assume it's not going to be null but um let's also take care of some Foundation here on the server side so let's also take care of some validation here on the server side so here at this point it's better to just extract this into a separate function with the utility function that can validate these inputs so let's create a a helper function and we can just call that validate string that's just some simple server size validation and that's just going to take in a what we think is going to be a string right so that may take in some data from the form some value right and what type is it going to be well we think it's going to be a string but we don't know for sure so there's another type in in typescript called unknown technically we don't know for sure yet as it could technically be something else so then we can just um we can remove this and put that in there right and instead of message they should become value right and instead of saying invalid message um we're just going to return true or false so here if so here this function will return false right so it's not validated properly if it doesn't pass this test and otherwise it will return true right in dash script sometimes you also want to annotate the return value of a function but it already infers it's going to be a Boolean not either true or false okay so now we can see we have the same issue again because we are not using this yet so now what we want to do is for every field basically we're going to we're going to validate it first with this helper function so we can check if um if if if we get files back so if it's not validated so if not validate string and we need to pass let's say the sender email let's start there sender email so we're going to pass the sender email I need to have another parenthesis here we're going to pass the sender email to this validate string function so it's just going to check is that is it does it actually exist is it actually a string in that case we'll return true right if it's not if it's not a string or if it doesn't exist we're going to return false right so here then we can return an error like before right an object with an error field error property with the message invalid message right so this is just doing and actually this is not inval message this is invalid sender email right and now we can do the same for the message so we can check if uh well copon helps us out here here we want to return an error with invalid message right I just have to tap through because it's very systematic so it's easy for copilot as a message we'll go through this test as well okay so this is basically going to be our server side validation so just on simple server size validation now there's one other thing that we are checking on the client on the client we have some validation here and it's required so it's not null right basically and since we say type is email that will also only we can only submit it if it's actually an email so if I try to submit this without and add we get that issue right so we are basically doing the same on the client side now here we are also checking for the length we're not checking if this is maybe infinite length or that's a huge number that's going to crash our server or database so here we also want to have a check for the length so when we validate this we also want to pass in like a maximum that this sender email should be right or maybe even a minimum we can also do that but let's keep it a bit simple let's say we want to be able to also pass like 500 here for the sender email and then here and then here for actually the text area let's make this actually much bigger let's make that five thousand makes more it makes more sense that this text area message should have more than the email field right so let's actually make this 500 and here we want to pass in 5 000. now we're going to get an issue because this helper function right now doesn't accept a maximum yet right so now we need to say a second parameter here we'll call that max length and that should be of type number which we can then check here so we want to return files if the value doesn't exist or it's not a string or or if it's more than that max length so we can say value.length if that is more than this maximum we also want to return false right so we have extracted a helper function here just for some cleaner costs so now in the action you can see it's much cleaner than if we would have to copy and paste this um like this in here so we have extracted the helper function now typically in a serious application you're going to have multiple helper functions like this because we can also use this somewhere else so we can have multiple server actions maybe not only send email but also we're going to have another form with where the user can submit other data right and there we may also want to validate a string so typically in the library folder we're going to have some utilities or helper function you can call that utils or utilities or helper functions we'll just call it utils.ts and then we're going to put these helper functions in there so I'm going to copy this validate string helper function I'm going to put that right here right so then we want to use it in another file so we have to export this it's going to be a so-called named export so then we have to import it here but we have to use the curly braces so we can say validate string and this is not the correct path it needs to be at forwards flash is going to be the root go and then go into the lip into the lib folder and then we have utils right so that still works but now the file is a bit cleaner and we can easily use this in other files as well like like other server actions all right so this was a bit a bunch of typing here and now we get an issue here so why do we still have this issue all right now when we do all of this we know it's going to be the correct format so it's not going to be null Etc but typescript doesn't pick that up here right so sometimes touchscreen just doesn't pick it up and so it still thinks that this could be null so here we can assert basically that we know better than typescript so we can add as string we know it's gonna we know it's going to be a string at this point right so here's for the message as well we can just add a string and basically assert here that it's going to be a string these two right because we are checking it's not going to be null right because then we would return files here and we would return this we wouldn't even get to here so we cannot get here if it's if it doesn't exist if it's no so we know it's not going to be no we also know it's going to be a string because if it's not a string it will return false and we also know it's going to be within that it's going to be less than at maximum length so we can be confident enough to assert that these are going to be strings all right so what we're passing now is the text that's going to be the actual message that we fill out in the form and also this reply to email so let's actually double check this so we'll say test at Gmail and I will say hello world actually let's uh give it a different text message now new message so I will just write this and now I'm going to click submit and I'm going to check my email block all right now I didn't receive the email so I waited some time and this is still the old one so I didn't receive it so something went wrong here now if we look here this actually needs to be awaited so we need to put a weight in front of this here make sure you also have this marked as async and then it still won't work so what we need to do anyway is we need to deal with errors it doesn't work so we need to know what the error is right so here we can wrap this in a try catch block so I'm going to put everything in try catch so then if this this send a method throws an error we can catch that error so we can see what's going on so we can say catch the error and then just like here we can return an object with an error and we want to see what the error is so we ideally could do arrow.message right so if sent the recent throws an error we catch it here and we want to get its message now typescript is going to complain because if we hover this error is of type unknown right so this Arrow here that we get is basically a type unknown which actually makes a lot of sense because technically this you can throw anything in JavaScript right so you can throw you can throw the number five right you can throw that so technically descent method could throw the number five so we catch five here and then we try to do five Dot message but message message doesn't exist on the number five right so you can throw a new error in JavaScript new error test error and now you can actually get message but this will give us an object with a message property but we don't know if they actually if they actually throw something that was created with new error right now they may actually also just throw a normal JavaScript object with error or message and so we don't really know what they throw if something goes wrong but let's just log this to see what we get and I'm going to open up the terminal here and now I'm going to send another email to check if if to check the error if it still doesn't work but I'll just say test at gmail blah blah and then I'm gonna press tab press enter to send the email and let's see I don't see anything in the terminal here so then I'm going to open up the browser inspect tools if I do this again I'm going to submit again now I can see this uh fetch here and let's see we have payload to the pillow at least it's working right so at least it can capture the data from the form and we actually get a response here and it says something like error invalid sender email ah okay so we don't even we don't even get to this try catch block because we are for some reason it's not valid it's the the sender email is not validated properly so that's interesting so founder date string we pass the sender email and I don't see any obvious errors that we made here so it's going to be a string right so it should return true here but apparently it's returning this object here right error invalid sender email so it's returned it's giving us this error and that's interesting so let's actually see what we get here on the server side or sender email I'm going to open up terminal because this is going to be unlocked here in the terminal I'm going to click again and we get null actually that's interesting and obviously it's because this is not the correct name right very uh yeah sender email is the name here so very silly mistake sender email should be the name as it needs to be the exact name here as what you put in the form right name a sender email right so what we had before was just email but there's no uh there's no form control here with the name email and there's type email but not name emails sender email but this needs to be sender email okay so now all of this should work I'm gonna close here close out of here and now I'm gonna click on submit again and I'm gonna check my inbox and now we get message from contact form blah blah which is indeed the message right if we now click here you can see reply to is test gmail.com so if I now click on reply it will actually send that email to that uh email address that the user filled out right now it's also a bit ugly here this onboarding and actually in the API docs they give you a way to make that look a little bit better so to include a friendly name use the format your name and then with angled brackets so let's do that let's try that so here we can say from um well this needs to be an angled bracket the email and then what we can put here is the actual the more better looking name so here we can use something like contact form let's put it like that all right I'm going to save here and let me just gonna send the same email again to check that submit and let's see I've got another name yeah so now we see contacts contact contact form here so it looks a little bit better I think that's as nice you can read about the the docs here there's other ways to customize it and customize things but we have a pretty simple form we don't really need a lot of customization there there was a bit of work so now we have the validation with doing that properly um but let's think a little bit more about errors because there could be other things going on wrong but we also may have a typo in the domain that's instead of recenter death we may have resend.com right so if I try doing this and if I now try to send this message click submit now we actually get an error right so now this set method will throw one of those things we don't know exactly what they're going to throw that's a third party Library they could throw anything we don't know that so here we catch whatever they're throwing and we're just logging that and we can see it's an object with name message and Status cards right so it's saying something about the reason.com domain is not verified okay so let's take this error handling to a professional level so I'm going to fix this and what what do we want to do when we catch one of these errors because here's just a city you know contrived example but in the real world you know some the third party Library could have could have an issue right maybe their email servers aren't working right so we still want to output something to the client then right so here we're still in the server we want to return basically in the same format here also an object with an error property with a message so here if there is an error we do want to return something here so we want to return an object to the client and we want to say error and instead of hard coding this we actually want to get this message we want to get some kind of message that's the third party library has given to us so we want to say arrow.message and when we do that typescript will complain because again this error could be of any could be could actually be any type now in typescript we have we have oops we have any and this will get rid of the error but this is basically a escape and escape hatch so this is not really what we want to do in time scripts so with any what you're basically saying is anything goes you can do whatever you want with this error basically make all the errors disappear well that's not really why we even use typescript if we do that the more the more precise type is actually a noun we don't know what this is going to be so you cannot just access that message on there because it could be a number right and on a number you cannot access that message all right so here you know error handling is not the most exciting topic but it's part of being a professional developer we also discussed this in my JavaScript course also in the context of these try catch blocks so let's see we can just do a bunch of if statements so we can check if we can check if it actually has a message property and so we can check if this error if this actually is an instance of error so in JavaScript we have this error Constructor new error my message if you do this you will get an error object with message property right so we can check if whatever this third parties whatever whatever it is through is an action instance of that error Constructor well in that case yeah we can just use error.message right that's not a problem and we actually saw that they give us an error we actually saw that they give us an object um I'm not sure if I can still find it but it was somewhere here it was actually an objects now that was actually not an object that wasn't actually specifically an instance of error that was just you know they just they just they just created an object Lateral with message and Status cards right that was it wasn't created with new error so now it's not gonna go it's not gonna return that because you're only checking for if it's actually an instance of the error Constructor so here we can also check else if the error what whatever whatever is thrown if it's if it's actually uh if the type of this is actually an object right strictly equal to object and it has that message in that object so you can run it like this you can check if the message property name is in the error right so you can use you can write it like this and now we get an issue because it's saying that error could also be null you cannot check if something is in null so initially here what we can also check if the error is even existing so if error exists and the type of that error is an object and there is a message in that object then we can also return error.message right we touch kit won't give us an issue here because we know now it's going to be an object with a message property now this is getting quite uh you know you can already sense here because now what we also want to do is what if the what if they're not throwing an object maybe they're actually throwing a string maybe they're actually just throwing the message itself maybe just throwing that and now we're not we're not dealing with that here right because that's not going to be an instance of error it's not going to be an object so now we're just losing that so now we have another else we can check if it's a string and just use that as the message so here at this point it's probably best that we extract this into a helper function right because we're gonna have to deal with errors and other server actions and throughout our application as well might as well extract this into a separate function so what we want to be able to do we're going to put all this stuff in a separate function and ultimately we just want to get the message basically so here we're just going to return an objects and what we want to do here is we want to call a function let's call it get error message and just pass that error and that and that function will then just figure out what the message is so let's copy all of this and remove that from here this is much cleaner now and we're going to extract this logic out to a helper function here we'll call that get error message that will take in that error and it will extract some message from it so indeed it's going to be an error of type a noun and I copy that so I can paste that here what we had before right so this will just return a message so let's actually let's just create a message here and this should be of type string right so we want to return a message of type string and that's what we're going to return here return message right so this message will then be the error here there will be we'll be hearing this object's error and then that message right so this function should return a string well let's make That explicit here okay so now we don't want to return some objects here we just want to return uh error.message here and so we just extract error.essage or not return we want to assign it to message right so then here we'll say message is error.essage as well all right we got an issue here type a node is not assignable to type string okay so this is really really Advanced so here we're saying if error exists and it's actually an object and it has that message property so for example if they throw an error with well it could just be message but invalid sender email so this in this case we could we could get error.message right now technically they could throw something like this so they could throw an error that exists right another type errors object and message also exists message is an error but then it's actually a number type and here we're saying it should be a string right so if we really this is really uh advanced we can say well we're going to cast that to a string so we can wrap whatever they give us in the string what we get from JavaScript and this will convert whatever that is to a to a string right so this is getting a bit uh Advanced I'm not sure if I should have included that in this tutorial but this is easy to pick up once you've mastered JavaScript itself right so I'll keep hammering on this how important that is and this is this is the real world you need to deal with errors properly all right now what if they throw not an object but for example they throw just a string in a standard email now we're not checking for that here we're only checking for instance of error object and actually if it's just a normal object but we can also check if it's a string so we can also check type of error if that is strictly equal to string then we can just use message is just that error right it's going to be string so we can just use that and else if all of that doesn't give us a message or if if all of that doesn't pass the test of the if block we'll just have a default error here right so then we weren't able to extract it from whatever dates through so here we're just going to say a known error or typically people call this something went wrong and so ultimately this get error message helper function always gives us some message that we can then use here in the catch block and it's nice that we have extracted this into a separate function because now if we have another file another server action you know you have to deal with errors all over the place so you can just reuse this and let's actually put that in the utils file as well so let's copy this and let's put that here in the utilities file and make sure you also export it we're going to export this and then we're going to import this get error message that's not much cleaner and this is much more professional all right so now we have this functionality it works we can send emails to ourselves but it doesn't look so nice so it's just very plain now and typically in you know professional applications if you deal with emails I'm going to close recents here if you do with emails you want to style them as well so very popular library for styling emails is react.email you can start this is a more reactive way basically of styling emails and it Smooths away a lot of issues with starting emails because you can imagine all these email clients like Gmail and Microsoft email and there are some other uh third-party email clients as well they all have different ways of interpreting the email message and they may have issues with styling and this Smooths away a lot of those issues it just makes it much easier to style emails so here we're gonna it's actually by the same people as from the recent the recent service that we just used right so here on the web side they have some examples here right so you know you probably see these um emails as a consumer yourself you probably have some services that that have styled their emails right so it makes it very easy to style emails so the reason we're including this here in our application here because technically you know a simple email may be enough but you know if you want to publish your portfolio online and you know some tech lead that's looking to hire you wants to see how you've coded this portfolio well it would be impressive to show that you are also capable of styling an email it's not that difficult but it's just another feature that we can add here to impress the person that's looking to hire us even more right so let's quickly do that so it actually show you how to do that so if you look at the source of any of these they basically give us a bunch of components and we actually zoom in here a little bit they give us a bunch of components like body it's basically like an HTML file the body and HTML and hat and we can even use Tailwind so then you can just create a react component and we can pass that react component here so instead of passing a text field so plain text instead of doing this I'm going to comment this out what we're going to do is we can actually just pass react and we can actually give a react component and recent will actually uh will actually interpret that properly right so we're going to create the react component now with react email and then we pass it here to resent right so I'm going to comment this out for now so where are we going to create that email so email is also something that typically you want to have a separate folder for so I'm going to create another folder here last one email and in here if you have a bigger application with multiple types of email you can give them a unique name here we'll say contact form email or contact form and let's actually call this email contact form email.tsx RFC contact form email all right so we have this so now we have and we need to get access to these components that react email gives us so we need to install the package so we can say npm install at react email forward slash components and also add react email forward slash Tailwind right because we're going to use Tillman and they even allow that so we can Style with Tillmans if you've ever styled uh if you ever try to style emails you know how much of a hassle that can be and this is going to be much easier now Okay so we've installed this I can close the terminal again now what we want to be able to do of course is this email takes in this uh text here this message and we need to Output this here somewhere so this should take in that message and we will call that message and that's just going to be a string right and actually let's do it the way that we've we've been doing it for react components so we'll say contact form email props we'll Define the type up here to type contact form email prompts message is going to be a string okay all right so then we can use those components from the react email Library so we need to import them let's actually import a bunch of them so we need the actual HTML component body and hats as well hat heading HR or like a horizontal line we will also use container which will Center everything preview section and text and this is coming from let's see it doesn't react it doesn't recognize it so we'll say add react email forward slash components and then we're also going to use Tailwinds right so we can style it till end but we do have to import the Tailwind components here from at react email Talent okay so a bit bit of uh setup here okay so then what we can do is it's basically going to look very similar to just like a an HTML file so we're gonna start off with the HTML here and then we have a hat We're not gonna have anything here now the head can hold things like the title for the email but we are already defining that with subjects here and if you're not sure what some of these components do they have complete documentation and they also show you the support for all these email clients so Outlook from Microsoft Apple email Yahoo email and there are some popular other ones right so it's pretty cool that you can now use this and it will make it look good across all of them but much easier than before all right so let's see we'll have head now we have that preview as well this is basically going to be if we look here for preview email clients have this concept of previewed text so that's basically just going to be a short snippet of text and we could use that but I think we are already doing that here with uh right so we'll just quickly add that here as well so preview we can just say new message from your portfolio site and then we're gonna have body now we want to wrap everything in the body in the Tailwind component so we can use the Tailwind classes we will have body and in the body we want to Center everything so they have the container component for that and they have a way of previewing this by the way so we can spin up another server or they will spin up another server and it will open up a new tab where you can preview this but this is going to be quite straightforward so let's uh let's just quickly type this out or you can just copy it from the GitHub repo if you don't want to type it out so it's going to be the section now in here we're going to have and the heading for this email heading we can say something like you received the following message from the contact form and then the actual text of this email and that should be the actual message so we're gonna pass the message to this component and that's what we're going to Output here and then we also want to have maybe um I'll maybe we want to have a line and maybe we also want to show the sender email here so this message came from the following email or the the sender's email is the following email so we can have some text here again we can say the sender's email is and then the sender email it will also be in the reply to field right reply to but maybe we also want to make it explicit here in the email itself so it's currently not accepting sender email so we have to add that here right so typescript is complaining so sender email will be a string and we have to enter here sender email as well okay okay so now we have our email component my bit of boiled plans here make sure you export this now what we can do is when here we can import that we can import this email so I will say contact form email it already suggested for me and now we can do is we can pass that here as as a component oops I can pass this here as a uh as a jsx component so I can and then we have to pass that as props right so here we can say it needs to get message and send her email so now we can remove this text fields and we can just pass the message right it's going to be message is what we have here message and sender email right message is message send your email is under email all right that's basically what we can do now which is pretty cool now we get an issue here obviously what's the issue and the issue is here we're using jsx in a normal typescript file or you can also see it as jsx using in a DOT JS file you'll get the same issue right so we've we've seen this issue before so the Quick Fix here is to make this a TSX file and so if I do this we are allowed to write jsx in here and actually let's see what we get now there are some subtle differences and ideally if it's not necessary we do we do want to keep dot TS right so we do want to we we don't want to have this become a jsx file just because of this little snippet here so there's an alternative way of writing this and that's actually what react does behind the scenes right we've seen that before so what we can say is react and then we can just say react Dot create element right so instead of writing jsx which is basically just a synonym for what we're doing here with create element so what you can what you can write here is react.createelement now we need to import reacts itself here so here um important react import react from react okay and this is the same as doing this but here we also have two props right so if you want to pass props with create element you just have an object here as the second argument and that's going to be a message right messages message that we do we do this and here we can we will just do like this a sender email it's going to be it's going to be the sender email so this is equivalent what we're doing here is equivalent to this and so this is the same as this right so when you write um when you write jsx with Section heading and you use these components behind the scenes react will convert that to all of these react.create elements right so let's remove this and now let's see what issue we have so we basically have the same issue as before which is that typescript is not able to figure out that this message will always be a string and not something else so we can assert here that this will be a string right and sender email as well as string right so this was a bit of bit of boilerplate called a bit of typing if you cut it along so now let's actually see what we get if we send an email so let's go back here and we'll say test at gmail this is a test so now I'm going to send this I'm going to click here and let's see if that works I'm gonna refresh here my email inbox and indeed we can see message from contact form new message from your portfolio site so that's actually what you see here so this preview is what you will see here in the email client new message from your portfolio site and you can see now that it's structured a little bit differently it doesn't look great yet because we haven't added we haven't added our own Tailwind Styles let's do that now right but you can see it's already styled a bit differently now we can actually use typescript Styles that's the last thing we'll do here um so this body let's actually give it like a background color you can start this very similar as um you know playing HTML or a plane or of course just react right just react we want the let's see but just change the background color a little bit and then we'll give this section also some styling class name we can give that a styling of BG white and then we want to have that border right so we can actually use our basically our utility that we created ourselves on board and black and we'll add some margin or vertically and some padding horizontally and as well as uh vertically we're going to add some board radius okay and then you can see this heading there's quite a bit of line height there right so if the as the text gets bigger typically you want to reduce the line highs so in until when it's called leading so we'll call leading tight all right so if we save this now and now we have to send an email again so I'm going to click here on submit again gonna refresh my email inbox and now I have another email here let's see if this is titled even better I'm going to open it here and now you can see it Styles a little bit differently now the text for some reason has become purple so I do want to change that and I think it's it's probably something that the email client adds because it can see that this is a duplicate of before so it may uh style it with purple now I'm going to overwrite that hopefully by doing this text black okay so one last time I'm gonna submit and actually maybe we should submit with a different text another test blah blah okay so now I'm gonna check submit go to my email inbox and and get my email here let's see what we get all right so it's still purple text and I think it's just because I've been spamming myself and this is what the email clients is doing um we could continue playing around but you I think you get the point here we can style these emails and there's probably a way to override that but it's going to be outside the scope of this project for now right but I think this looks pretty cool and this is much much easier than styling emails before all right now during recording I accidentally uh continued with the footer and uh dark and light mode but there are two things that we still want to add to this form so for example when we click here we do want to see like a loading indicator so that we know that it's being submitted right so if we look here once we click on the button the form is going to be submitted and we don't wanna we wanna know we want to see some indicator of that and this is also a new feature in next.js or rather react but next year as uh has implemented this so what we can do is actually when we use a server action like we're doing here we also get access to another hook basically and that's the following hook that's the use form status hook and let's see so if we call this we don't have to pass anything it's just going to tell us what the status is so if it's bending it's it's being submitted and if it's not pending well then it's not being submitted now we need to import this so if you do control spacebar there you're gonna see it's it's still experimental right so now it Imports it as experimental underscore use form status from react Dom but what we can do is we can give it a different name so we can say as simply use form status right so then we can just use this name so we can do this right so this can automatically detect that there's some form being submitted and we can use that now there's one issue here and you cannot do this on like a sibling level here and so here the form or the form here is basically an element here in the contact component and that's where we're using this hook if that won't work the this needs to be used one level deeper essentially so we're gonna use that pending for the button mostly so what we're going to do is we're going to refactor this button into a separate component so what we're going to do is we're going to create a new component here and we can call that uh submit BTS Dash BTN TSX and RFC submit submit vtn and we're going to copy all of this the button and what we're going to replace this with right so now we need to import this stuff here so I just import the things we need and actually just one thing okay and then we need to place that component here so we'll say submit submit ptn okay so just paste it there okay um we can remove this import of that icon and now what we can do is instead of using this use form hook in here we can use that and because this that won't work we can use it here in this submit button component because this is now one level deeper so here from the submit button right which we have added here so this can now detect that basically there's a form higher up here in the hierarchy that's being submitted right so it's still experimental so it may look a bit strange but that's basically this is going to be the future of forms right so we're going to have server actions and then you have this use form status that can take care of the pending status because usually you want to show like a loading indicator and so make sure you have also imported this and now we can use that depending here to uh customize things a little bit in the pending States right so what we can do instead of instead of showing submit when it's pending we can show something else so we have some logic here so we have to use the Kodi browsers and we can say if it's pending we can say sending but we actually we can also use like a load like a spinner and stillwinds actually gives us some some an easy way to add a spinner so let's just use stillwind here so let's just create an empty div so if it's bending we're going to show that spinner div and then otherwise parentheses we'll just keep this and now we got an issue here because uh this is not wrapped in a com in an element here so here we'll see a reacts fragment but now we don't need to use react.fragments because we do not have like a key property that we wanted to add just uh like this okay so this spinner will have a height of five the width of five and then we can use animate spin as this is a default animation that we get from uh till wind rounded full border bottom two and the Border color should be white and what we also want to do is this button should be disabled if it's independent states right so we don't want to use it to double click right or maybe on accident maybe on purpose we want to say disabled well if pending is true it should be disabled and we can also provide some other styling for example we don't want to have the software effect when it disabled right so if it's disabled we can say scale should be the hundreds and also disabled we want to reduce the background opacity to 75 percent actually let's make that 65. all right let's see what we get if we save here okay so now I'm gonna try sending a message here so I'll just use test gmail.com test and now I'm going to click here and let's see what happens now you can see we have this loading indicator right and eventually it will be finished and then it will be not pending anymore all right so last thing we want to do with this form is properly deal with the errors right so we we did a really good job here of extracting some error message so here in this server this is our server code so here we're trying to send this email with recent and maybe this recent surface is going to throw an error for some reason we don't know what the error is going to be but we can still extract some message and that's what we're returning to the client now right so now we're returning this object with error so here in the contact form here in the form we can we can get access to that right so the send email is basically just returning an object or could be returning an object and what we can do actually here in our server action we can also send back data because this send actually gives us an ID of the of uh whatever uh request this is and we may actually want to use that so we can actually say let data and we can say we can assign that here and so here let data we're going to attempt to send an email and if there's an error we're going to catch that and we return here now if it's not an error we will go here and we will just return an object with data right so now what we're going to get is either data or an error object and so here we know now we can extract data as well as error right so this function will give us either data or error and so pretty cool that we can do this here on the client side again because what we can then do is we can check if there is an error we can show show something to the user and we can show that message so if error we can just alert and then the actual error right now some template that not some standard string but actually the error that occurred and then also return here and I just return to return on to stop the function and otherwise we also want to give like a successful indicator so we can say alert and here we will just say email sends successfully right we're not using data here but for completeness sake we will just include this here maybe later we want to use it so now let's see so now what what will happen let's say we make a mistake here in the domains a set of recent.dev which is what it should be let's say I think it's recent.com it could be any other error in practice right so the service could be down we may have made some other mistake there could be also a mistake on recent server Parts there could be an error and something could be thrown here and now we are actually properly dealing with that here we actually want to output something to the user so now if I try to submit here we should get an error because I change the domain yes so here we see the recent.com domain is not verified so the so we actually see this error that's actually is that's coming from recent right because here it sees oh yeah this is not correct so it's going to throw that error here we are returning something and then we pick it up here and display it to the user and we haven't even created one API route or something or endpoint this is all handled for us behind the scenes all right now very quickly these alerts don't really don't really look good so basically the popular library to deal with this is is this Library reacts hot toast and let's see if we can see an example yeah so these are look look pretty good and super easy to use so often in any professional application you're going to want to show these messages to the user and that's called toast and this is a very popular Library so let's quickly install this so I'll also npm install react hot toast okay I'm gonna close this and I'm gonna go to the layout so first thing we have to do to uh to make this work is we need to decide where it should be uh where it should be output so here in the default it's top Center but we can also put it at the bottom in the right for example so first we need to basically tell react hot toast where it should be put so we'll go to the layout here because this is also something that's uh that should be pretty high up in the tree so we have the theme switch the steam switches are that's you haven't seen that yet because um I accidentally continued to build the the video but eventually we will you will see that we're going to have a theme switch now let's say we want to have that we want to have that toaster as it's called so we need to provide toaster from react hot toast right and you'll see that we will add this provider so don't worry if you don't have that that's just what we will add in a second and but we need to put the toaster here somewhere and we can then specify the position so we can say position should be let's say top right an accident is going to be put here so we can just say top right right so now we know where the toaster is gonna be so we can close this and now here if there is an error we don't want to have this alert we just want to do toast toast dot error right so here we can just output the the error right we don't have to use message that's what we've already done we need to input this let's see and that's actually the default exports here so it's not a names export it's a default export so make sure you don't have curly braces and then um that's for the error and then instead of having this alert we actually want to have to host dot success okay so now I still have this issue right so I still have this missed out should be dot def but we have.com so if I try this let's see what happens now and there is another issue or I need to refresh all right so now let's try this out so we have this domain this.com it should be dot nav so let me just quickly type out again that's test now I'm going to submit this and let's see if we get an error and we get an error here right react host it's showing us the message okay so let's fix this I'm going to fix it to dot Dev I'm Gonna Save here and I'll wait until it has updated so now I'm gonna try again and now it should work so let's see what happens and now we get this success message that's very easy to add some aesthetically pleasing toasts or basically alert messages or just some quick notifications all right so now we will continue with the rest of the application all right so then we're almost finished let's see the last few things that we need to do so we do need we need to add a footer here right so it's just going to be a copyright statement and then I think it looks good to also quickly explain what types of Technologies we're using for this website so that will just be a paragraph okay so I'm going to close everything right click close all I'm going to create a new uh component we're going to call that footer.tsx and we'll say RFC footer and we actually have a footer tag in HTML so let's use that as here in the jsx as well so we have a copyright statement now we actually have a small tag in HTML which is the appropriate tag for this and then to get a copyright symbol we don't have to look it up somewhere we can just use an HTML entity so they always start with Ampersand and then the name and then it ends with a semicolon that will give you that icon thingy so I'll just say 20 20 30 Ricardo feel free to replace this with anything all rats reserved okay and then we just have a paragraph which will just be uh you know quick explanation of the technologies that we use there now a quick starting tip again I like I like it when it's just a bit bold this first part so we'll wrap the first part and span I will say about this website colon built with react and next.js and then specifically the new app router and server actions comma typescript Tailwind CSS framer motion react email and resend and we're gonna host it on for sale all right we'll see how that works all right let's also add this to the page and actually this time we want to add it to the overall layout right because if we have multiple pages we wouldn't only want to have it on this home on this home page we want to have it on every page so we're gonna add that here to footer to the layout root file and we need to import this now control spacebar and it will automatically import this for me okay save here let's see if we see something on the page and there it is okay so let's quickly style this this footer needs to get some margin on the bottom some horizontal padding we'll Center everything in here and we want to de-emphasize the text so we're going to make it a little bit less dark all right so this small tag has some default styling of its own so we need to override some of that and also add some margin here we will also make the yeah we will make the text a bit smaller and then this this paragraph here text XS right so here we're duplicating the class you may think you can just put it on the on the footer here and the rest will inherit that and typically that's true but this small has some text size of its own so that's why we need to override it here and then we might as well just put it here as well okay so class name font semi bolt all right let's see what we got all right so then we have this there's also uh yeah we need to add some margin on the bottom so there's a bit more space and it's not working right now and that's because the small tag is in line so let's make it a block level element and let's see if that works yeah now that works all right so we're pretty much finished here and the last thing we want to do because the footer is pretty much uh finished right now well pretty easy the last thing we want to do here is also add this dark mode so if I click here you can see the page becomes all dark mode and when I click again it becomes light mode again right so this is a very typical feature and if you're gonna have somebody look at your portfolio website especially a technical person and they see you have light and dark mode I mean it's just an additional feature that showcases that you know about the modern standards on the web and that you're able to implement that all right now importantly these days people are not only going to click here they also have light and dark mode configured on their own computer so I'm in Windows here and I can personalize the colors here and say something like choose your mode So currently I have light mode I'm I'm not really a huge fan of dark Mouse I know some people are really going crazy over it but I'm just I like light mode so what we also want is that if a person does actually have dark mode so if the person has dark that this also becomes dark so this is the example if I refresh now it actually becomes dark right so the website not only needs to take care of this you know manual toggling you could say but also needs to detect what the mode is on the user's computer right so then if I make a light and I refresh you can see it becomes light again right and I can still toggle this as well now here when I toggle manually let's say I put it on dark Mouse here manually if I now you know leave the page and come back later let's have refresh it should still be dark mode right so it should also remember the setting that we have here so we're going to use local storage for that right so you can see it remembers the dark mode okay if I set it to light mode and refresh it's still night mode alright so you can see it remembers the setting as well so we're going to use local storage all right so let's start off by adding that little widget to the switch to the page so currently we don't have anything in the bottom right corner so let's create a new component here and let's call that we could call it dark mode but technically it's also for light mode so let's have a more General name let's call it theme switch RFC and we will call it theme switch all right so which tag should we use well it's a button so we might as well just use the actual button tag and in the button we're gonna have in the button we're gonna have a an icon right it's going to be a component so here we'll start off with the sun icon BS done and we will import that from react icons okay now it we want to place it in the bottom right corner and should scroll with us right so we can make this position fixed so we'll say fixed and it should sit a little bit from the bottom and a little bit from the right okay let's see what we got actually if we can even see this now of course not because we haven't added it to our layout or page yet right so if we go here in the layout file now we have header children footer and now we want to add a theme switch here somewhere as well it doesn't really matter where we put it and we could even put it somewhere else like here theme uh theme switch the steam switch does not need to get access to the active section right so we don't have to put it in the provider we could still do that but at least reactor is telling us that for optimization it's better to only put the components in there that actually need access to that uh active section value but it probably doesn't matter in a small application like this um so I'm just going to put this here and let's see if we imported this yeah it's imported so let's see yeah so now you can see we have a little icon here all right let's time this a little bit better so it's going to have a certain height let's actually start with the background color BG white and it's going to have a width of three RAM and also a height of 3 RAM now just like the header we want it to be a little bit see-through with like a blurry effect so we'll give it a BG opacity of 80 and then also a backdrop blur of 0.5 Ram will also give a very slight border so we'll say border which is which will just give us a one pixel black border by default but the Border color should be white and then we're also going to reduce the opacity to about 40. all right let's see what we got okay so we asked we we need to separate this from the background a little bit better so with the header we're doing that with a with a subtle box Shadow so let's also do that here we'll say shadow to XL which is pretty big but it's not going to be too much now you can see it's a bit uh we can see it is very subtle though if I zoom in you can see it a little bit better all right now obviously it needs to be a circle so we're going to say rounded pool all right so now it's a circle and now the icon in there needs to be centered right so it's a layout issue so we can use flex and we can say item Center for vertical and then justify Center for horizontal in this case and that's your Center yeah we also want to add some hover and focus effects so we'll say in the hover state we're going to scale this to 1.15 when we press down on it with our Mouse we're gonna scale it to 105 that's not a custom value that's just what still went over offers us and as you'll be smooth so we can add transition or transition all there's a subtle difference here between them I think so if we hover transition all it literally means for all properties and if we do Transition only yeah they have some specific properties named here and the timing function and duration is there a difference in there a timing function and duration seem to be the same yeah that's the same so transition all I think makes more sense because I actually want it for any property that gets changed so we'll use that from now on alright so now when we hover this you can see it's pretty cool Matt scrolls with us and you can see it has a cool backdrop blur and obviously I'm zoomed in here so let me make that 100 again okay all right now obviously what we want is when we click on this it becomes dark mods so here we can add an on click Handler so we can say on click and here we what we want to do is essentially uh I'll toggle the theme right so it should go from light to dark or if it's already dark it should go to light mode so now we need to we need to keep track of something right so we need to keep track of something you want to use state in react so here we need to keep track of the of the theme the active theme or or just theme so here actually react helps us out so I'm just gonna copy the uh accept the the suggestion here I like to you can write it like this I like to just import use State and then just use stance like this okay now I'm going to remove the type for now um so here the default value is going to be light right that's fine with me okay and if we hover theme now we can see the touch cut in first that this theme is going to be a string but we can be a little bit more specific than that because it's not going to be any string it's not going to be blah blah as a string right it's only going to be light or dark so we can specify a type here we can call that a theme and that's going to be the following a union type of light and dark strings right and then we can specify that here so we can we can tell the uh touch good here for this state variable this is going to be of type theme so now if you hover theme it's not going to be any string it's going to be of type theme which is just light or dark okay and then we'll also create a function that will toggle this theme so that's what we will write here so we will use uh let's write this here toggle theme so that will be the following function so now we have to write a little bit more we're going to write a little bit more so I'm gonna extract this out into a separate Handler here instead of writing it in line here and we actually already get a bunch of suggestions here now it's not exactly what we want to type right now but it's very very close so if the theme is currently light and we click on that button we want to set the theme to dark all right let me remove this for now and else if this then the theme must be dark so then we just want to set the theme to light right okay when I save here we get an issue so we're using your state as the client-side feature so we need to make this a client component use client all right let's see if that works okay so if we click now it will set the theme to dark right but we won't see anything because we're not really doing anything based on the theme variable right now so what we what we can start with actually is just change the icon right so here when I click here in the example the icon should become a different one a moon and if I click now again it becomes the sun again so let's start there so here now it's always this sun icon so we can have some logic some JavaScript Logics on jsx you have to use Kodi brancer so here we can check is the theme currently light then we want to show this sun otherwise we want to show BS moon it's another icon and I can import this like this okay so now we should see something right so now if I click here it should change and it changes right so we are now properly keeping track of the all right now what we also want is now when I set for example now we're in dark mode right because we can see the moon if I now leave this page and come back later let's say refresh it should it should remember our preference right so right now it gets reset to the Sun so how do how can we persist data well what you can actually hook into as a developer is the user's local storage so we can see that here if you go to application here you can see logo storage session storage there's actual action an actual DB here as well most of the time you want to use local storage and we can put some data in here and the user will when you when user comes back to our domain we can read that data again so here when I click not only do we want to set the state here we also want to say persist this data in the local storage so what we can do is we can use the window objects and we can say local storage dot set item and we can set the theme to dark we already get a suggestion here right and then for the other Block it's the opposite all right so here we're going to set it to light right so now if I save this and let's see so it's right here so now if I click here you can see we have some value Here Right theme and dark right so now if I refresh here um it's going to be light mode again as we can see from the Icon but the local storage is still here right so then when we load the page we need to read the item or get the item right so how do we do that well we can use an effect for this right so use effect to use effect hook you want to use that when you need to well synchronize with an external system so local storage is an external system right it's not something that comes from react it's outside of react so this is a good use case of using use effect here we are interacting with local storage as well but here is because of a user click right so if it's in in response to a user action you can just use it in the in the Handler function but here on loads we have to use the user Factor so here we actually get a suggestion um so let's actually see we can say local theme we can get Getters from the local storage of window.localstorage.get item and which item do we want to get because we have multiple well the theme one okay and let me close out of here we only want to do this once on loading the component so we can have an empty dependency array okay so then um so then if there is one so if it's not in because maybe there is none here right it could be null let's actually see what it could be right so we can just hover to see what type it could be it could be a string or no right because it could also be empty here so it could be any string or null and that's not actually true because we know it's not going to be any string right so we could be more specific we've just defined this as a separate type so we can tell um we can tell typescript that this is going to be um either this theme right so light or dark or of course it could also be null right so now if we hover local theme we know it's going to be of type theme or null so here we have type theme light dark or null so if it's null we don't really want to do anything so we're just going to check if local theme Matt so if it's actually existing so it's not null so it's going to be either light or dark we just want to set the state here and so then we can just set the state to whatever that theme is okay so now I'm Gonna Save here so now when I load it's currently dark mode so now that's I will put it on light mode you can see it changes in my uh local storage and now if I refresh well that's actually the default so now let's actually change it back to dark mode it's dark mode and now when I refresh it it shouldn't be light mode it should be dark mode right so now let's see if it works and it works right so initially you may actually see light mode because this use effect runs after uh rendering so this this first gets rendered on the page painted on the page so we're gonna see first this sun because that's the default default here is light and then it's gonna run this use effect so this comes basically right all the way at the end it's gonna get the dark value here from local storage and then set it to dark and since then we're changing the state it's going to render all of this again and then it will actually be the moon alright so that's not a big deal though so um because it needs to fetch something from local storage can take some time but uh that's not really an issue all right now what we also want is not only should it look into local storage but it should also check what my default setting is on my computer right so I have my option here on my PC and I could change it to dark right you can see here it now changes to dark but if I refresh the page it's not it's not dark Mouse here we can see it's light mode right so right so now what we want is that if we are now coming to this website and we haven't set any changes yet right so this will always be dominant so once we actually click that will that will take priority over what we specify here right but if we haven't set anything it should take this into account so right now we're not doing that so here we can simply check if we already set something in local storage we should that should just be the theme right now we if if nothing is in local storage we want to check if there is some setting in on the user's computer so here we can actually use a media query so it's called window.match media and then it's called prefers color scheme I already got the suggestion here so prefers colors color scheme dot matches right and if if it prefers color scheme is dark um we need to set the theme to dark right so now if I save here and let's let's clear my local storage I'm gonna go here application application logo storage I'm going to clear this right so I'm gonna I'm coming fresh to the website but my browsers my computer setting is set to dark now let's see if our application picks that up so if I refresh here we should see a moon right so you can see indeed it becomes a moon it's not coming from local storage it's coming from this match media all right so now we are setting the theme properly here and we are probably keeping track of it obviously we want to style the rest of the page so how can we do that with Tailwind so Tailwind actually has a separate article on that it's actually pretty interesting and they also explain how it works with supporting both that system preference as well as manual selection that's what we're doing here manual selection and now what we can do is we can go for example to the layout file and here we set the background color for the page right now we can say in dark mode we want a different background color so let's say in dark mode so I can say dark colon BG gray let's make it 900 and dark text Gray 50. so this is going to be whiter text and we want to decrease the text opacity a little bit so we'll say dark text opacity set to 90. okay so let's see what we get if I save here and go back nothing changes but now if I make a dark Mouse L actually we already see a change here and that's not supposed to happen because I haven't clicked here yet so why do we see dark mode here if I click here it doesn't change anything okay of course because I have my system setting on dark right now why don't we see the proper icon here so let's see Team switch maybe I should just read out the page and that doesn't work it's a bit strange why is this not the correct icon if we so I'm so I'm going to to clean local storage here start from a clean slate and I'm gonna clean everything here delete and I'm gonna reset this here to light mode in my system settings as well and now I'm gonna refresh the page okay and I think I already know what the issue is actually so if I set the system here to dark now yeah so till wind can automatically pick up on this and so it's gonna do this outside this system that we basically set up now so we have to specify to till when that we're going to do it in a different way so we can go to the Tailwind config because we wanted to do it in a manual way as well right it's not only when the user system preference matches that but also the user should be able to click on this so that's why we need to set dark mode here to class all right so make sure you change the Tailwind configuration to class the class method and then what we need to do is we need to add the class dark right so it says dark mode is the class methods now we actually need to add the dark class to the Dom as well so here when we click on this now let's see we have here we're setting it to dark and we sell it in local storage and now we also need to add this in the Dom so we can say documents dot documents elements the class list we're going to add a class here which is going to be dark and then if we go from dark to light mode we need to remove this class again so let's copy that and paste that here instead of add it's going to be remove right and now what we want is whenever we add we make it dark we should we should also add that to the Dom so here here in local theme where we where we grab it from local storage if if that turns out to be dark mode in local storage might as well say if local theme is dark we need to add that to the Dom here right and then the same goes for here so here we know it's going to be dark so we're also gonna set the class here right so we need to do this for till end till when this is going to check if the dark class is added to the Dom if that is true we can use those uh select those classes like dark colon right so now I'm gonna make I'm gonna reason everything I'm gonna set this to light and I'm gonna set this to light I'm gonna clean local storage I'm gonna remove local storage and now I'm gonna refresh and now let's try switching between okay that seems to work well we'll start the rest of course just to check the background color to see if everything is working okay now I'm going to remove my local storage value here clean local storage and I'm gonna set the setting to dark mode in my computer and now I'm going to refresh and Page start mode right so now everything is working it's a bit complicated here to support both the system preference as well as manual toggling I'm consider to light mode that's what I prefer and let's see if I refresh now it's light mode yeah but I can still change it now okay so now we can just use these dark classes so dark colon to modify our page a little bit so let's do that now let's quickly go through it you can fine tune this as you see fit of course so these lots of colors they should they should they should they should also be changed a little bit so let's add that to the end of this list of classes so we'll say dark this color needs to become different so we'll say dark PG should become nine four six two six three all right and this one in dark mode should become BG x76394 all right so let's see what the color is going to be now all right so yeah I think that looks much better and let's actually also style this theme switch itself because it's difficult to see the icon now let's go to the theme switch and here I'll add this at the bottom in dark mode the background color should Simply Be BG gray 950 so then we have this all right looks pretty cool and everything seems to work so far alright so then let's quickly go through it uh I think there's not that much but uh let's check it out let's go to the header alright so header needs to be changed a little bit so we'll say header um actually the motion div here that's going to be that white uh color the bar now that needs to become a darker color though so we'll say PG gray 950 and we'll also say ah okay we'll leave the up the opacity is already set we'll keep the opacity we will change the Border color though so we will change the border to border black at 40 opacity and we also need to change the no that's that's about it so let's see how this header is going to change now okay now I do want to reduce its opacity of the background a little bit so we can say dark PG opacity to 75 all right that looks much better you can see everything still works but the the colors of this active item also need to change a little bit so if we go to link here these colors in dark dark mode let's see here for all the links we'll say in dark mode the default text here should be text Gray 500 and then when we hover it in dark mode right so now we have to combine these pseudo classes dark hover the text Gray three should be text grade 300 and then here when the when it's the active link so if I save here okay so this looks better and let's also change this background thingy and that's that span let's see here it's gonna be dark BG Gray 800. all right let's see okay let's compare here with the example all right that looks about right now you can see the color of the active item here it should be it should be uh light it should be whiter color so here in the example it's a white it's a white color and here it's it still is a great out because here we are saying if the active section is this link so the active section is getting this text grade 950. but in dark mode this should become text Gray 200 so now this is lighter all right let's see if that works yeah everything is working here all right very good all right all right so let's see what else we should do here so obviously the next part is going to be these buttons so let's go to the intro section so let's go to um that's going to be the CV download button right so let's see that's here so we just need to change this background color it's just going to be white color so it's like BG wise with 10 opacity right so if you look now this looks much better we're going to do the same for the other buttons now let's see if we'll do the same here or this LinkedIn icon as well as the GitHub icon now here we also want to change the text color so basically the icon color so we'll say dark text white with an opacity of 60 and the same goes for the other icon or anchor tag that's wrapping the icon and now if we check text color should be updated as well yeah all right all right so that looks much better now we can see the section definer is a bit too bright right so here we're just going to go to section divider and we're just going to change its background opacity so here we can just say dark BG opacity to 20 percent right so I change this and now you can see it's a I think this looks better all right so then we have this text I think this looks fine so we'll just keep it like this then we have the projects obviously they need some adjustments so let's see so they look like this and now they look like this so let's quickly change this go to projects and also actually individual projects actually we only need the individual project I think so let's just start here so here we need to change that background color so we'll say for the section uh element here we'll say dark bg10 and also that hover effect so in the in dark mode when we hover make the background white with 20 opacity alright that looks better and hover effect still works the text needs to get a different color as well oh let's see I think we set the color actually on now we'll send it here we'll just set the text Corner whoops we'll set text color to white dark text White and we actually need to go to the description to set it specifically there you can see description here here we're going to say dark text white but with a lower opacity of 70 percent and actually want to do the same for the tags here so we can just copy this and paste that for the lis alright so let's double check all right this looks much better compare with the example this looks right all right and it looks much better and the skills here well we just have to change the background and let's go to the skills section and here for the Lis we'll say dark BG white with an opacity of 10 and then the text actually needs to become dark so it needs to invert right so we'll just say dark text white actually should it should get a white text so now it's dark but now we need to flip it we invert it so I'm changing the text to text wise 80 so that should update in a second yeah all right so that's basically the skills section all right so then we have the experience section let's take a look let's look at the example let's see all right so basically uh it should look like this and what we have right now is this all right so let's go to experience and here we cannot use Tailwind classes right because this is a third-party component and they basically expose the props and we have to use we're basically being forced into using their way of styling this component so what we would like to do for example this background needs to change so what we want to do here is in light mode it should be this color right but in dark mode so we want to be able to do something like this so if the theme is strictly equal to light right then we won't have that color otherwise the color should be we'll just use rgba 255 to 55 basically wise with five percent opacity we can't use Tillmans here so I'm using just normal CSS and this is what we want to do but where do we get the theme from because this is a different component we don't have this theme ready here and so how do we get this the how do we access the value of the theme in this component because now we're going to get an error Right theme doesn't exist there so where does this theme exist well we we have put that now in the theme switch component as we are keeping track of the theme in here right so if we look at the tree of components that we have the layout is here the theme switch is here right and our experience and other stuff is on the page the page is what's going to be here basically so we have a problem right now and we actually have the same problem as before when we try to keep track of the active section which is that we need to pass around the value of the theme in in a serious application it's going to be too many different applications many different components in your react tree and we we can we don't always want to use prop Drilling and we also can't really use that right now because that experience isn't a chance element of theme switch right it's it's uh it's basically like a sibling and then we need to dig down so here is we basically have the exact same problem as with keeping track of the active section and that time we solved it by using the react contacts API and in professional application for a theme that's also something it usually you would put in a context so let's quickly refactor this into using the context API right so currently we're keeping track of the state in here and now we're going to go to our context folder and we're going to create a new context here and we'll call that theme context dot TS actually TSX because we're going to have a exported component from here so we'll just say RFC and in a context what you're going to have is a so-called provider component right we've already discussed that theme context provider and then this is the component that's going to keep track of the states right and this will provide the state to early any elements that we wrap in here in the react tree right so now this stuff here we need to copy this out of this theme switch component file which will clean this up nicely and we have to put that here so this provider component now will be responsible for keeping track of the state now we need to provide we need to import some stuff here so I will say use date it also wants to know our theme type right so we also specified that here we can remove that from here now and paste that here by the way we can also remove these Imports in the theme switch components and now we have an issue here because here in theme switch we still want to be able to switch the theme right and here for the icon itself we also need to get access to the theme but we'll see how that works we'll this will now come from this provider eventually right so now multiple components need access to the theme right so we'll see how to do that so what we've done it before but you'll see all right let's see we need to import user facts as well all right now it takes up quite a bit of space so here I'm gonna collapse this because we have already discussed this we don't have to see this right now this is just some Plumbing here to make the contacts work all right so here we need to return not just a diff we need to actually return a provider component from react so the way to do that we first need to instantiate the context right so what we're going to do is we're going to say theme context is react.createcontext or just import it as a named export like this and then you can write it without the react dots so we're going to say create a context here and we can provide a default value here that default value is not the same as the default value in the state so if I go to our layout here the default value is what's going to happen when you X when you try to access the context outside the provider component right that's rarely useful so typically you know if you don't really have it like a if if it doesn't really use case that you need to support it's probably easier to invest to just provide null here and typically this is actually capitalized so I will say theme context all right now what can we do with this well now we can actually return that provider component so we can remove this and here we can create theme context dot provider.apks right now we're going to put that in that in the layout file again right so we're going to wrap other components in here and we're going to receive that through the children prop we've discussed this before now here typescript wants to know what type that's going to be so let's stick to our convention here of using the component name and just adding props to there and then we'll say type and or interface I like to use uh at the degree consistent but interface and type are almost the same so it doesn't really matter and we'll say children is react react node okay so then in here here's where we're going to Output those children so basically this provider component is just going to wrap part of our react tree all right so if we hover this we can see property value yeah so obviously this provider should pass along the actual theme right so then we can consume it in other components here we're just providing us this is this provider is just going to provide it um and and what specifically is it going to provide well we can say that here with value it's going to be an object that will hold our theme right we can say theme is theme in JavaScript if it's if it's the same name you can just say theme and also we also want to toggle the theme right it's not a set theme function itself but we're just gonna do it through this toggle theme function now so not directly with that theme but like we've done before now it's this uh a custom function that we created all right so let's see okay so we're passing along this value for for our contacts there but we have not specified that here so when you create a context here task is going to infer this is going to be a context of type null right and here this is not null this is going to be an object with values so here we need to provide the type of this context right so let's do that uh here type theme context type so we're going to have a theme right and that's actually going to be of type theme Right light or dark and then we have that toggle theme function so to type a function here it's about the inputs well it's not going to take anything and it's not returning anything so just void okay so that's going to be that's going to be the type of this value right so we need to specify that for when we create the contacts we can do it with these angled brackets and then let's see we're going to have another issue because now we haven't we have not specified that this can be no but now we are saying we have a default value of nil so so now sometimes this is going to be null so what we could do is say or no so it's going to be this or no okay so now that you get rid of all the issues you know this is the real world is a bit uh annoying maybe to take care of the types but uh we get a lot of benefits from that all right so now let's see what's the issue yeah so now we just are back to this issue where theme is not defined right so now we have basically created our provide wider and now we're gonna add this to our react tree so let's go to layout here we've already added this active section context provider and now we need to wrap the component with the theme context providers and then we can access the theme in those components that we wrap so let's um let's actually wrap everything here we could also wrap these divs but these don't need it so it doesn't really matter so we can say theme context provider I'm going to import that make sure you import it and automatically import it for me and then we need to put all the components that need that in there right so let's see the theme switch needs it but also some things here so it's best to just wrap everything here like this what we can also do is since these provider components don't take up anything in the Dom what we can also do is just add all this here this is a more typical format so let's just do this this looks a bit more familiar perhaps so basically in a real world application you could have a lot of these provider components so you really get like a tree of Provider components at which point you can actually refactor that to one file and have like one one component be all basically house all the providers but um that's a bit outside the scope here let's continue here yeah so the issue that we have now in the scene context this is a client component because there should be a client component because we're using use effect use State contacts API so this needs to become a client's components now when I make this a client component and we wrap basically in our entire app in here you may think well now everything is going to be a class component right because now this is a client component and everything here is also going to be a client component well let's see what's the issue now and that's actually not how it works right so this layout file is a server component because everything in the app folder is by default a server component and we don't have used clients so this is a server component now we are we can import a client component so this this context provider is actually a client component right this is a client component but since we are using this pattern of basically everything in here this is going to be the children of this theme context provider so we just pass this as the children and immediately output is here and if you do it that way this will not automatically become client components right so these can still be server components right in our application we actually have most of our components being client components but these could technically all be server components right even though in our reactory they are nested in a client component right so if you want to have a server component in a client component you have to use this pattern of using the children and passing it along as children right I'll have a course on react nextgs very soon highly recommend you check that out it's really important that you have mastered these uh these Concepts as a professional if you want to be a professional developer right so it only becomes a client component if you actually specify at the top use client or you import the components into a client component so if I import another components here import some component from from somewhere else this component now because I'm importing it here in use client in a client component this now also becomes a client component even if this one does not have used client right but because I'm importing it here basically this becomes a boundary in the reactory and so everything you import then will be a client component and then everything you import in that component will also be a client component right so bit confusing but that's how it works right so then if you want to have child elements not automatically become client components you have to use that pattern of using the children right so I can pass along server components here as children and I'll put them here alright so now finally this should work so let's see we have theme context yeah did I remove this I think I removed this accidentally so this should become use clients and now we we have added the provider here to our reactory so now we can we can consume that context right so whatever this provider is now passing along as a value we can consume that anywhere in here right anything that we've wrapped in here so let's start here we get this error theme is not defined in experience so let's go to experience component experience so now we can consume that here so if you remember the way to consume this is we can use use context right that's the hook that we get from react and then we have to provide the context itself and that's actually this very bone this is what we need to provide because we could consume other contacts as well like we have another one right about the active section but we want to have the theme context now we could export this import that here but uh that's a bit of a hassle right so previously what we've done we've created a custom hook to consume the context and that's that's easier to do so let's actually also do this here so we'll export another function here export function we can call that use theme and here is where we will actually uh and actually this is already a common pattern so we actually see what what it should be so we can just say the contacts we're just going to use use context from react it's going to be the theme context right use contacts you need to import that can be this theme context and remember this theme context could be no right so we could technically try to consume this outside that provider component in which case we will actually get null and just like we saw before we don't want to deal with that at every point right so we will have to check for the null value at every point that we consume this context so better to have a custom hook where we don't have to specify the theme context at the actual context variable every time but also we can deal with the null value right here so if it's actually no we just want to throw an error because we don't want to use this outside that provider so if we accidentally or somebody else on our team accidentally does that just throw an error so we can fix it right so here I got some suggestion from copilot use theme must be used within a theme context provider okay so a bit of boilerplate stuff here but uh yeah react context is very important so now we can import the hook here to consume it so use theme so let's try typing it use theme it suggested for me I can just execute that function and what we get here is the actual value that the provider gives us right which is this object here and we can immediately destruct destructure destruct that to the structure that to get the theme and the toggle theme values so we can say theme and actually we don't need to toggle theme Here In The Experience component so we'll just get the theme that's our theme is what we're using here then to check so now you can see that error should be gone if I save here and here it says theme is not defined but now it is actually defined so let's see if that works okay so now we got a different error which is that in the theme switch we were using toggle theme and actually also theme itself let's go to toggle theme or theme switch right here here we also want to consume that context so we can actually just copy this if we want to consume that then we need to input this and now we can also extract toggle theme from there and now if I save it this should now also work so now we should be without any errors let's see if that is indeed the case Dev server taking its time but that's okay and let's see all right so now if I click here everything still seems to be working right but now we can continue styling like we were until we had to solve this issue let's just continue starting the experience section now right so now we've abstracted everything away very professionally into a theme context file using react contacts and type save with typescript so very professional stuff here but it all becomes very easy Once you understand and really have mastered the fundamentals JavaScript and now you have a Tailwind it's all about CSS so um and of course react itself so I'll have courses of course of course and all of them definitely recommend you check out the links in the description alright so here we need to continue styling here so here now we have these uh arrows here they also need to be uh changed a little bit so here this border we can just check is the theme light then indeed oops then indeed we do want to use that otherwise we want to use 0.4 Ram solid and we're just going to use white with some lower opacity so 255 all the way and then 50 opacity all right so then we also have icon Style Let's see we have icon style and we base we bit that's basically the background color here of the icon uh Circle we basically want to do the same so well we'll just type it out so if this theme is light then we want to have white otherwise it should become rgba 255 to 55.15 and I'm getting an issue here on I forgot to comma here and it's going crazy because I just missed a simple comma um and it looks like maybe I missed something else so what else let me just refresh so sometimes you get these strange errors maybe I change something else and actually no that seems to work so uh I'm not sure what that was all right so now you can see that um that looks a little bit better right so let's let's change the description here as well so we say description that should become dark text white with 75 opacity and that should be it so if I save here and let's wait until this has updated yeah so this looks good now now this line is a bit too too uh White right so we need to de-emphasize that line a little bit so we we actually had to use the globals file for that right because it was an issue because it's a third party Library so we had to set this align color variable ourselves to prevent some issue so now what we can do is in dark mode we want to change this now remember when you when we make a dark mode we set we added that dark class to the Dom so we can say and actually we set it to the HTML elements so I can prove that to you here so here in the in the elements tab you can see in dark mode now we have added this class to the HTML elements actually so we can say this HTML element when it has the dark class we can just set a new value to this line color and again I just wanted to use to be white so we'll use 255 for everything but 0.2 opacity all right let's wait until that updates all right so I think that looks much better all right so then really last thing we need to do here is just change the context form a little bit so let's go to contact so here this text here please contact me directly this needs to become dark text white with 80 opacity and we want to change the color of the form of the text in the form so we'll say dark text black now let's see now we have that and the text here is white so we need to change the text here so dark in dark mode we need to change the text to text black so for some reason in dark mode it automatically makes the text White yeah so now it's dark again all right so also it's a bit too wide here the uh the fields here so very cool effects that you can do is just make this a little bit lower opacity so we can set the background should be white but with an opacity BG opacity of 80 percent and then when we actually focus it so we'll say focus in dark mode so dark Focus we want to increase that opacity to a hundred this is going to be a transition so we'll say transition all to make that smooth and we want to do something similar for the text area so we can just copy that and now you can see the input now if I if I click here you can see it becomes a nice effect now we also get this outline that we don't want so in dark mode we do want to remove that outline now we'll just say outline none all right and let's copy all of this all the way until dark BG white and let's copy that for the text area as well all right so now this looks pretty cool in dark mode nice effect all right let's quickly style the button as well so I will say button we'll just say dark BG white and dark BG opacity of 10 percent okay let's check that out all right so that looks much better looks pretty cool I think and we are officially finished with converting our project into dark mode right so everything still works on light mods and now it also works in dark mode right so really cool well done for making it this far alright so we're pretty much finished with our project here and usually at the end you do want to make sure that everything is responsive so it looks good across multiple devices and we have styled everything you know with these uh SM and other breakpoints so for the most part it should be responsive but let's double check so I'm going to open up the dev tools here I'm going to use iPhone 12 Pro and that's let's actually see the intro animation to see if it works on mobile and let's see that works really cool now I can already tell that there's something wrong because I can scroll to the right here so something is overflowing horizontally basically so let's see what we get yeah so the the projects here are not responsive right so it's the project section here that seems to be a problem everything else looks really good actually right now we need to make the projects section uh properly responsive right now uh yeah it's just a bit messy so let's go to Project or actually the individual project all right so have a look at the example here we can see that this looks much cleaner and responsive in Mobile so here we actually are removing the images you know if we try really hard we could keep the images in but it would it would be a lot of extra styling so for so just to make it a little bit easier we're just going to hide the images initially and then only on smaller and up are they going to be visible right so what we're going to do here is we have a bunch of classes here what we can just do is say uh hidden right so then it's always going to be hidden that's not what we want so we can say from smaller and up it should be display block so not uh not display hidden so now we should still see the images but on the smallest devices they should be gone yes now the images are gone and now we can see there's there's too much space here for this one so this padding on the left or whatever it is should not be visible on should not be there on smallest on the smallest devices so let's see where that does come from I think we did something here yeah so petting left hand and we also have group even margin left a lot of ram here it's being applied for all sizes but we we only want that on the bigger devices so let's see if we can do something like this SM and then group even margin left yeah that works okay and then we also have this uh rasling let's see okay so this is how it's supposed to look all right now this one still has a lot of padding on the left here and that's because here we have another group even class here so this also should only work on smaller and bigger not only not on smaller than the SM breakpoint right so then this lines up better and now I think we just need to restrict the width of these cards and actually that was all that we need to do uh we don't have to change anything else sometimes this devtools is not uh correct so it shows it was showing me horizontal scrolling but if you just close out of it and open maybe refresh the page and open it up again sometimes that horizontal scrolling is gone so now you can see this is uh completely responsive as well right so the smallest size that you typically want to support is about 320 and we talk more about this in my CSS course as well but uh yeah definitely uh support all the way until 320 pixels these days we have foldable phones as well so um if somebody is putting your website in one of their in one of the two screens like surface Duo it may actually be even more narrow but for now this will do um right so we have a completely responsive beautiful portfolio website with some really cool animations and some really Advanced features alright so let's deploy this to the internet we're going to use for sound hosting for that but first we need to put it put it on GitHub so you need to log into your GitHub account if you don't have one create one and we're going to create a new so-called repository or repo for short and we can give this any name we want so let's call this uh portfolio website project I'm gonna call it something like this all right let's just call it portfolio website and it's going to be public and don't change anything here we're good we're going to create a new repository now okay so now um it's been created but it's going to be empty now right so if I open this up and there's nothing here so uh GitHub display some instructions here to push your code to uh this uh this repo so let's go to our terminal here so here I'm going to close all the folders I can hold I can do that by holding clicking this icon I'm going to open up the terminal I'm gonna open a new terminal here so first we need to initialize this as a project for git right git is separate from GitHub git is just a technology to keep track of uh basically the the changes that we make and manage our code base so what we're going to write here is git init okay so now we have actually re-initialized it because it was apparently already one was already existing uh I think that's coming from nextgens so as you create an XTS project it will already initialize a git repo for you but doesn't matter now we need to add this link here let's just copy this and what we're going to do is we're going to add that as a remote all right so what we're going to type here is git remote add and then the name for this uh remote it's called origin so it's just wrapping here but the it's one word and then I'm going to paste that URL so that's this whole URL including dot git I'm going to press enter and now we can push to that uh remote called origin so now we need to decide what to push so we can actually check get status to get an overview of all the things that we've changed since the last commit and you can see that's basically everything so we can say we want to we want to add everything now okay we're gonna get some issues here with crlf that has to do with um with things like spaces and how a space should be encoded and things like that it's not really important but now we can we have added that so now we can actually commit it so we can just write git commit and then as a message Dash M we'll just say first commit okay so that has committed all of our changes now and now we need to push it so we can write git push and where to well to that remote repository which we called origin so git push origin and then which branch well we're still on the master Branch or the master Branch right so here we can say git push origin master and that's going to push everything here to GitHub all right so now if I refresh here you can see we have all of our code now here on GitHub it's basically the same as here right now for me this is probably available right so unless you change it to private this is going to be publicly available so you can see here in our local files we have dot Infidel logo with this API key but here I don't have that file right because it's ignored to get ignore right which is which is what we want all right so now this is on GitHub now we can go to for sale so I have already created an account on first cell if you have it's for sale.com very popular service these days so if you don't have an account yet go ahead and create an account and then log in and when you log in you'll see a dashboard so I already created a project before just to test things out but now we want to add a new project so we're going to say add new project and then here it wants to know where which projects right now basically this is going to be this right so we need to tell for cell um that it needs to use this code here this this rebound so we're going to continue with GitHub here I'm already logged into GitHub so it can already immediately log in here as well and then you can see we have connected our GitHub account to for sale and for sale will already look at your repost that you have so what we want here is this one that we just created two minutes ago so I'm going to click on import here and then we can give that a name but you can also change that later so let's just deploy this and see what happens all right so it's going to build our project as well right so you don't have to build your project yourself but if you want to do that in the package.json there's actually a script for that right so there's a build next build it will create an optimized version ready for production right but now that for sale is going to do that themselves on their servers so we just have to wait a little bit and I'll come back once this has finished all right so here it says congratulations you just deployed a new project to for sale so let's wait until this image has loaded yeah so we can see this looks good and if you actually click on the image it should already work so now we we get a custom URL here and you can see that our project now is live on internet right so they give you this URL that you can go to we can change this a little bit but you can see now that our project is like everything is working here with the animations um and we can even check the contacts form now I won't do that here because I already checked it and it does actually work so uh but you can see everything is working it's live on the internet everybody can go to this URL and they'll see your beautiful portfolio website all right now let's quickly change this URL into something that's a little bit more readable so I will just continue to dashboard here and we can go to settings project settings all right so here you can see they have domains here and there are actually two domains so if we go to deployments here and just click on this deployment that we have you can see all the available domains here so they actually create a couple of them so we can change this let's see we can go to portfolio website this is showing the deployments we can go to settings here or as then we can go to domains and here you can see we have that URL so we're going to edit this you can actually change this now you you do need to keep the for sale.app but maybe you want to just change it to your name so just Ricardo in this case it may not be available so then you need to change something else and see if it's yeah so this is not available it's already used by somebody else so maybe maybe your full name right Ricardo Ricardo and then the full name or Ricardo portfolio let's try Ricardo portfolio also not possible okay so then maybe actually you do need to use a full name and then portfolio or maybe portfolio site let's see that works okay so that's what the status that one is actually available so now when you go there it's now a little bit looks a little bit better than this weird call Alpha so now I have Ricardo portfolio site dot for sale.app and so you can play around with that see if it's available for whatever you want but we have come to the end of this whole tutorial so really well done for making it this far we've learned a lot of new things and you now have a beautiful fresh modern portfolio website not just in terms of design but also in terms of Technologies used we have some beautiful animations that are going to impress any visitor that comes to this web website we have actually we haven't we actually have an a working form here and yeah we've used a lot of new technologies especially you know in right so we can see react and xjs so app router it gets a little bit you know time to get used to with layout and Page we have server actions now and we even use that experimental use form status hook which um which is going to be the future of dealing with forms and we've used typescript when we had some issues with typescript sometimes and uh we've learned a lot about that until when CS as we looked at some more advanced features like group hover group even and how we can use the add apply rule right so we've learned a lot about Tailwind we've used framework motion to really create some beautiful animations and transitions here we've used react email and the recent surface to make this this form actually work and we've deployed to for sale so now our project is hosted on for sale so again well done of course we all right and of course we also implemented dark and light mode and it's completely 100 responsive so this is basically the perfect portfolio project I hope you enjoyed it I hope that you learned a lot check out my courses in the description if you want to master the fundamentals my react and xgs course is almost released so also make sure to get on the email list and make sure to subscribe of course because I'll be releasing more projects like this so make sure you subscribe and also hit the notification Bell so that you are notified when a new video drops so thank you for watching and I hope to see you soon bye
Info
Channel: ByteGrad
Views: 135,979
Rating: undefined out of 5
Keywords: responsive portfolio website, react portfolio, next.js portfolio, nextjs portfolio, web developer portfolio, software developer portfolio website
Id: sUKptmUVIBM
Channel Id: undefined
Length: 440min 20sec (26420 seconds)
Published: Fri Jul 21 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.