NextJs Portfolio Tutorial - Build a Responsive Portfolio Website w/ Advanced Animations (2023)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone in this video we will build a responsive and easily customizable portfolio website using xjs and Tailwind we have here multiple sections starting with navigation bar hero section we also have animations throughout the page then a metrics About Me section with different tabs you can switch followed by a Showcase of projects that are also clickable each card and you can navigate to the link of your project or GitHub we also have tags at the top to filter out the projects and they contact us form that we will connect to the mail server so you can receive the submitted messages in mail and finally at the end of the landing page we have a footer and let's take a quick peek at the mobile view we will Implement in responsive Styles and finally at the end we will also deploy the project using virtual so you can start sharing the link to your portfolio and throughout the tutorial I will also provide some tips for building your portfolio that have been useful throughout my experience and as I mentioned in the beginning this portfolio website is easily customizable and towards the end of the video I'll also show you how to customize it and can be done by just changing one line of code also for this memoji I found some resources so you can browse different languages and pick one that you like the tutorial will be divided in two chapters and each chapter will have a corresponding git Branch so in case you missed something you can always continue the tutorial with the current progress by checking out the appropriate branch and if my tutorials are helpful please like And subscribe and if you're new here welcome make sure to turn on notifications so you don't miss future videos and without further Ado let's get started we will start creating project by running this command MPX create next app and latest if you don't have already installed create Next Step it's going to ask you to select why as in yes then give the project name after that it's going to ask several questions about configuration for typescript we select no yes link yes Tailwind as well yes and no First Source directory then for the app router we select yes and no for import Alias and press enter and this will download all the required modules once it's done downloading we're gonna see the interview so CD and the project name and after that we start our application by writing command npm run Dev this will start our application most likely on localhost 3000 it will indicate it and we can command press go to the browser open it up and that's our application and before we jump into code I'll show you guys what we're implementing first and it's going to be the hero section as you see here on the right we have the image on the left we have the text and the buttons we're also going to implement this typing animation and for the text and patterns first we'll implement it in a simple style and then add gradients on top of it now let's quickly go over folder structure all the configuration related files would be outside of source folder and then inside source folder is where we have our code and now if we go to page.js that is like the main file for next.js project and all the page that we saw in the screen the code is coming from this file now I'm going to open it up the our application inside the vs code you can have it open in the browser of your choice but to save space I'm going to open your pop here and command shift p or you can open command palette from the top menu and then simple browser show where we paste the link for localhost and I'm just gonna move this to the right so I have a code on this side and we can see the changes and I will also delete all this extra code inside the main file so let's remove that and just add for now a simple header once we add that that says like portfolio website we should automatically when we save the changes you see them so here it is now I'm going to remove this Flex classes that is actually centering it and also the padding so let's remove it save these are the two vs code extensions that I recommend having to make development faster also for following this tutorial but there's a really optional you can still follow through and this is our first one is Tailwind uh it's from like the creators of tailwind and it helps you first it gives you suggestions when you start typing for all the tailing classes just in case you don't remember something and then when you hover over the class it gives you like a CSS that comes with that class and the next one is this react um Snippets uh it's like if you create a lot of components useful because it you can select the command and it will create like a simple component for you going back to our code on page JS file let's we have Flex container as a main container and let's add the flex direction as column to it and we can also change the background by BG and then selecting Tailwind colors like black or we can pass the custom color in the brackets and the hash of the color we're gonna I use directly black but something a little bit lighter and once we update that we don't see the text anymore because it's also color black so let's add a class name text y so it shows up and since we're building out hero section and we'll have other sections on pages it is best to create a separate component for it so I'm going to um cut the header from here and add it into our new component let's save the changes on pages for now and for components we're gonna create a new folder and let's name it components and now let's create a new file that says um hero section as a name and that jsx as an extension this is where the extension comes in I put area FC and creates like a functional component for me then I update um instead of deep we're going to use a section and I'll also paste the header that we um previously copied and let's update also the text itself instead of portfolio website we can add an introduction here and it's not showing up yet because we haven't added this on the page so let's import the component at the top of the page where we have our Imports and then inside main section we can add here section like this so now we are able to see it on the screen we can after that add a container basically if we hover over this we see that what container does is there are larger screens it gives expense up to certain width so it doesn't go full width and it's a good practice usually on the landing pages you notice they don't go full width and to center it because it's not centered by default Intel Wing we add margins Auto which is MX Auto Intel we so this is smaller screens widths but if we extend it further away we're gonna see why border which later on we're gonna update that so it does not show up and for inside the content we can add a padding by P and then the number we can also give padding a Direction so for horizontal have a different size padding and then for PX that would be on the x-axis a larger one let's add a small description inside paragraph so I'm going to paste like a dummy text under H1 and for paragraph let's oh it's also shows up as a black text color update the text color I'm going to paste in custom color that's a little bit more gray than the white header that we have and to the header I'm going to add some margin so we have a space in between header and paragraph and let's increase the size so for text and then there's different sizes I'm going to set XL and as for font that would be extra bold so if we measure it on the larger screen it looks okay but on the smaller one it's a little too big so that's where if you're familiar with media queries it would be similar to using media queries at different breakpoints that is already provided by Tailwind so for larger screens we said LG and text Excel and then by default we give it what we want on smaller screens which is text for excel okay and then we can also do this responsive text sizes for paragraph So for paragraph I'm going to do text um Excel by default and for larger screen sizes let's do a larger for default and then Excel so yeah that looks better now let's take this header section and create a grid like wrap it into a div and that has a class grid and the reason we do this is we're going to have two columns on the larger screen so grid calls 12. the reason I put 12 is because of the division so on the left side we're going to have text and that's going to take like a 7 out of the 12 sections like we I set it for degree through the other section on the image we're going to set the remaining five so we wrapped the first section that we want on the left in Span and then we can also Center it by placing self-center but on small screens we're going to see only one column I have added this image inside public images folder if you want the exact same image you'd be able to download it from GitHub link is in the description of the video and I generated it using my journey um so if you want maybe like what prompts I use I can make another video about it let me know in the comments and I'm gonna go and add that image inside hero section now for the second column that we have so to add images in using xjs we first have to import image at the top from next image and then we created place it wherever we want and for the source I'm gonna change the name because it has spaces and we can't have space in jsx so I'm gonna name it hero image so for sellers we passed the path of where image is placed then we give it an altac um alt text and width and height is required in next name image so I'll set those values to 300 now our image shows up I'm gonna wrap it in another div let's add like um a circle with the background right around it so it looks uh cleaner so I'm gonna take the image add another TV around it and then for creating Circle it's basically circle is rounded um corner so we said round it full uh like border radius set to really high and then we set a background color I'm also going to paste like a past custom color a little bit more gray than the background so we can differentiate it and then we can pass the width and the heights to it 500 400 now we want to Center the image based on its parent and that is where transform translate comes in transform is like a CSS function that can set your um div or image based on how what percent of value you pass to translate which could be either pixels or like a percentage so I want this image to be centered relative to the parent so I pay I said parent position as relative I said image position as absolute then I set it as a transform that that indicates that we want to use transform and afterwards we set the values for translate so it could set a position based on X and Y axis so if we said translate X and negative means it's like minus percent uh one from two it's like minus fifty percent on x-axis and do the same on y-axis and we also set from top 50 from left 50 that should like perfectly Center it uh it just switch the position because we don't have the height and with indicator properly to its parent position but once we update that let's set 500 pixels then it is centered relative to the parent I think it's a little bit a high value so let's fix that and also for smaller screens let's have a smaller value so I'm gonna do 250 for both values and then on larger screens let's have 400. so that looks better and we do the same for uh height on the larger screens now let's also Center our second column by uh Place self Center and as you can see it adjusted itself on the x-axis it cuts centered we can next add a margin um at the top so it has some space in between the hero section and then on larger screens we can set margin to zero because on larger screens they are placed right next to each other so we don't need to push down the image and I'm gonna also add a margin bottom on the paragraph because after that we want to add the buttons so we would have two buttons in here let's create a div and inside here create both of them first is going to be hire me and then the second would be something like we can say download CB and we would pass um some shares that are selling to this buttons now the text is black but I can see it they show up on the screen and let's change the styling so um we're gonna add some paddings on the X first six and then smaller paddings on y that would be three Also let's do rounded also being more like circular and margin right I'm gonna add it only on the first um button and let's paste that stylings on the second button and now we're gonna have them in like different colors so for first first one let's set background white and then on Hover it's usually reset a little bit darker so we're gonna do slate 200 as for the text set it to Black so it um shows up on contrast so that's our higher me and let's continue for this one let's do like just a border white border so for background we set it to transparent and on Hover let's highlight it so background slate 200 they'll be white um I think text we can set that to white as well but let's make darker on the hover like 800 text white then we have a border wind pass border and then border color which is white and let's save this great let's add some margin at the top and if we expand this they should be side by side so I have the app open in the browser and if we expand it we can see this like borders let's work on removing them and we're gonna switch to the page um JS and update it there so the main we can have another um div that has a container set on it so let's create that and broke the hero section in it and the main class will have the background that's uh darker and and we'll apply the rest of the paddings and then the centering of it to The Container uh class so let's add that on that div and this is what we get now let's clean up our uh styling on smaller screens and get familiar with other break points so we're gonna update LG from small which encounters for Styles starring smaller screens so if we expand that we'll see that columns 12 applies on larger range of width and let's also add in between so we have by default text for Excel and for a little bit larger screens we're going to have text five Excel before it gets to even larger font size and by default let's Center the text that's on our hero section and then align your screens let's have text aligned to the left so it looks better as centered but if we expand it it's gonna stay on the left side and let's also make the style font size of paragraphs too big so by default make it smaller we should make buttons forwards on mobile so I'm going to add W slash full and then on SN with fit so that way when we extend it it would be a smaller button size now we'll make buttons gradient and some of the text but this is also optional if you want to keep it simple you don't have to do this part but for those of you who want to follow so to make something gradient in Tailwind reset background gradient and then we pass Direction in this case to P and R so to the right side is going to change color so starting color we pass from Blue then we can also pass via that would add a color stops in between and at the end it's going to end with two pink 500 so that background of first button got updated now let's change text to White so we have enough contrast um great and we'll also make part of this will split like the header and some of it would be gradients or wherever I want to split I'm going to press enter and I will put the first part wrap it into a span so we can add some styles to it and we will set for uh text is a little bit trickier because that we can just apply Color gradient to the text so what we'll do instead is as a color we'll apply transparent then we will basically create a clip out of it so it would have a gradient and text would be basically cut out and we can do the clip by BG clip text and then reset background once again um to gradient the same way we set for buttons we indicate the starting color we indicate the color stop which is optional and then to what color in transitions to which is to Pink 600 so let's save this and we got our first line um turned into a gradient text now let's work on the second button so in this case same way border doesn't have a property for the gradient but we'll kind of create two elements one of them would have a gradient background one of them would be transparent so we would end up getting the result of Border being ready so let's add background of the button container once again gradient um from Blue via purple to Pink and it is not changing the color because I have a typo it should be grid with the eye okay save that and let's add another um span error I'm gonna add that around the text um and we'll add be able to add styles to the span so let's start with giving it a class name and then passing first block position then we'll take the background and set it as same as the color of our background so it has that outline effect and then on Hover we're gonna make it a little bit lighter we also need to make sure that we set border radius same so if we pass also around it full it's gonna have the same borders as its appearance the button and I'm gonna also add the paddings and for the border with since we want it to be one the paddings of outside um element would be one and then minus six minus one five Etc and now I'm gonna remove this white border for the typing effect on our hero section we're going to use this package react type animation and I'm gonna copy the info command npm itself react type animation and here they have an example on how we can use it we can copy this and open vs code and modify it into our preferences so I'm going to go back into hero section component paste it in here so at the top we need the import command and I'm going to leave that but we don't need an extra component we can just use this type animation component inside our hero section so I'm going to cut that out and paste it let's please see where um kind of like second line introducing ourselves so we can include different um things like uh different positions we've held or Etc and the first has to be the word itself and second is the number that you see is duration in milliseconds on how long it runs and then use ref only works on client components so might be that type animation uses to use ref uh so we can turn hero section into client component by adding use client keyword at the top so now if we save that the error is gone and we do see the typing effect it goes over the array that we pass in the sequence now I'm going to remove the style because the font is too big let's save refresh that and okay now it's better I'm also going to add maybe a little bit of space in between the first span and type animation we can do that by Break Tag in the second part of the tutorial now we'll implement this navigation bar with links and the menu on the right side or logo on the left side and we'll also Implement mobile menu which looks uh like this so you'll have a hamburger that opens up and displays the same menu we had and then we can close this out so once again in components I'm gonna create a new file name it nap bar and let's create a functional component and I'll update instead of the we're going to use nav which is an attack for navigation and inside the nav I'm going to create a div let's remove this network word and start um adding elements into the div so first we're gonna have on the left side link and make sure you import link from next just Link at the top for the logo and the href uh we're just gonna add like a slash that goes to like a home page and let's also pass words logo into it um as a second div is where we're going to have our menu items so let's give it a class name menu and also we're gonna make the parent container for this logo and menu items flex and we're gonna spread it out so Flex wrap and items we can Center them as for the Justified that is going to be between so first item would be on the left second all the way on the right we can also Center it and add some padding around so they're not too all the way to the edges and for the link itself self text would be five weeks also quite like pretty large text also color white uh font we're gonna pick semi bold and now to see number on the page I'm gonna go to page JS and edit in there so we import number from components and then we add before we start the hero sections all the way at the top let's save this and go now we are able to see the logo and the navigation bar itself now if we inspect it which we can do by command option I and we hover over we see on the green that is a padding and then menu uh is all the way on the right now let's add uh start filling out the items for the menu for items we're going to create an ordered list and let's add just the first item as an example so at least item Li then inside we have a link href let's do hashtag about that's going to navigate to about section when we build that later on and give the name title about I'm Gonna Save this and also for the menu items itself it's going to be hidden by default because we're going to create a separate menu for mobile so for larger screens medium block with Auto and ID is snap bar and let's add some classes to our link so first we'll have block then we'll add some padding on horizontally and also on the left side the text would be of this like custom hash color which you can copy from my GitHub or add your own uh on small but let's do text Excel uh rounded and then on medium we're gonna have a padding zero and on Hover text white so it pops out and if we go to the application we can see that about show up where the menu is and of course we're gonna add more menu items but since we would have a lot of reusable code for each single item it is the best to create a separate component for it and that's what we're gonna do now so let's go back to our nav bar and we can copy this styling that we did for the link and I'm going to go to components create a new file we're gonna name this nablink.jsx enter and create a functional component and before we add props to it I'm gonna open our application to the side and Below I'm going to move navbar where we create like a first link item so the props that we're going to need first we need the link so we're gonna name it href and then we need the title like the label of the menu item and we're gonna add the return statement installed return statement we can copy this link that we created but it's more hard coded so for the values we're going to update as href and title so it's Dynamic it's getting it from the props and at the top we need to import the link and Below we export default Network and that's it it's pretty simple to create components this way and then reuse them so to use it I'm gonna remove empty block so that it shows up there because we couldn't see the menu on the small screen and to use it import into the component that we want to use it in this case net bar and start creating an array of the props that we're going to pass to the snap link so first is going to be title and then we're gonna have href so these are all the sections that we're going to create so we're adding them into the menu second would be the pro projects and lastly we would have contact Section then we're taking this nav links array and inside nav bar we're gonna map it out and for each item we're gonna return this nav link so let's do that and have links.map and that would be list item key has to be unique so we're gonna pass index to it and then nav link component I'm gonna so instead of passing it as a child we have href that equals to link with that path and then in other props we have title that would equal to link dot um let's see title um we have to double check that um the value names are correct and let's um close that uh we have an error and oh I think I'm missing an extra parenthesis here um another one maybe okay let's save that um and now we have all this uh list items that are loading as links showing up on our screen now let's fix the positioning of the menu items we want them to show up on a row on certain screen sizes so on the UL I'm gonna add a class name Flex I'll also add some padding which for larger screens it's going to be zero and we will also add the flex Direction Flex row let's do that one as well for uh small or maybe a medium screen sizes um so changing that and we'll add a spacing for spacing between Flex item we use space and then the direction and then the number of the space and margin top 10 that looks better for the logo I think the font size is a little bit too big so let's do text Excel for like medium and by default we can do something like text LG and I think that one maybe is too small Excel might be better or 2XL let's see okay yep um that looks better now let's make sure that when we scroll the menu in a bar stays at the top and we can do that by updating styling on the navbar the nav item itself so let's add a class name to make sure the position is fixed we add um fixed and then we Define where is the position so we want from the top to be Zero from left zero right zero that way it would expand for width and stay at the top okay so now it's overlapping and it's goes behind some of the items so we want it to always stay the visible so we're gonna update the index set it to 10 it should be higher than the other items let's also set a background color and for the opacity so we are still able to a little bit see what items are in the back we're gonna set to background opacity 90. okay so now if we scroll it remains and we are able to see it uh for initial like page load we want a hero section and the menu item of course not to be overlapping and we can update that inside the page JS where we can set Argent top of the main container of the page same as the height of the nav bar so they don't overlap and let's remove the padding on the nav bar is too high so I'm gonna remove that save it so now they're not overlapping anymore which is great let's add the padding X so on the sides it's not all the way uh stretched and I meant X not Y and yep that looks better for the icons for mobile menu we're gonna use this package hero icons where we can browse the icons that we want and just copy them and we do need to install the package I believe this is also by creators of 10 wind so that's how I discover so if you go to documentation copy the install command paste it install it and once it is installed we can go to navbar where we're going to have the mobile menu logic and the component and first we have to turn it into a client component because once we add like interactivity like clicking also use State we're going to need to keep track of state if the nav bar menu is open or not um so and um let's add that state um based on that we're going to display different kinds of buttons with different icons and we can go to where uh this menu we want to hide it so we're going to add heat in by default and then on medium to larger screens it's going to be block so now if we minimize the screen it's gone and we can add another div that would instead show up so that would be block by default and then on medium you would be hidden and that would be our kind of like mobile menu so let's Mark Mark the div as that and inside here we're gonna have this conditional logic so if nav bar is open display like the button with um open icon and then if it's not then a different button so let's just add those in both cases and here at the top we still haven't added the icons we want to have so I'm going to import that the first one would be parse 3 icon like hamburger menu and then second would be the one to close so x mark icon and from hero icons react 24 and solid all right and let's um put them inside this button here so first one we're gonna do when it's um not open so bars three icon and then if we don't edit the class names it's not going to show up so we have to give height we have to give a width as well let's save that and add some um styling to the wrapper button itself we're gonna do text slate 200 um give it a color so the icon would take in that color coming from the text class of the button and we can also do make it a flex item centers or icons are centered add some padding is on the sides as well as the top and the bottom but border rounded the reason we're doing we want to have kind of like outlines give border the color which is going to be slate 200 and the same color as the icon and let's add on Hover make it white so text White I am doing the same hover effect on the border as well all right let's save this and we can copy the same Styles pasted for when the number is closed just update the icon it would be like a closing icon and um I think I yeah saw the raw okay that looks good so now we can see the button showing up um on our application but the logic is reversed by default we don't want X to show up we want the open icon but we're gonna update that let's also add some padding from the top so it's not all the way to the end of the screen okay and let's also add the interactivity so when we click we should like be able to close it out and display the other but update the state and for that we go to button on click and as um like callback we're gonna pass set bar open hook and for the value we're gonna set that to true and yeah let's also reverse the logic so if it's not open then display the other one um and same thing for the other button except that the value that you will set would be the opposite so false and now if we click here it's getting uh we can see that the button is getting updated that means the state is also getting updated great and for components we're going to create a new component menu overlay that's gonna be shown up when we switch this menu on like the mobile and press the button and let's create a component for that menu overlay it's also a functional component and we're going to take some of the logic from where we Define inside the nav bar and we are also going to use nav link element because we already created a component we can use it only difference would be the way you would showed up so many overlay container and and props we're gonna taking the links that will layer map it out and let's see how we have inside the nav bar we'll do it in a similar manner so I'm gonna update this to an R unordered list again and the class name for this one it would be also flex but the flex direction is going to be column um adding some padding also items would be a center and let's up remove this text and instead um create with the curly brackets links map it out so you're taking link and the index and then we need to import navalink at the top so we can use it and in here let's um return that with the respective prop so href equals to link path and the title equals to same way we have here link that title and once we add the title let's add just the closing the tag for nav link and also wrap it inside a list item we pass in the key as an index and that should be it for many overlay we just need to import it into another bar and then display it when um the menu is open so it doesn't matter where we uh position it because it should just show up actually it doesn't matter after the logo and the pattern that we have so if not bar open then we're going to display menu overlay if not now and we need to pass the links to it um so that it knows which links to display and that would be the nav links that we created here so let's pass that on save it and now if we open the menu it should show up great I'm just gonna update the opacity so that on um we have like full opacity and that would be inside a nav yeah background opacity let's set it to 100 save that and that looks better moving on to the next part of the tutorial we have About Me section that will implement it in the grid you will have this image for the section as well as the description and this will be a different tabs that could be switched and it will display the content for the respective content of that tab first we'll create a new component name it about section and inside here once we create functional component let's import right away on page JS so we don't forget to import after and it's going to go after hero section okay let's save this and if you open it shows up here the text is black so that's why we don't see it but let's start updating and adding things to the components so going back to about section I'm going to update the div turn into in the section and then inside section I'm going to create a new div so we want to have two columns right and this div would be of grid so let's add uh class name to the section first make the text white for all the um columns and then inside the div we're going to add another class name uh to Mark item as a today we're gonna set it to div and then we Define how many columns we're going to have in this case we're going to have just like two columns that would be grid columns two we're gonna also Define the Gap in between those columns which would be set to 8 and items will be centered also add padding um from the horizontally and vertically and on the larger screens we're gonna have a bigger Gap so Excel Gap 16. and we're gonna also make a smaller padding for a larger padding for larger screens the other way around so small py16 and then Excel px16 let's um save that and we'll add an image on the First Column so let's first import the image this is the image that I have inside my public images folder and I'm gonna add the image tag and as a source indicate the path of my image which is the images and then the name of the image as I mentioned previously we have to pass in width and height in this case we'll set both to 500 and then we once we create the second div it will automatically be considered as a second column of the grid first We'll add like a header of this div about like what this section is about which is about us or about me and after that we're going to add a paragraph a little bit of here where I see could be a description but um I'm just gonna paste in uh dummy text which could be um modified later on based on your experience and so this is how it looks like and then on bigger screens it kind of goes into the center everyone is more spread out but we're gonna fix that um doing the styling first let's update the font sizes of the header and the padding and then we can change the positioning because we're gonna also add like skills and experience section and um yeah so let's start with updating the header I'm gonna push this out so we have more space and maybe open this to the side so we can see what gets changed and for this header let's add a class name we can change the text to size to 4 Excel and then font let's make it bold also text would be white and add some margin bottom um so we have space in between the paragraph and the header as for the paragraph we're gonna change um text color and um decided to also a little bit darker text size would be base and then on a larger screens it would be LG okay um that looks better let's do on a little bit larger this medium is smaller big breakpoint and we're this is after the description we're gonna have uh different tabs basically and we want the tab names to show up in Flex Flex row Direction so that's why we create a wrapper container and inside here we're gonna going to before we create the tab itself I'm gonna show up just like a three spans one would be for skills education and then experience but this could be uh modified as well and let's do some styling for those they show up in a row so add some spacing sensor and then we can add the functionality So based on which tab is open we get that content uh let's add first margin on the right side then font say my bold and then on the hover since it's clickable let's do text white and by defaults the text color would be this uh hash that I'm passing okay so now if I hover over I do get uh White so I only applied for skills for for now but then we can copy and paste it and then board and bottom uh would be purple so this would be for the active element only and in this case once again we're using skills and uh now to be able to I guess switch in between these tabs we want um about a section to be turned into a client component and we would need a state as well to hold information as to which tab is open and for that we would go at the top and add using keyword use client Define this as a client component and we also import from react use State and use transition Hooks and first we create a tab State that's going to hold information which tab is open by default we're going to do skills and then we're also going to import this start transition function from use transition hook that we are going to use inside handle tab change function that takes in the IDE and then starts transition and that transition updates the UI and it updates the state without blocking the UI so State update would be done by set tag and then ID is passed now we will create a new component to handle this like tab button and that will be components a new new file tab button.jsx we create another functional component and for as a we paste um the span that we had previously created we turned that span into a button and as for props it needs to take active and also select type of what happens on on click as well as the children children would be what's displayed inside the button so we're gonna update that skills into a dynamic value of children and the reason we need active is because we have different styles when it's active and when it's not and because we have different styles let's create a variable name it pattern classes and based on the active cell it would have conditional values so if active question mark let's have text white further bottom and then purple as far as if it's not active then the text is going to be different color and we also have some um class names that are shared between the two and those we're going leave it inside the class name and I'll show you guys how first let's remove all these classes we don't need them on the button anymore and for the button we're just gonna pass on click select tab that's coming in as props and inside the button let's create a new paragraph and um Define classes for that one so if I accept this I would need to put the children inside the paragraph and then remove the classes that we already defined um so the only ones we're going to keep is margin right three and then font say my bold because those apply in both cases whether or not it's active or not and let's turn this into a conditional into an object that takes in a variable and then using string weight tools we add a text so yeah this will combine the both and inside going back above section we're gonna import the tab button and going where we have this supposed to have buttons we're gonna add it in there past select tab handle tab change that we defined and we're going to call but handle tab change also takes in the value so we have to use it as a callback function and pass ID for like as a skills and then whether or not if it's selected tab it means um the state tab that we have if it equals to skills then you would be active not selected and inside we give the label which is skills and then close the tab button let's um save that and if we go to our application we should see skills show up the first one is coming from the type button and the other one are just like spans and if we click we do get an error that start transition is not a function I think the order matters so I'm just gonna change these pending first and save it let's do same for the other education and certification so we just have to change all the values accordingly and let's remove this extra span that we have after the tab buttons and save it now let's see if we click on them we don't get error anymore and then they actually get updated um the ones that are clear are set as an active now what we want to do is for the active tab we want to display so each single one of them will have its own content and then this content would be displayed conditionally and let's create a new array name it tab data and this will contain information for every tab what kind of content it can it has so first we will have title skills then ID for skills and then content and this doesn't have to be a string it could be like um you could pass jsx to this field so I'm gonna do an ordered list and as for the list items this would be for all the list of the skills so we're just gonna add in some values in here and we'll copy this first object in the array and modify it we're gonna add two more objects for certification and experience and we'll modify their values so first comes the education and the third day certification the autocomplete in this case is pretty useful because it gives some values we don't have to think about I'll just update the last one okay now that we have this we will take this tab data and after we have balances where we want to show the content so let's scroll down and once the buttons are done we're gonna create a new div and what this div is going to do is it's going to taking um like adding some merges at the top you will find uh the one that has the ID that is same as our tab State that we have in here and based on the state whichever contents ID matches so items in the array then it would display the respective content and if we save this we should see um the education is displayed now the skills and then certificates right so we have some space here that when we update it kind of moves up um so let's fix that like styling in terms of styling um and that would be maybe like the flex position we're gonna do Flex start and let me move this so we can see if it actually once it's updated so that would be for tab buttons justify start save it oh no actually it's not the type button styling it's the the column itself we can turn it into a flag so let's take the div for that um column add a class name we can also add um some margin at the top by default and then on the larger screen it's going to have zero we have to remember that on smaller screens we're gonna have only one column that's why we need the margin between the image at the top and then we make it flux Flex column and height full is what's going to set it to like expand full height and then push it all the way up and let's take a quick look at the mobile views as I said we have a margin here image shows up first full width and then about me like the text and the tabs that we have okay um that's great I'm gonna close out this mobile view now and uh let's go back to our code and add like bullet points to our unordered list which can be done by list disk also add some padding um that's how entailing by default it has no bullets now let's build the project section that contains projects in the grid format and each project card contains the title description we also on Hover have different icons so this would be for the preview link this would be for the GitHub and at the top we have text using which we can filter out the different kinds of projects from the project sections since we are going to have images on the projects I have added some images from my projects that I built on previous tutorials on my channel which you can check it out and those are inside public images folder and then projects as for where we're going to use these images is inside um project section so let's create a new component name a project section and in here we will add like a header at the top and then we'll create that says my projects and we'll create a projects card and those cards will be mapped out in here so let's go ahead and create fed and the project card is going to take few props first one is going to be the image URL like path of the image then we have the title of the project itself and the description for the image this time we're not going to use next.js image we're just gonna take image as like a set it as a background so inside here let's create a separate div for the image and then in the style we're gonna pass a background and in as a string then URL will pass the dynamic image path so that would be image URL let's save this and then we can also add like the background uh style size and that is going to be a cover um and okay I'm gonna move this out class name I can also add other styles like for example the size of the image otherwise it's a div so it's not going to have any height it says height 52 and then on larger screens we're gonna do medium and up that's gonna be 72. inside after this image day we're gonna have another div that's going to have a class name text white and in here will display just header as a title and then paragraph As a description of the project let's see if that let goes go back to project section I'm gonna import project card here at the top and the next thing that I'm gonna paste in here is array of my projects so each array item is going to contain an ID title description image and tags we're gonna go into text a little bit later on and so the images are coming from this Project's images folder and then we'll go inside the component and map those projects data out and then inside the map we take in the project and pass the project information to the project card that we just created so let's as a key we're going to use project.id I have set every idea is unique and so title is going to be a project title then we have uh image description that's a project that's Precision description and finally image that's going to be image URL is going to be projects that image and let's add a closing tag to the project if we go to the application this is how our project listed looks right now so let's go to Project card and update some of the styling starting with adding rounded um corners but we'll add it at the top only for the image and then at the bottom for the other section so it looks like the card itself has rounded corners and not both elements then we're going to update the background color of where we have the text add some padding to it on X4 as well as at at styling to the title so the root set font to excel then we'll update the size weight of the phone to semi bold and um that's got updated we'll move on to adding some margin on the bottom so it's a little bit separated from the paragraph and now updating the styling of paragraph will change the text color make it not white but just a little bit darker than the header um so visual header has to have more significance and now we will add an overlay on this image so when somebody hovers over they're going to be able to see the links that they can click and we'll call this div an overlay will make this parent component relative and overlay position would be absolute and as we have already done this we will position it so it takes up the full width full height and from Top it will be zero left it would be zero and as for background you would give it like a little darker color but we'll set the opacity to Zero by default and it will also be hidden by default it should only appear when when somebody hovers over here so now how can we do that we can mark the parent code so it's hover state is dependent on the parent so we can mark it as a group and then we can say a group on group hover and then change the state like color or Etc so group Dash hover and then State I will set it to flex so it would be hidden by default and it would appear and group power we can also change the opacity so from zero when it's not visible at all we'll set it to 80 percent and for a transition we can set an effect all of all this change of opacity and duration could be 500 milliseconds and if we save this hover over we're going to see that it's the background is going to appear and in the middle of this um background we wanted to darken it because we wanted to add some leaks so let's import uh the icons that we want for these links the ones that I picked was code bracket icon and another one is eye icon so what I was thinking is we show both the GitHub URLs and these icons are coming from here icons and also the preview URLs for your projects and then let's import a link from xjs and this uh both of these icons we're going to place that inside our overlay as I mentioned so let's open that up go inside add a link for now before we add links href I'm going to set it to the default slash otherwise it's going to throw an error then we add an icon in there as for them class names of the icon Heights and widths are both 10 text let's change this to not white but a little bit darker darker color and we also need to have like the coarser pointer so when somebody hovers over they get this uh they know it's clickable and the cursive cursor changes to pointer we also want on Hover it to turn into white and let's do the same for the link as well we'll set the Heights and widths uh to 14 bigger because we want to add a border border which would be two and we'll also make it relative so then we can position the icon in relation to that and the Border color by default would be the same as the icon color although on Hover we're gonna make further also White and let's um save this so yep this shows up on top right corner now we can um make the main overlay as a flex and then item Center and justify Center that should Center our link item okay and it does show up in Center we can also Center the icon inside the link itself that's why we made link relative we're going to set icon to Absolute and then as we did before when we Center things um top 50 at 50 also adding transform Translate and once we add that um there will be minus 50 negative 50 for both X and Y and it shows up a little bit on the side oh I have a typo I'm missing as okay it looks a little bit still push to the side uh let's remove Flex from here because oh and then margin is what we what margins well it's pushing it from this position let's see this and okay so now it's Center great let's work on the hover so we have not added uh oh however it just says white that's why it's not like showing up it should be text white but also not only on icon but whenever the link itself is hover that's when we want to change uh the power state of the icon so right now icon is only getting hard when we're pointing at it so the way it changes once again how we used group but because we have group added on the overlay component itself if you want to have another group we have to give it a knee so I'm going to give it a name link so group slash link and then this hover would only change the state when group slash link is hovered over so let's do to group Dash hover and then slash link the name of the group and now yeah when we hover over the link it also a code bracket icon changes the color and let's add another link as I mentioned for the eye icon only thing I'll change here is the icon and later on we'll have the link as well let's add a margin on the first one on the right side save it so they have a space in between great so yeah we have both links and icons in here and we would have to now actually pass in the values for the link so I'm going to name it git URL and then preview URL in the props of the project card and pass it on to the link and to our second link but if we pass right now we're gonna get an error because we also have to pass it wherever we have defined project car which is in Project section so for every value I'm going to add just the sample URL and you can change those for your project links easily from the project section data array let's save this and also to fix the error inside the project card we have to update the URL so let's save that and oh yeah project.url the preview save that all right great and now if we go scroll over those are uh links and yep so on mobile one card shows up uh per each row let's add the margin top of the header so it has some space between the image so let's make it bigger I'm going to set this to three instead and if we expand this we will see that we have three cards uh per each row with their links on Hover let's add filter text above projects and that will go in inside projects section so the filters will show up under my projects and then you would like clicking on it would filter out what kind of projects there are so let's create some divs visualizer first and then we will create a component on the filtering functionality so first let's start with button although it would include all the projects then I'll add a web and um as a component itself that includes this buttons we're going to make that uh all the text flights so they show up and we'll make it flex and flex direction is going to be row so they show up side by side let's also Center it by justify Center and then item Center as well and add the Gap to uh and so we do have text file already um we can add some comparing on y so let's remove the text Y and okay that looks better uh so let's move on to the button itself uh this is gonna have like an outline uh it's gonna be rounded full and for the Border size it would be two and then border purple 500 will have for the active selected filters let's add some padding so the Border has space around it will increase the text size to Excel and cursor pointer would be also set since it's a button let's change py to three so it's more like not like a circle but more rounded and let's copy this uh styling to the our second pattern which is web and let's instead update The Styling so how we would Style just the one that's not active and we will just change the Border color we're gonna set that same as the text so let's do slate 600. and uh on Hover we can also set that to White however border White and that is how it's looking like now let's move on to creating this buttons into a separate components and then we'll add a function and the state that's going to determine uh which buttons are active so let's create project tag inside components new file new component then I'm gonna open this to this side and copy The Styling for the button and then afterwards make it Dynamic so let's paste that in here and let's determine what props we want to take in so we would need the name of the filter then on click function as well as the if the filter is selected currently and then based on if it's selected or not the styling's gonna vary so let's create a variable button style that's gonna conditionally displace if it's selected we would have this like text y it and Border would be purple 500 then the for the other condition when it's not active we can just copy what we had for the web previously inside project section yeah little darker text and then the border is like 600 okay I'm also going to copy this hover state and let's move this out and I'm going to remove all all in here I'll leave only the default states that are going to be and let's turn this into a template literal that will also accept the dynamic value of pattern Styles variable all right uh now we need to update this hardcoder value of all into a name instead that comes in as a prop and the next thing would be on click itself on the button we're gonna pass on click the prop to its own click uh variable let's save that okay and that should be it for this project tag we can move back to the project section and import project tag at the top foreign we're gonna turn project section into a client component because we need to save the state and do some filtering so that would require that also you state from react and we'll create a new state that will track which filter is selected and by default it is going to have a all as a selection so let's do a tag set tag that equals to Ru State all and this is where the tech field that objects inside this project array have comes in so tag field is an array and it contains all the text that certain project is marked as it could take one or more value since it's an array and now let's create a function that when a tag is selected is going to filter out the projects and I'm going to name this handle texture actually this one will just update the tag so it's going to take in the value for new tag and you will set it a new tag set it current tag to that new tag and we would need to take this handle tag change function and pass it to our project tag component so let's first display the project tag and then do on click handle tag change and we'll do create separate project tags for every text we have like all mobile and Etc and let's pass that on so tag name would be all and then active would be instead of actually we have e selected field and that would equal to condition if tag the state is equal to all then you'll be true if not false since handle Tech change is a function that takes in the value we have to update on click on the right side on project.jsx and we have to pass in the name of the tag itself so it takes in an argument right and project tag knows which uh name we are selecting that's why uh let's duplicate this and do the same for web mobile or any other tags that we want to have the function that we pass Remains the Same Same just the name and the is selected value we do update those all right mobile let's save this let's see if we click on the background this let's change to border instead and I don't see the name it might be that the field oh the prop name is name itself so instead of in Project section we had tag so we can change that to your name and let's save that now the name should be showing upgrade and if we click on it it will select that value that's clicked now when we click we do want this projects to get updated and filtered out right so let's let's write the function for that and we can just write it inside the component previously we would have to create like a use effect or create a separate state for pro like this kind of updates but in like the newer versions We can just directly filter it is it recommended to directly filter it inside the component so project data that filter we're taking the project and if project tag includes the current tag as a state then uh we would it would pass the filter and we take filter projects and map it out instead of just projects data and let's fix the parenthesis save it so now if I click to web it should only show me Web projects and then if I click to mobile only mobile that's great in this part of the video we are going to implement this contact us section that contains some information as to like why they should contact you or social icons and then on the right side we're going to have a form that's going to send an email once user clicks send message and we'll also add this footer at the end of our application for a contact form we are going to use recent to send emails uh and install the module that's called recent as well it's very easy to set it up we have to create an API key if you don't have an account you can create an account or you have to go to recent.com I'm going to include the link and once you're there click add an API key it's going to generate and once you generate that copy it create a new file envy.local in your project and going back to your documentation let's see what we should name to our environment variable so I see that they're using resend API key make sure the name matches and we can press equal and exactly paste your API key which like belongs to you since you'll be sending the emails from your application now we can go to their documentation switch to the app router version and inside app as they mention in here I'm going to create an API folder and then inside API folder we have a send and we for to create the API route we name the file route.js and I am going to paste the code that they have here and let's go over it so first I'm going to comment out email template because we don't have that and so we use the API key that we just added in our environment variables and then we can change the settings from is who is the email sent from and in here you're gonna add the email where you'll be sending the email and then inside the two field there's an array so you can send that to yourself something like if you have support email for example support.com and also the person who showed the interest you can just send us a confirmation like oh you show the interest here Etc I'm just going to put my emails in both of these cases and then for the email template if we take a look at the example that they have on GitHub I'm going to go to app API actually inside component email template.t6 it's just a react component so it's easy to create templates just using a react but for now we don't need the complicated templates I'm going to comment this out and insert instead of this wrapper here I'm just gonna in place create a component and add like a body something that says for example we can have a paragraph tag and then email button let's save that and if we go back to the documentation we have two one more step is verify the domain if you go to domains tab from your admin folder you can say add the domain where you add a domain that you own because you can't really send an emails from I guess Gmail you have to like own the domain and then Gmail or other services and once you add that you'll get this DNS records that you'd have to go back and add in your domain provider now let's create the form itself this would go in components and a new file email section component and then we'll create a functional or I put the ending wrong let's rename it should be jsx inside here we create a functional component name it email section and I'm going to change instead of div we're going to have section first inside this section let's add a class name this would be agreed and on larger screens we're going to have two columns on the left it would be more like an information uh we'll add some margins horizontally and responsiveness also some padding on the top and the bottom and the Gap 4 so that the columns have a gap in between I'm going to remove this default text and let's update the ending tag to section as well inside here we can start working on our first column which as I mentioned is going to be more like informational uh let's add a header I'm using H5 in this case and something that says let's connect let's update the styling of this H5 vertex we're going to set to excel font is going to be bold as for the text color will have white and add some margin so that it has space between a paragraph that would follow up this paragraph is going to be more like a description of what this um form is foreign who should reach out so for text color I'm gonna set a little bit darker than the white and I will also like paste a text that I have written up um let's add first before we add the text margin bottom and then let's add Max with we don't want it to span all the way to the width of the grid so that would be Max with medium and below this description I want to have uh Social Links so we'll create another div let's just name that socials and make it flags and flex direction would be row so they lining up one next to each other and for The Gap we're gonna set that to two now I did have I do have pasted inside public these two switches for icons and the link of where I got them from and also include in the um description so if you want I I'm using GitHub icon and Linkedin icon and importing at the top of the email section but if you want to use like different icons you can also look that up in the same style so yeah let's import it and the path is public then we have the name GitHub public slash GitHub icon SVG and instead of Twitter this should be LinkedIn so I'm gonna change the name in here to import the file name okay uh let me close the file browser for us and also this would be links so let's might as well import the link from next link and we'll also add the image because to use SVG we can display that using image from xjs now let's start creating our link so first we're going to have a link and then inside the link We'll add the image and let's start link href this is where you can add the link to your profile I'm just gonna have a GitHub default and then image this is how we add svgs in xjs as a past we import the SG we give it a name and then inside the source we indicate that name and also add like I'll alt tag for the image and do the same for LinkedIn now that we have this First Column we can start create a second div that would be for the second column and inside this do we'll create a form the direction would be Flex for this form and direction is column with gap S4 and let's start creating first input the before we do the input we have to add a label at the top and to Mark which input this label belongs to we used HTML for props for the label and if we say an email then on the input we would also give that name as an email then we indicate type which is email for actually the type we add that on the input itself and the label I'm going to change it to your email all right let's um crop that out edit on the input and we add an ID that is email as well as the name and required field so if somebody um types it in and has no value it's going to show the error now let's take a look at our email section component and import it on the page JS so that it shows up in our application and I'm going to import the component at the top and afterwards place it after the project section so let's add that in here save it and we're gonna scroll down and we can see the text we have added on the left and the icons as as well as the form with one input element now we can add the other inputs to our form and style it a little bit so going back to the email section where I'm going to add more styling on the label so we can do block first and then add some margin at the bottom as well as the text size which would be small font type would be medium and move on to the input we add a class name and then we change the background color first we're gonna make it a little lighter than the background of the application itself we add a border and the Border color is even going to be lighter shade than the background so we are able to visually see that it's an input and we can also change the placeholder color which is also going to be shade and then the text color is going to be more vibrant as user starts typing inside something to 300 for the size of the text same as label it's going to be small and then we're going to have a rounded corners and add a padding um to the input as well as the width would be for with so let's save this and the background color has an updated so let's see if there is a typo uh oh I'm missing one element okay uh that looks good now we can move on and add some of the other inputs that we need for the contact form so for that I'm going to copy this label and input that we have pasted and modify like the ID and then the label names of the input so the second one is going to be subject of the email that we'll use later on in the API so changing that as well as the type will be text instead and ID so that it matches the label as for the placeholder we can um change that to be something like just saying higher completely remove that let me free save this and look at the screen on the right we'll see that subject input has been added to the form we can fix the gap between the input elements I'm going to set that to 6 and save it it does look that it's adding uh gaps in between all of the like the label and inputs so let's add margin at the bottom of the label actually I'm gonna remove that and instead we'll wrap will wrap label and input into a div and then add margin to the div if that makes sense um so yeah let's try that let's remove the gap now we have more margins but we can do this and cut this place it after the input same for our second input we can wrap that inside a um another div that has class margin B6 save that and add that class also on our first day okay so we have merges and we can add like a smaller margin for example to to the label I'm gonna copy that and do the same on the other label for the subject okay now if you say that that looks better and we can move on to adding a third field but this won't be input this would be text area so that's why I'm not gonna paste that in I'm just gonna add a div with the margin um six same as for the other inputs and start creating the text area so we still need the label HTML form this would be the message class name let's accept the suggestion see if it looks good it would say message and then text area name we have to also match the name to the html4 ID would be same uh columns we don't need to Define columns it's gonna be a pretty small one um save this The Styling would be same as we have for the other elements let's see if it matches it looks like it did see just the same one and place for holder leave your message here or let's talk about and then three dots is what I'm gonna add foreign area let's add a button for the submit of this form so after we have the Steve would come a button the type of it would be submit and we'll write the summit function afterwards uh as for the styling we're gonna add a class name so the background color would be purple uh let's add the P 500 on the hover it's gonna be solid different purple like shade of purple 600 text would be white font size medium will have some paddings on all the sides and the rounded Corners with the width full of the form and then as a label we'll have uh send the message let's save that and that looks good so now let's see how it looks like on the full width and we can add the mesh on like the whatever it says let's connect just to make it more animated and look nicer since we don't really have an image for the contact form so for the mesh it's actually we don't need any svgs or create it in figma we can just use like Tailwind classes to do that it's that simple and after the section I'm gonna create a div just for the mesh and as for the class name the classes that will create the div is going to be um this like background where we pass a cast custom value to the background that's why we have brackets then we're gonna pass radial gradient and we're gonna set two stops so the middle would be the purple and then it would expand to transparent so it's going to create a circle effect and rounded full is also what's going to shape it as a circle we need to pass height and width otherwise it would not show up by default he has no height and for the Z index I'm going to set it to zero so it's kind enough shows up on the background so that's our Circle it's kind of uh blurs doesn't blur out so it has like a strict border so let's add the blur effect I'm going to set the intensity to large and save this so yeah this is what we're looking for is just we're gonna position this move it to the side uh so we're gonna make this section relative and the mesh would be absolute and we'll move this absolute on the left side probably at the top or at the corner so we can add um first from the top it would be positioned full so at the bottom on the left we're gonna have minus four value and then we set transform translate to negative 50 and negative 50 for x and y axis so it goes up to the bottom we can push it out the value a little bit or all the way at the top by setting it to zero Also let's add a class name to the other components Z10 higher than the one we have so they are in front first and let's move it to the bottom actually it does look better and we're gonna add a footer so the white space would be replaced by the footer afterwards or if not we can also push this mesh out if we didn't have footer that would be the solution and let's move on to creating footer now we are going to add a new component we'll name it footer.jsx and once we create a functional component inside we can use HTML tag that is footer instead of div so I'm going to update here that on line five and let's remove this placeholder text let's add a div and inside div on the left side first we're going to have a logo so I'm going to add a span with the text of logo it could be replaced with your image and then on the right side we'll have a paragraph that says all rights reserved this won't be in line yet until we do the styling but first let's go to the page at the uh the footer um and all the way after the um container it's going to be like the last element and then we can open have it open to the side and see the changes so Footers that show up we don't see the text um yet because the color of the text is black I believe so it gets covered by the mesh so yeah if you hover over that's the logo and let's style the footer now so starting off with the footer element itself we're gonna add the class name folder as well as the border the Border color would be the same as the Border we have on our input elements and also on our header and it would only be on the top side then for the inner element we're going to add a container so it has some space around also a little bit more um padding and uh we have to fix so the Border space still shows up on the side so to not have any space around we can say border left set border left as transparent and for the right as transparent as well so that removes that white space and for the text we're gonna set that to color white so yeah now the text shows up um and let's continue with the styling of inner container we're going to set that to flex and justify content in between so we have them spread out on the left and on the right side system we only have two elements for the smaller text on the paragraph we're gonna make it a more gray color so slate 700 and I think the border at the top hasn't really changed the colors it should be not white but like this color that I passed out because we don't have to spell out Topic in past t Okay uh now that looks good and let's make this a little bit lighter I think it looks uh too dark not the other way around so it was 600. and everything else looks good let's update our sand API route so the from email and your personal email also comes in as the environment variable so that in the source code it's not exposed on the client side since it's your information and that we're going to take the variable and pass it in the form field and make sure to add from email in your EnV local file replace it with the email that's going to be you know sending emails then we can try it out using Postman make an API request to localhost API send we should be getting back an ID if email is sent back successfully and also double checking it on my mail I received um this like dummy email that has hello world as a subject because we hard coded these values it sent it but now we can modify it by making it taking request and result and we can read the body of the request and we're gonna make the body have three Fields it's going to be first one email then we also have a subject and the message and once we have access to these three fills we can modify the two to also send an email and then I'll modify the body of the email so it contains a message that user filled out on the form let's save that and add subject as a header we can also add something like I thank you for submitting and Confirmation any way you would build the react component you can do the same in this case and or like message for ourselves maybe you have like multiple contact us forms and different websites and you want to know which one they've submitted so some kind of like identifier you can add that on the next line I'm just gonna say new message submit it and let's go back to email section now we need to connect the part where user submits the form and the API request is sent and we'll do that by creating a function handle submit it's an asynchronous function since it is making a request it takes in an event and we're going to do event prevent default so that the page doesn't get reloaded when the form is submitted uh then next we'll take in the data coming in from the four forms through the event so email would be Eda Target email value subject similarly and the message and next we will create a Json data format out of this data so it would be Json it's that stringify data that way we can't really send Json we have to send the string format of it and we taking we Define the endpoint which is API slash send for the route that we created and finally we send in the request and get back the data so these are the options that I'm gonna pass in on request the method is post we also have headers application Json and as a body we pass in the Json data variable that we created and in the end we get back the result and recall fetch function that's going to make an APA request and give us back the response and we can convert the response in a Json format then we have to read the response parset so if the status if it's successful we can for now just test it out console log that the message has been sent and let's close this function out so yeah we did Define the function but now we have to pass it to the form so that on submit it actually triggers it and the way we do that is make sure the button is of types of meat and on the form we Define on submit and we pass in this function since we have no button and on click event we have to make this component client component and we add use client keyword at the top of the file otherwise we won't be able to use button and we also change in the route we have to get body using a way to request.json I didn't realize that changed in xjs and once we update the route.js one final thing that I like to do usually is to check that the names from the data match the names on the input elements as well otherwise we won't be able to get the data from the event so we take a look at the input and for example this one is missing so I'm going to name add name equals email same thing should go for the subject and the message itself so this one doesn't have it either let me add that and what about the message message does have um name great and for the status um it's we have to get it from the response and it's actually doesn't send the status we can modify that but it sends numbers so usually 200 is number for successful status and then let's log out um let's console log the data that comes in which as we saw in Postman should be ID so if I send message it's going to bring back ID and console log message sent the message that we added okay that's great but what we actually want to do is the user to know that it's been updated so we're gonna add a state to track that using use statehook from react and let's create a new state um this could be constant email submitted like a Boolean value and then set email submitted by default it's going to be a false and then we can take that hook that up there it's the state function there are this state and once it's been submitted we can set it to True inside our handle submit function now on the UI side we add a conditional very female submitted show a text in green color that email was sent successfully now let's test it out so if I press in here send a message oh and then once it's sent the text shows up we are done with the email section and now we will add achievement section this will go below the hero and this is once again optional but it's a good practice to Show achievements in a way of numbers and metrics um two recruiters or other your potential clients so I've pasted my list of achievements and it has two objects have two variables metric and the value value is the number metric is like what measures it and inside the functional component for achievement section we're gonna take in the list and we're gonna map them out and display it is a like a same format and for now before we do the selling let's just display a header as a value and then smaller like a paragraph would be the metric and then we can start adding class names we want this metrics to display in the column Direction and justify Center so they're spread out and some margin to it afterwards for the header we have text white for Excel and bold as for the paragraph the text will be oh lighter darker color than white and um the size would be base all right for the outside wrapper itself we're gonna add some padding as other sections have on larger screen as it's going to have a bigger Gap as well as smaller paddings for smaller screens and we're gonna add another div that's gonna have a border because we don't want the the with the border to span full ways that's why we're adding another one and we'll make it have rounded Corners as well as also having a padding and flex direction to be the row so let's crop this out and wrap the list inside this thief so that it shows up right now we go back to the page and import an achievement section in here and display it um following the hero section as I mentioned all right let's save this go back to our application and we can see the metrics show up in in here now let's make some changes to the hero section give it like a little bit more padding so we don't see the side of it about me and we can also make changes to the header so we're gonna make achievement section padding set to four and then moving on to the hero section let's add the class name to section we're going to set this class name for larger screens padding would be higher so padding y 16 should be fine and then let's also change the text color for our text on the left to be 8xl which is a little bit bigger as you can see it's when the text becomes bigger it's moving on to the next line and the width height is increasing so let's fix that by setting it like on updating deleting first leading is like a height in between the lines and after the leading we're gonna update and the direction we're going to set justify to self start so that way it's aligned on the start and let's give it more space as well so call span I'm gonna set it as eight and for the image which is second uh column it's gonna be four now going to the nav bar let's set a border and give it a little bit more aligned with the other elements as well as add a padding so in here we can change make the Deep container also more padding on larger screens and center the container margin X Auto add a border as I mentioned the order would be the same color as we have order for the achievement section and let's see how it looks like so that does look better and let's update the footer so this one the logo has is over the mesh so it should have a higher index and we can do that by going to the footer file and adding Z10 here save the changes and yep that looks better in order to be able to easily customize colors and our theme in our project we can Define the main colors that we're using inside Kelvin configuration file so first I'm going to import the colors they already have defined and then inside the thing we're gonna add a color section and we'll add two colors of primary and secondary I'm going to set primary to purple and for secondary pink but you can also pick um other colors from the Tailwind set so if we save this right now and missing uh closing bracket so if we receive this the reason for that is that we have only defined two colors primary secondary but we don't have to redefine all the colors we can just uh destructure and add the colors that already exist and on top of that Define these two or as many as you want so we got colors back now in order to be able to with just like one line of codes change the primary and secondary colors we have to everywhere that we have defined this change it so I'm gonna go to um hero section first and where we have instead of purple this is going to be primary and then instead of pink this is going to be secondary as well as for hire me download CV I do have already changed from what I can see and after that let's navigate to project tag here as well it should be set to primary next up we have email section where we have this mesh that is using purple color so go ahead change that to primary and also one thing you can do you can like search uh wherever we're using purple from the search bar inside vs code but I'm gonna walk through everywhere right now so um make sure not to miss it and after email section we have never reach actually that's it and now let's see how easily it is to customize them so for example if I go back to the Tailwind configuration file and if I change this to for example green I'm going to get this and I can change this to yellow so the main color would be green secondary it would be yellow what we can do is that we don't need to use necessarily two colors you can just use one color so I'm gonna set this to Yellow so both of them could be the same and that's how easy it is to change I think the only place we missed it is in here and this is inside tab button um so purple yep let's change it to primary save it and that's it and before we move on to the last part deployment it we're going to do animations and I'm gonna reload the page to show you guys animation so it would be on the hero section as well as on the metric section then we have where the projects get displayed one by one and we have it on education insert like tabs itself where this gets expanded and let's get right into it for implementing animations we will be using these two packages first one is framer motion and then we have react animated numbers and we'll install both of them using npm install and then the names of the packages and even though animations can be done using CSS the reason we are using these packages is that they make it very easy to create animations it's way faster that way and also easier to read especially if you're new to anime animation world and first we're gonna get started with react animated numbers and what we will do is when you go to the website it's going to increment these numbers here in the achievement section so let's navigate to the achievement section and in here uh the module itself is using um use wrap and for that we have to Define our component as a use client and there are some issues with importing the modules so the hack that we have to do is import Dynamic from nextges Dynamic and then create a dynamic version of the component so I'm gonna display now how so it would be um animated numbers and this equals to Dynamic import of the animated numbers react animated numbers which is the name of the module and we start with return and let's wrap this in here answer surrendering false that's what it had issue with basically server side rendering and I'm going to copy this put it inside achievement section but before I do that I'm gonna modify the values because um it takes this package takes in the number and right now I have kind of like string mixed with numbers but what we can do is instead to use still like plus and Etc we can add a new field call it post fix and add that plus that way and I'm going to remove it from here same goes for user maybe we want to do on this case just more realistic number and let's do prefix that would be here hours this could be an exact number for the years we can do value five and oh 17 is not a value intelling let me change it to 16 and I'm gonna remove achievement value instead put our package so for props I'm going to add include comma then we have animate two number achievement value but because we have value as a string we would have to convert it into an integer and we can do that using Parts int so local all set that to en US uh class name we can also update The Styling bypassing Quest name which is great so text White for Excel font bold and then we have config so basically how to configurations that um determine how the animations work and in here we return Mass 1 then friction 100 and if you want to customize it further you can always go to the npm documentation and they do have way more props than I am using here so index plus one and then three all right so this and we can add the prefix and post weeks before and after so achievement prefix and if you reload the page we're gonna see that this numbers increment I'm just going to check so oh I haven't changed so this should be post fix and they should be displayed in a row so I'm going to add Flex Flex row foreign animations on rest of the sections we're going to use framer motions it enables us to determine how we want animation and determine properties so it's less like animated numbers more like we have to build the animations ourselves but still very easy to use so let's start with the animations on hero section and to turn any div section button or any component into an animation there's two steps in bold first we have to import motion if it's not already in that component or in that file from framer motion and then second we taking um the component tag that we want to turn to an animation and we add Motion in front of it so for example if I want to add animations on this thief I'm gonna do motion dot if and right now we won't see any animations because we don't have anything defined but there's um States as to how we can Define animation so one of them is initial and inside the initial we create like an object that defines all the CSS properties we want that div to have initially so if for example if we take property and set it to zero which means that the div is now visible right then we can use a second state which is animate on animate we can set opacity one that way we get the effect of it appearing and it's important to note when this initial clicking initial goes in whenever component gets loaded initially and then comes in anyway and one more thing that we can Define about this is transition so how which this one is optional um transition is uh it has properties as well and in this case I'm going to pick duration and I want to set it to 0.5 so how long would this change from initial to animate going to take and let's see an example so it would be this div that we picked and if I reload it would slowly appear as you can see and we can Define as many properties as we want for example if we wanted to getting have a effect of like increasing in size and initially starting from small we can use property scale uh set it to half and then once it reaches it gets like fully loaded we can set it to one let's save this reload it one more time and now it's gonna like pop up uh and we can copy this animation and use it on the other column that we have in here so if I close this out this is the other day right and let's do this remove that one and since we changed this into motion D we have to change also the ending uh tag but this one okay yep and now um as I said the image also appeared so that's great but if we for example up the add animations on the components that are further down the page and they're not visually visible when the page loads the unless user Scrolls to them the animation still kick in when they load right so about me if I had an appear effect when the page I reload the page or initial loaded the effect will clicking but I will never get to see it so in order to make sure that components animations kick in when they're actually visually visible to the user we should use this hook called use inpig so let's apply it for example on Project section to use using view is basically a hoop computer motion that determines Returns the Boolean of whether or not this component is in the view and then if it is in the view or if it comes in in the view we can add an animation based on that so first we'll need a use ref because we're going to pass the ref to the using View and then we need the motion and the hook that I mentioned itself use in view from frame of motion and after this inside the project section component itself I am going to create a new ref ER that equals to use ref and by default this would be no now next let's create oops not here a constant is um here that equals to using view we're gonna pass the reference to it once true so once uh it comes into view set it to true let's save it and reference we're gonna pass it to reach part of G6 we want to uh uh control and determine if it's in view we want this one so I'm going to add a section here since we already don't have it we can't really apply rack to the fragment and I'll say ref equals to ref so now when it comes to view this value gets set to true and what we want to animate is the project so when it comes to view projects will load one by one foreign inside project car so we have map here right we're gonna add a motion that we and let's actually change this one to unorder the list and add some animations uh for this one since we have different states we can Define the state separately and this this concept is called variant so card variants first date I'm going to do initial and initially I'll also do a slide in effect so this that way I'll pick uh the property y and then I'll set it to 50 and opacity would be zero because it's not visible and on animate I'm gonna take it move it to its position where it's supposed to be and then opacity one close out the card variant and we're taking card variant passage to this one but using variance prop then we Define on which state which property we're using from the variance so I'm going to make it simple and an end it initial and animate that way so on initial will be set initial but on animate depending on if it is in view then repeat uh pass animate if it's not in the view then let's do initial again save it so now if we reload the page once it becomes in view it's supposed to appear and let's see and now it did the animation do one more time okay now since this is a list what I want is the projects to appear one by one and how can I achieve that that would be using a transition controller to transition so we're taking each project and it has a unique Index right and we also pass g equals to index just mark it as unique okay I think we want to do ref on this one because this might be visible but not this one so we don't want it to kick in yet so if I try this again so now it shows up uh and back to the transition we're going to utilize this Index right here to determine the transition and each uh project would be delayed by whatever the index is time certain amount so for example each transition would be of duration 0.3 and it should be delayed by taking in the index and multiplying by the number depending on how what Gap we want to have in between those transitions so if I reload this now they show up one by one great let's uh move let's add like a minimal animation on the tab Button as well so it's going to be well a simple one I'm gonna import the motion then I am going to Define variance so by default which would be zero and then on act T we're gonna set reads to calculate and then oops 100 percent minus 0.75 gram and let's do motion div so we need becomes active we can also depend uh make anime depend on the state so this tab button gets State from parent is a prop active and if it is active then do the animation and if not do default so variance is variance and then class name would be height one background primary uh 500 margin top 2 and margin rate three and we'll remove this uh border below because this will taking the place of the Border we can't really animate the Border but we can animate a div that has a height and just has a color let's save that let's go to about me so now it starts from zero and uh which kind of extends and that's why we did margin right three as well and this one otherwise it would we didn't want it to go forward so it would fill in like with up until like here I will move on to the final piece which is deployment and so you can get host your portfolio and start sharing for the deployment we are using versal and please take a note that uh reversal you're only able to deploy if you have your code as a git repository so you'd have to upload it on GitHub it doesn't have to be public you can do that as a private as well and I'm gonna navigate to versaille right now also if you don't have account creating account and deploying is free so I do have any content I'm going to navigate to the dashboard where there's add new button I'm gonna select project and import I have it connected to git and it will already import your repositories you can select your project and then import for environment variables we would need to set two environment variables that we have in that EnV file otherwise the email part would not work but if you don't have the email piece using recent you can skip this part so you add the name of the variable on the left side and then the value itself for your API Keys as well as for your emails on the right side and after we click deploy it's going to start deployment it takes usually very short time and we'll get the link at the end of the deployment now the status is ready I can click visit and it will take me to the URL of the deployment thank you for watching this tutorial and I look forward to seeing your versions of the portfolio website so make sure to put the links in the comment or jump on our discard server and share it with others
Info
Channel: webdecoded
Views: 232,988
Rating: undefined out of 5
Keywords: nextjs, portfolio website
Id: Kb1f5bvF6f4
Channel Id: undefined
Length: 140min 11sec (8411 seconds)
Published: Sat Sep 02 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.