Build and Deploy an Amazing 3D Developer Portfolio in React with Three.js

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
have you ever looked at jawdropping 3D websites and thought I wish I could build that well today's your lucky day the 3D web world is vast and full of potential but let's face it diving into it can be daunting questions like where do I find quality 3D models or how do I integrate 3js with react might have stopped you in your tracks not having a standout portfolio is holding you back from Landing your dream job so let's fix that hi there and welcome to one of the best projects we've ever created where you'll build an entire 3D portfolio inspired by some of the coolest sites out there check this out a floating island in the sky with a plane and even a magical bird no more endless crawling just drag your mouse and navigate using your keyboard to wander around as you explore the island you'll encounter interactive elements that serve as your portfolio sections for instance reach a water well and a pop-up appears offering a brief intro and a link for more details reach friendly foxes and a new popup giving a brief of your work will appear then reach the plan section and you'll see the contact info link if you click on it you'll be redirected to the contact page and yes there's another 3D Fox that react as you interact with the site start typing it'll start walking stop it will stop as well submit the message and it'll start running isn't that incredible now you might wonder if this is too advanced for you don't sweat it we'll break down everything from react 3 fiber for 3D rendering to Tailwind CSS for styling all in a beginner friendly way by the end you'll become a master for building react you eyes upgraded by react 3 fiber 3D rendering alongside this video I've also prepared a comprehensive 3js cheat sheet that you can use for reference in all of your future 3js videos the link to download the resource entirely for free is in the description and before we Dive Right In a big shout out to emelan CMI our 3js developer if you need expert advice on 3D Web projects his contact is in the description below so so are you ready to build a portfolio that's truly out of this world let's get started now you might be wondering where do I host this incredible portfolio so that everyone can see what I've done see the portfolio you'll buil today isn't just a project it's a career asset it's designed to Showcase everything you're capable of making you an attractive candidate for any job so before we start coding we need to set the foundation I highly recommend hostinger for hostinger 3D portfolio they're offering an amazing Black Friday deal right now and trust me you don't want to miss this when it comes to hosting this 3D portfolio you can go for the Premium plan but in this case I'll go for the business one here's why it's perfect for this project you get up to five times increased performance which is essential for smooth rendering of 3D elements free SSL for https security which builds trust with anyone visiting your portfolio free domain name which gives your portfolio a professional touch and a free CDN which ensures that your 3D portfolio loads quickly further enhancing the user experience this deal won't last forever and because we've partnered with hostinger you get an even bigger discount so visit the link in the description click claim deal and then add to card here we need to choose the period of our hosting and with the crazy discount going on right now I'll definitely choose 48 months to save the most money down below you can choose your payment method and enter your special JavaScript Mastery coupon code which will give you an even bigger discount once you've made your purchase we ready to set everything up and soon get started with building out our portfolio so let's start with hostinger's guided setup we can Skip and create an empty website now let's claim a free domain and if the domain is available finally click continue and then you can click finish setup while our hosting is being set up I just wanted to quickly let you know that there's a GitHub repository containing the entire code for this project so if you ever get stuck just make sure to visit the GitHub page and compare your code with the code that's on here while you're here I would appreciate it if you gave this repository a star now another super important thing to mention to make your learning experience as best as possible is to join our official JavaScript mastery Discord server thousands of developers are constantly communicating right here but even more than that the primary reason to join is that we have created a special 3D portfolio Forum so that whenever you experience any problems this is the best way to get help with that said our hosting has been set up so let's go to the control panel on top we can see another Black Friday Banner which reminded me that we're also running a crazy sale on our next gs14 course nextjs 14 just came out and our course is already up to date right now it is the best course to learn the modern nextjs development so after you're done watching this portfolio you definitely want to increase your skills even further by using nextjs to create phenomenal modern web applications in the course we also introduced a completely new concept active lessons so whenever we have to develop something hard we motivate you to do it on your own by providing you the task examples even the way to think about approaching it resources and then even hints on how to approach it this is the best way to improve your developer mindset so right now or after you're done with building the 3D portfolio go to JS mastery. proo and become a top one nextjs developer and as you can see the 3D portfolio domain is ready with the hosting activated and the only thing it's waiting for is for us to develop the website so without any further Ado let's get started we're going to start from bare Beginnings by first creating an empty folder on our desktop called 3D portfolio once you have it open up your code editor of choice in this case I'm using visual studio code and simply drag and drop your empty folder in once you're there go to the top left View and then terminal this is going to to open up an integrated Visual Studio code terminal which is going to allow us to initialize our project to create our app you can use any tool framework or technology you prefer that can be angular Vue swel kit nextjs or just react in this case I'll be using vit that's going to quickly allow us to spin up a react GS application but in case you want to play with NEX gs14 spel kit or anything else feel free to initialize the project that way and then follow along with what we're doing to get started with react we can just copy this Command right here mpm create V at latest go back to your terminal paste it press slash at the end to install it in the current repository and press enter this is going to ask you what framework do you want to proceed with in this case I'm going to go with plain react and just to keep things simple I'm going to use JavaScript there we go in less than a second our project file have been set up so let's run mpm install this is going to install all the necessary dependencies to run our project and then mpm runev to run it once it loads in less than a second you can run it by holding control or command and then pressing this URL it's going to open it up in your browser which means that we're good to go our base file and folder structure is going to consist of assets app CSS app.jsx index CSS and the main . jsx files there's many files here but as you know I want to teach you not just how to do things but how to approach building everything on your own which is exactly why we're going to completely delete the entire Source folder don't worry we're going to quickly bring it back by creating a new folder called source which now allows us to start from beer Beginnings first every app has to have a starting point which in this case will be a main. jsx file here we can import react Dom from react router Dom then we can say react dom. create root to this root we need to pass the ID of the element we want to connect to in this case it's going to be an element with an ID of root and then we simply want to render our app so what this means is that react is going to hook into a single div on our HTML and then populate with all of the great content we're about to create of course we have to have our app somewhere so let's go into our source and let's create a new app.jsx there you can run a command called ra fce this is a shortcut once you click it it's going to create a base structure of a react application if this didn't work for you you can go to extensions type es7 plus react Redux react native Snippets this is going to allow you to quickly spin up react components and Pages once you have it we can go back to our main and you can double click app and then press command or control space and then press enter or click this first link right here which is going to automatically import the app for you before you save this and test it out there's one change we have to make react D is not coming from react router Dom we'll be using this later on it's coming from react-dom SL client this is what allows us to hook into it this is built right into react now if you save it and check our website you can see a text of app appear on the top left but let's add some styles to style this application we'll be using an incredibly popular Tailwind CSS utility first CSS framework packed with utility classes that's going to allow you to keep writing your jsx as you usually would with automatically providing all the Styles right here and it's not like any UI kit out there it doesn't provide you with predefined components rather it allows you to just use some utilities but then merge them with your own specific design style it can be simple playful elegant brutalist and of course it can be completely custom as well so let's go ahead and set up Tailwind CSS by going to docs and then in quick search we can type V and it's going to show you how to install Tailwind with v so first we have to install dasd Tailwind CSS post CSS and auto prefixer so let's open up our terminal open up a new terminal window and then here you can run mpm install DD for development Tailwind CSS post CSS and auto prefixer once that gets installed you can also initialize tailin CSS by running MPX tailin CSS in it- P this is going to generate a couple of files such as the post CSS config and Tailwind config the next step is to configure our template paths within tawin config so let's copy this content and go into our twin. config here we can replace the content and this allows us to style all of the files within the source folder which is exactly what we want and next we can copy this H1 hello world to test whether our app works we can do it right here within the div inside of our app.jsx indent it properly and it's looking good now if we do it you can notice that this indeed is an H1 but it's not underlined which means that Tailwind CSS properties are not getting recognized so to make it work we have to create a new file called index.css which we have to import within our main. jsx so we can say import /index .css and then in the description down below you can find a link to a GitHub gist there you can find our index.css you can copy all the code and then simply paste it right here don't worry the majority of the styling for this project will still be done completely by you but here we simply have some utility classes that are going to help us style faster such as the class for the input or blue gradient or head text and more importantly we're importing the Tailwind base components and utilities right here this means that now if we go here you should be able to see that the hello world actually changed but to make Tailwind fully cooperate with us we also have to add some additional colors and the way you do that is with the Tailwind config.js file so in the same GitHub gist find that file copy it go to Tailwind Doc config.js and paste it right here this is is going to modify the font families as well as add some special colors so now if we close all the files and simply remain within our app file you can notice that we should have an H1 that says hello world and that's exactly what we can see you can also test out some other properties such as text- r-500 you can immediately notice how my visual studio code recognizes this color and if I hover over it it even gives me a special color it's going to apply and if this popup didn't show up for you that must mean that you don't have the right extensions installed so go to the extensions Tab and then search for Tailwind here you can find Tailwind CSS intellisense and this is phenomenal because even if you're not used to Tailwind if you write code it's going to let you outut of fill and it's also going to show you exactly which CSS properties are being implemented once you hover over the classes great so now now that we have gotten that out of the way the last thing we need to do to get started with coding is reload our terminal by going right here pressing control C and then running mpm runev one more time this is going to reflect all of the changes that have happened and we'll be able to see our hello world in the browser and there we go we have a big bold red underlined hello world so finally let's start turning this into this to do that we can first collapse our browser a bit to the side so we can see our code more clearly and then we can start creating the structure of our grade portfolio hopefully this bird is not going to Annoy Us here and it's going to let us do our own thing but it's such a cool feature how it flies in and flies out so first we have to implement routing because once you click on about or something else a new page opens so we have to have a comprehensive routing system within our react application and we're going to do that with react's most powerful routing Library called react router Dom so let's go to our second terminal and let's run mpm install react-router-dom the way it works is it allows us to import a couple of components such as the route component the browser router component which we can rename as router and a routes component which is coming from react-router-dom once we have have that we can wrap everything in a main section because this is going to be a main part of our application once you have it there we can also give it a class name equal to BG DS slate D300 over 20 and this is nothing more than a special background color if you now save it and go back and reload you cannot see anything yet but now let's add a router a router has to wrap everything in this case it has to wrap our navigation bar which we're going to implement soon and it also has to wrap all of our routes that we can Define like this and of course routes component is the parent element for individual route elements each route has to be a self-closing component that has a path of forward slash in this case and once we're in the forward slash we want to render some kind of a component and in this case it can render just a string of home as you can see we can see the nav bar always and since we're on the forward slash we can see home now the next route we're going to need is going to be a route with a path equal to forward slab about and it's going to render the element that's going to be called about of course right and we have to self close it right here we can duplicate this two more times and we can call the second one projects that's going to render the element of projects and the third one is going to be of course contact that's going to render the element of contact if we now save this you can see navbar home and what do you say that we immediately implement this Navar so we can then navigate across all of these different routes to implement our navbar we'll have to create a new folder called components make sure that it is within the source folder called components this folder is going to have a new file called navbar do jsx and there we can run our afce which is going to create a simple navbar component and we can then go back within the app turn this into a self-closing navbar component double click it press control or command space and just import it automatically if you do that you can see the new naware appear right here which means that now we can go into the Navar and start creating our first component ENT of the day our navbar is going to be an HTML 5 semantic header tag this is important for the SEO so it knows exactly what type of content is within this div it's going to have a class name equal to Heather as well and the first thing we'll show in there is something known as a nav link which you can automatically import from react router Dom this nav link is going to just have a two property meaning once we click it where is it going to point to and this one is going to go to the homepage meaning just forward slash within it we can render Just A P tag that's going to spell out your initials I'm going to do ah in this case it should look something like this then we can style it to look more like this so let's give it a class name equal to w-10 this is going to give it a width of 2.5 Ram or 40 pixels h of 10 also this is going to modify the height we want to make it rounded - LG this is going to give it rounded Corners we can also do a background of white then we need to Center the items within it by saying items Center as well as justify Center and of course we have to give it a flex container so it nicely centers we can give it a font bold and a shadow of MD to make it feel like it's floating on top now let's style the P tag by giving it a class name equal to blue- gradient uncore text if we save this we have something that is really close to what we have on the final website great so now let's go below this nav link and let's create a nav HTML 5 semantic tag let's give it a class name equal to flex text- LG gap of seven between the elements and font Das medium finally we want to create another nav link this nav link is going to go to slab and it's going to of course say about react router Dom really nicely allows us to figure out if this is the current route we're on in that case we can apply some different styles so let's say class name is equal to let's make this dynamic by having a callback function within then we can destructure the is active property and use it to make Styles so we can say if is active is true then we're going to give it a text- blue of 500 else we're going to give it a text- black now if we save this you can see it's currently black but if I click it it's going to be activated the page is going to change to about and it's now blue we can now duplicate this link below change this to projects and then also this can be projects and now we have two nice links and they allow us to switch between about and project and if we click home we have home this is it for our navigation bar now we can go back to our app and we can get started with laying out the main file and folder structure of our application each one of these is going to to be its own page so let's go ahead and create a new folder within our source folder called pages and within it we can create home. jsx inside of which we can run RFC to quickly spin up a react page we can also repeat this for the about. jsx inside of which we can run RFC let's also do this for projects. jsx where we can run rafc e and finally let's do it for the contact page. jsx where we can say RFC now this allows us to close all of these newly created pages of course you can do so manually or you can simply hold control and then press W of course make sure that you're within your Visual Studio code and not Chrome as it would close your window so I just hold control or command and press W now that we have those pages we can import them and use them within our routes let's hold the ALT key on Windows and select all of these line indexs here use control to move over to the start of each string remove the opening string sign and turn it into an opening component sign once again use control to move to the end of the word one more time Arrow right and then simply close all of these components you'll have to do it manually for the other three by providing the ending sign I just wanted to show you a couple of key strokes that I usually use When developing to speed up my development workflow and next we have to import all of these Pages the simplest way to do that is to go within our Pages folder and create a new index.js file within this file we first need to import home fromhome and we can duplicate this three times then we can import about from slab project projects from SL projects and contact fromont finally we can say export and then mention all of these here home about projects and contact this now allows us to go back to the app and at the top we can say import and we can use named Imports to import all of these pages in one line by saying home about projects and contact act coming from that/ Pages our app is back to the functioning State and we can still move across all of these routes and what do you say that we start with the star of our show the homepage so hold control and move into the homepage and let's go ahead and let's start implementing it together to get started with our homepage we can first wrap it in an HTML 5 semantic section tag because that's what it is a section we want to give it a class name equal to a w- fo meaning it's going to take 100% of the width as well as h- screen which is going to make it take 100 view height of the screen and then we want to make it relative this is immediately going to make everything look better then we can create a div within it that's going to have a class name equal to Absolute top -28 left- 0 right- zero and a z index of 10 now within here we can say whatever you want but for now let's say popup you can see it shows up right here let's also give it a flex as well as items Das Center and justify Dash Center and there we go we have our popup does this remind you of anything if you go here this is the popup I'm talking about we'll be able to focus on that later on for now now let's simply comment it out and let's focus on creating our 3D screen everything starts with a canvas component that looks like this for now let's move this a bit up and let's focus on laying down our 3D screen this is the first time we're starting to work with 3D elements so let's install the package we'll use to implement 3D within our react applications to install it we can say mpm install and the package name name is ADD react D3 SL fiber and press enter react 3 fiber is a react renderer for 3js it allows you to build your screen with reusable self-contained components that react to state are interactive and can participate in react ecosystem so for that you're going to need types three if you're using tab script and at react D3 fiber it doesn't have any limitations and it's not slower than plain 3js this is amazing here you can see the Showcase of all of the phenomenal projects that have been built using 3js fiber we have Bruno Simon's phenomenal fishey 3GS Journey connections monitors even and a lot of phenomenal project oh and would you look at that this is the T-shirt configurator so if you if you want to learn even more 3js then definitely check out this project after you're done with the portfolio with that said as you can see 3js and react 3 fiber are definitely the way to go when it comes to creating 3D content and you will learn how to do it in the best way possible now that we have installed react 3 fiber we can import one of the most components from it that's going to be canvas so import canvas from ad react d 3/ fiber and we can use it right here within our section by declaring it as a new component canvas and this is going to act as a root component that sets up our entire 3D scene so all 3D objects and lights will be rendered within this canvas and as discussed it's a part of the react 3 fiber Library a react renderer for 3js we can give it a class name equal to w- full for full width h- screen for full height BG D transparent and that's it for now we also need to Define cameras properties so let's put this in a new line and let's define camera we can provide near and far properties objects closer to the camera than near property in this case 0.1 won't be rendered same thing for the Far So OB that are farther away from 1,000 won't be rendered as well so we're just setting up our playing ground next we'll be using react suspense component which we can import from react the suspense is used as the wrapper so right here we can say suspense and create it as a wrapper and it's used for rendering the loading screen so we can say a fullback right here is equal to a self-closing loader component and this is of course a component we have to import from components loader. jsx we can run RFC go back and then import it by double clicking and then pressing do/ components loader which is going to import it at the top so what this does is while the 3D model is loading which is going to be quite optimized but still some loading time will be required it's going to show the loader instead so let's go to loader. jsx and let's implement this loader here we can create a div that's going to have a class name equal to flex justify Das Center and items D center right within it we want to create a new self-closing div that's going to act as a spinner so let's give it a class name equal to width of 20 so w20 h of 20 Border Das 2 border Das opacity -20 border Das blue -500 border DT for top- blue 500 rounded Das full and animate Dash spin this is going to be our loader we can see it on the Finish side if I reload it appears really quickly as our model is so efficient but here's the thing whenever you're rendering something within a c canvas it has to be a special 3D property so to turn this what is not 3D into something 3D we have to use react 3 Dre Dre is an addition to react 3 fiber and it's a growing collection of useful helpers and fully functional readymade abstractions for react 3 fiber the only thing you have to do is install it and then you can use all of these helpers they help you with cameras controls gizmos subtractions shaders and so much more so we can install it by going to our terminal and running mpm install add react D3 SLR once it gets installed you can simply import something known as HTML from at react D3 Dre and then we need to wrap this entire thing into an HTML tag that way we're not going to have any issues with the 3D canvas we're in and now that we have our loader let's light up our scene so we can see the model that we're going to render soon there are different kinds of Lights in 3D scenes and without lighting uper scene we wouldn't be able to see the 3D models clearly so let's explain all different kinds of Lights there are so this is a mini course in Lighting in 3D first there is directional light so we can create a new self-closing directional light component there's also ambient light so we can create an ambient light there is a point light which we can also create as a self-closing component there's a spotl as well and there's the hemisphere light looking like this now if you just add them they're not going to do anything on their own but as soon as we add our 3D Island we're going to go and Implement each one of these and you'll be able to directly see how it impacts the model that it provides the lights for so let's start with one of the most important aspects of building 3D websites and that is finding quality 3D models in this case we're using a website called sketch faab it has a lot of completely free 3D models that you can download and use within your applications and the link down below are going to be the models that we'll use as you can see we'll be using a model called foxes Island and it looks great it even has those little points that we're going to then display some additional informations on first you need to log in or sign up the link is going to be down in the description and once you're in you can click download 3D model and you can download a glb once you download it you can go to a special website linked below we'll use this website to help us load glb models into our 3js scene usually it's a lot of work configuring and animating all of our models meshes but luckily react 3GS fiber team created an app that turns glb files into jsx components so simply open it up the link is down in the description and then drag and drop your Island here it's going to load for a second and immediately you'll be able to see your Island appear right here it's even going to nicely scroll through it now one thing I want to mention here is that there's a lot of meshes right here so you can see it has some things on the bottom it has some additional meshes right here so it's a bit more complicated than we need it to be so what we've done is cleaned up this model a bit by removing some of the Shadow overcasts as well as some meshes to make it simpler and make it fit our portfolio so in the description down below you'll be able to find a modified and cleaned up island. glb file you can download that one in of the one you've downloaded before and then drag and drop it here and you'll be able to see the difference it loads much more quickly it rotates nicely and it has fewer lines of code as we clean it up to contain only what is necessary so this model is going to be down in the description feel free to download it drag and drop it into this website and then simply copy this entire file by going to exports and then copy to clipboard once you do it we can go right here here and then create a new folder called models and create a new file within it called island. jsx and paste what you copied of course we'll have to turn this into a component so we can call it const island is equal to a functional component and then at the bottom we can just say export default Island then you're going to notice that it's complaining a bit saying that there's an unknown property called geometry so let's go all the way to the top and let's import a couple of things we'll have to import the use ref as well as the use effect coming from react we'll have to import use gltf from react 3 Dre and we'll have to import use frame as well as use three coming from add react D3 SL fiber finally we'll need to import the entire island scene by saying import island scene from assets sl3d SL island. GB so do you remember that glb model that you copied right here into this website well I'm going to also provide it to you in a zipped format with all of the other 3D models will'll be using across this project so down in the description you'll find the zipped asset folder download it unzip it and then paste it right here within the source folder you'll find a lot of stuff here like all of the glb models some icons images favicon and even a song that you can play once you have that you can wrap all of this in an a. group so this is a group element and this a is going to becoming from something completely new we can import it a from add react-spring sl3 this is a new package we'll have to install to enable animations yep we won't just have static 3D models we can also say mpm install add react-spring 3 and that's going to allow us to animate our applications as well so instead of just simply having the regular group we can say a that group which means animated then we have all of these meshes inside of it and we don't necessar need to cast Shadows or receive Shadows so let's select it press control or command F click this arrow and then replace all instances with nothing this is going to remove the cast Shadow and we can do the same with receive Shadow as well finally we can remove the dispose of null and just say ref is equal to Island ref which we can create right here at the top by saying const Island ref is equal to use ref so we can refer to it later on so now we have almost everything we need we can just structure this to look a bit better there we go we don't have too many meshes but all of these meshes together are soon going to display our 3D Island we don't have to use this gltf preload so we can remove it and you see all of those warnings that we have if you hover over it that's coming from es lint it's just a bit confused because it doesn't know 3js so what you have to do is hover over it say quick Quick Fix and then disabled react no unknown property for the entire file once you do it it's going to look good and we're going to have our Island now let's go back to our home and right here below our lights let's render a self-closing island component by importing it from the models so we can say at the top import Island from SL models Island and save the file if we now go back to our current website you can see that it file to parse source for the import analysis because the content contains invalid JS syntax one of the reasons why we're seeing this is because I imported it as a named import but rather it's going to be a default import so we have to do this but the second reason is we have to go into V config and we have to add assets include make this an array and say everything everything SL everything meaning a star. glb so assets are going to include glb files as well once you save it it's going to load it up but now we don't see anything so let's go to our console and let's see what errors do we have could not load island. glb interesting then what else do we have also the same thing so it cannot load island. glb so let's go to our Island and here we're trying to load the island scene from 3D acids Island which points to the right 3D acid so this looks good to me but it's may be trying to get it from here and we definitely have to modify this so we can simply refer to the island scene that we're importing at the top right here and if you save this you'll be able to see something that looks like this which is not exactly what we were hoping for but that's okay that's because we have to modify the position of our model and modifying 3D elements positions rotations and scaling is super important that's the main thing when working with 3D objects so now let's turn this piece of nothing into an island to do that we can go back home and then in the home we can create a new function const adjust Island for screen size yep we're not going to forget this we want to make our application look good on all different kinds of devices so we're going to have a function to see the screen size and then modify the scale in position accordingly so let's define variables let screen scale as well as screen position for now just declared and then we can have an if statement and if window. inner width is lower than 768 in that case we can set the screen scale to be equal to an array of 0.9 0.9 and 0.9 similar with the screen position we can set that to be equal to an array equal to zero for the xais - 6.5 for the y axis and then minus 43 for the Z axis so there are three axes when it comes to positioning elements of the screen and we can have an lse statement copy this and then modify it right here by saying 11 one because we're going to be on a larger screen then so we can have the full size model and the position is going to be the same which means that we can simply declare it above let screen scale is null let screen position is equal to this array right here and this means we don't have to modify it for each and every one finally we can return an array that contains the screen scale as well as well as the screen position and now we can call this function right here on top by saying const Island scale and Island position is equal to adjust islands for screen size and now we can use those two variables to pass them into our Island as props so we're going to pass the position equal to Island position and the scale equal to Island scale while we're here we can also Define the default rotation so right here we can also add the rotation saying let rotation is equal to an array of 0.1 4.7 and zero I found these values to work the best and finally we can pass that as the third parameter right here to this array and we can also extract it right from here rotation and now we can say rotation is equal to Island rotation which we can call it right here at the top Island rotation and would you look at that we can already see our great looking Island this is great of course the lighting is a bit off and we cannot move it around but this is just the beginning so what do you say that now we implement the lighting to make this all look so much more realistic believe it or not in the 3D World Lighting plays a big role so so let's focus on the directional Lighting First a directional light simulates the light coming from a distant Source like the Sun so let's focus on adding the sunlight to our Island we can do that by saying position is equal to an array of 1 one one and then we can add an intensity of two if we save this you can see that the lighting has changed and right now es length is again complaining so what we might need to do is go into eslint RC and then under ignore patterns we can add source and this is now going to ignore all the files within the source so we no longer have those es lint warnings and this is looking good of course if you increase the intensity to something like five you can see it's much brighter zero it's darker but you can see how it looks really cartoonish right now if it's zero but if we do two it gets much more detailed you can also try moving the sun right here by doing something like 10 and you can see it moves the position of the island you can also move it on this axis there we go so now it's much more Central and you can also change it here as well so playing with the directional light is really important on how you want your scene to be perceived so feel free to play with it a bit more now let's focus on the ambient light the ambient light illuminates all objects in the scene equally without casting Shadows so we don't have to declare the position here but we can add an intensity of about 0.5 and you can see this is just going to make it look a bit better you can of course do two which is too bright again so I think that 0.5 works well the next light we have is the point light a point light emits lights in all directions from a single point in this case we won't need it because we're outside we have the sun and the ambient light so we can remove it next next we have the spotlight the spotlight is similar to the point light in a sense that it emits light from One Direction but in this case in shape of a cone so you can also provide an angle in this case we won't be needing it and finally there's the hemisphere light it illuminates the scene with a gradient so here you can even Define something known as a sky Coler and in this case let's go with a Coler something like hash B1 e E1 FF let's give it a ground color as well of something like # z0000 which is black and let's give it an intensity of one and now would you look at that how much more detail can we now see check the difference if I comment it and if I bring it back it's looking really really good let's try one more time if I remove it and reload and then if I bring bring it back there we go it's looking good great so our island is there and it's nicely lit now let's create some sky at the background so it looks even better it is a flying Island after all right so the way we're going to add sky is we can create a new component right here within models called sky. jsx and run RFC then we can go back to home and right here above of the island we can declare the sky self-closing component and we can import it from Models Sky that's going to immediately break everything but no worries because now we can go into the sky and we can turn this div into a mesh which is going to make everything work there we go and this mesh is going to use something known as a primitive element our island is not a primitive element it contains of a lot of different meshes that together create the island and we need to do it this way as we need to interact with it scroll through it drag and drop do something at specific elements and so much more but our sky is going to be primitive that means that we can simply consume the 3D model that we're going to use so the way that's going to work is you can say const sky is equal to use gltf which you can import from react 3r and then here you need to pass the Sky scene which you can import Sky scene from. SL assets for3d SL sky. GB and you can simply use it within here once you do that you can declare it as an object Within A Primitive so we can define a self-closing primitive with an object equal to sky. scene and if you save it you can see the sky appear in the background this is great now please let me know why didn't we just use a regular image as the background for this island the reason is as we're going to scroll through it we need to feel like we're inside of a sphere because as you rotate the clouds need to rotate as well that's why we use another 3D object this is it for the sky for now later on we're going to make it rotate and we have a couple of other elements here as well of course we need our plane and we need our bird that nicely flies in from time to time so how do we import those as well well let's go ahead and create two new models right here we're going to call it bird. jsx inside of which we can run rafc and we're going to create a plane. jsx inside of which we can run our fce as well now we can simply import the bird right here above the sky so we can say bird and we need to import it from Models so let's go to the top and say bird coming from Models bird and then we also need to get the plane which is coming from model's plane let's also use the plane right here below the island there we go and of course it's going to break because the bird is a div and we need to use a mesh if we're inside of the canvas so right here we can define a new mesh as we did before and we need to do the same thing for the plane so we can Define it as a mesh just so we can see our app again there we go so let's start focusing on the bird first we can do a similar thing we've done before and that is import the bird scene coming from assets sl3d SLB bird. glb we can then use it right here by saying const we can extract the the scene as well as animations is equal to use gltf bird scene and then we can again use a primitive object right here but this time it's going to render the scene that is now a bird and of course we have to import use gtf from react treat Ray save it and where is the bird I'm guessing it's hiding somewhere but we can make it show by adding a position to this mesh so the position is going to be minus5 two and then one and scale is going to be equal to let's make it small 0.3 0.3 and 0.003 one more time now if we move the position a bit to something like five we still cannot see it what about 10 no it's still not there now the reason why we cannot see the bird yet is because it's outside of the screen if I enlarge it there we go see because it starts from here and then soon enough we're going to animate it to fly closer to the island now let's collapse it this is good for now but as I said soon enough we're going to animated as well and let's do a similar thing for the plane so in the plane we can again import the plane scene coming from SL assets sl3d for SL plan. glb we can extract the scene by saying const scene and animations is equal to use gltf which we can import and then we can pass the plane scene and then we can declare it as a primitive within a mesh right here primitive object scene and there we go you can see that it's looking at us right now it's flying towards us but the beauty of 3D models is that you can turn the them around and position them however you want to so later on it's going to look like this and we'll be able to move it across the screen so now that we have all of the most important models within our most important page which is the homepage we can slowly start making them more interactive so far we have just lit them up created the island and put all the elements here but the goal is to make them all look great together and to be able to move across the actual Island to get some things on top so how are we going to do that well let's start by implementing the dragging rotation that's one of the primary features and for that I do have to give props to Joshua for creating Joshua's world this application has been an inspiration for 3D Developers for decades and he has implemented this way of moving through the 3D circular Island but here's the key part everybody has been looking at this portfolio and adir iring it but so far nobody has created a tutorial which is exactly what I wanted to do with this 3D World so let's go ahead and focus on the rotation next first we can create a new use State at the top use State use State snippet we can call it is rotating and set is rotating at the start set to false and of course we have to import Ed state from react which we can do right here now the only thing we're going to use this for is to get to this drag and drop feature so once you click it it's going to turn into an actual draggable Mouse not just the typical cursor and you can even click on it and it's going to look like you're holding it so that's the whole point so now we can do that by using the use effect now how can we do that well really simply in our canvas we can turn this class to Dynamic class like so and then at the end we can say if is rotating in that case cursor Dash grabbing else we're going to have a cursor Dash grab meaning we can grab it for the first time so if we save this you can now see a cursor of grabbing and of course we'll have to pass this over to our Island so we know when we're doing something so alongside these three we can pass is rotating set to is rotating set is rotating to set is rotating and that's it for now but now this plane is really bothering me it looks like it's going to jump at me so let's go ahead and modify its position as well we can do that by creating another function just like this one adjust Island for screen size we can duplicate that right here below and rename it to adjust plane for screen size here we don't have to deal with the rotation yet so we're just going to have screen scale and Screen position here both values are going to be set to undefined at the start so we can simply declare them like this for a smaller screens screen scale is going to be 1.5 all across the board so we can do it like this and Screen position is going to be equal to 0 minus 1.5 and 0er on larger screens we can have 333 which is a bit of a larger size and then screen position can be set to 2 -4 and -4 those values make it look better on larger screens now we can also call this similar to as you would call A Hook by saying const plane scale plane position is equal to adjust plane for screen size and we can just collapse those two so we don't have to look at them and we have a bit of a cleaner working environment there we go and now we can simply pass those two as props to our plane the way you would do that is similar we have our Island and then we pass the plane scale equal to plane scale and also plane position equal to plane position we can also pass is rotating right here because if we're rotating we want to move the propeller and the rotation can be fixed so we can say rotation is 0 20 0 now this is going to break it because in our adjust plane I have a typo screen position right here and then we don't need to return rotation in this case and I also have to correct our screen position here at the end and there we go we can see our plane now why didn't they change the position and rotation and all those things yet well that's because we're simply passing these as props but we are yet to accept them within the plane model right here so the way we can do that is we can accept all of the props for example is rotate in as well as all the other props which we can simply spread right here now why would we spread the props that's because we can simply pass them into our mesh so right here dot do dot props and now you can see our plane is looking good of course we'll have to modify it a bit later on to look like this but for now it's much better than before it's not coming towards us so now let's go back to the home and let's get back to what we were working on which is allowing the rotation of the island to do that we can now go into the island and do the same thing we can accept all of those props by saying is rotating set is rotating and then do do dot props to spread them right here once you do that we have to get access to the 3js renderer and viewport and the way we do that is by saying const GS as well as the viewport is equal to use three like so it's a hook then we have to use a ref to get the last Mouse position so let's say const last X meaning horizontal position is equal to use ref 0 we can do the same for the rotation speed by saying const rotation speed is equal to use ref zero and then we can use something known as a damping Factor const damping factor which is going to be set to 0.95 this is going to play an important role of kind of when you scroll it how fast does it move and how does it continue moving afterwards which is pretty cool now there will have to be three different functions the first one is what happens once you press the mouse down down right so now we're so here we're not just clicking we have to click it hold it when it flies and then we release it so there has to be a function for each one of these little actions we can say const handle pointer down is equal to where we get an event and first things first we want to stop the event propagation so e. stop propagation this means that the mouse click is only going to do what it does in this function and it won't touch any other elements or functions on the screen we can also do e. prevent default so we won't simply reload the page or do anything like that and finally we want to turn on the set is rotating because we have started to hold it similarly we want to repeat this function duplicated two more times so 1 2 the second time we're going to say handle pointer up so this is once we have actually released the mouse and then we want to set rotating to false and the last one is handle pointer move so when we simply move it and there we don't want to touch is rotating so now each one of these functions will also have to have some additional logic once we press the pointer down we need to figure out if it's a touch event on a phone or a mouse event const client X is equal to event. touches if it is an event touches then we want to get the event. touches 0. client X else we want to get event. Centex so once again it depends on what kind of a click it is and of course it's going to be just e because we have named it e as an event right here at the top finally we want to store the last position of the X right here last x. current is client X and we can collapse our handle pointer down now on one up we want to do something similar so let's go ahead and copy this client X and paste it in the handle pointer up but then we want to calculate the change in the horizontal position by saying cons Delta often known as a change that's going to be equal to client x minus last x. current divided by the viewport do width so yes we do have to do just a bit of math but this is more or less it finally we also want to update the islands rotation based on the mouse so we can say Island ref do current. rotation doy meaning top and bottom plus equal to Delta which is the difference times a specific factor for example 0.01 times math. pi because we're working with a circle here finally we want to up update the reference for the last client X position by saying class x. current is equal to client X and then we want to update the rotation speed by saying rotation speed. current is equal to this difference time 0.01 time math that Pi so all of this fits in a couple of lines I know it might be a bit different and we are using some math here but hopefully it's all going to make sense soon and now we can close the handle pointer up and the handle pointer move only wants to happen if we are rotating so if it is rotating then we can simply call handle pointer up so it's doing the same thing as the handle pointer up like this with passing the event right into it we can also do it in one line like so more on that soon but now it's time to put all of these functions to good use so let's create a new use effect this use effect has a cbook function and it's going to happen whenever one of the variables in the dependency array changes in this case we can put a lot of things here when GL changes when the handle pointer Down Changes which shouldn't really change because it's a function declaration but it's good to list them here pointer up and handle pointer move as well so essentially it's not going to change a lot we need to do this only at the start so what do we want to do we want to add event listeners for all pointers by saying document. add event listener pointer up handle pointer up pointer down handle pointer down pointer move same thing you want to call it you can see the GitHub copilot did it for me here because it's really repetitive I'm using this great GitHub copilot extension that simply autofills all of your code so whenever you see some crazy suggestions in real time that's co-pilot doing the coding for me it is paid I'm not getting sponsored for saying this but I highly recommend you to try it out I do think they have a free month trial anyway you can type this out just do the first one and then copy a couple more so this is adding events and also removing them from the canvas once we exit the page and still this is not going to allow us to move more than that later but while we're here let's also add the ability to move with the keyboard to do that we can say con handle key down is equal to an event where if e. key is equal to Arrow left and if we're not rotating so if not is rotating we want to set is rotating to true and we want to change the island ref current. rotation doy plus equal to 0.01 time math that Pi since it is a circle so that's going to look like this else if the arrow is right we want to do the same thing but reverse so else if e. key is equal to Arrow right if it's not rotating set rotating to true and then move it by minus equal to minus1 and finally what happens if we handle a key up so we can say const handle key up well if e. key Arrow left or e. key Arrow right is keyed up in that case we simply want to stop rotating so we can set it to false and we also need to add the event listeners for these properties as well so document that ad event listener key down as well as key up and we want to remove them right here at the end now we can collapse this use effect and all the functions we have created and put them to good use the way we're going to put all of this to action is going to be using a special you can call it a hook called use frame this use frame is going to accept a callback function that's going to happen on every single frame and this Hook is coming from react 3 fiber directly now this function is going to apply on every single frame so here we can check if it's not rotating so if not is rotating then we can apply the damping factor which means that it's going going to make the plane roll smoother so we can say rotation speed do current times equal to damping Factor so it's going to get slower and slower until it slows down then we want to completely stop the rotation if the speed is low so we can say if math. absolute rotation speed. current is lower than or equal to 0.001 then we want to Simply set it to zero now below this outside if not this inner one but outside if we are rotating which we can add an else here then we have to get the current rotation so con rotation is equal to Island ref. current. rotation doy and now I want to be completely honest with you I have a block of code that you'll be able to copy from the GitHub J down below so let's copy and paste it here together it contains a very long comment saying a lot of things right here it says that we have to normalize the rotation value to ensure it stays within the same range from 0 to 2 * mt. pi the goal of this is to ensure that the rotation value remains within a specific range to prevent potential issues with very with very large or negative rotation values and then here's a step-by-step explanation and the way that the math is mathing uh This was done for me by Chad GPT I am in no way a math or 3js expert so this was really helpful to ensure that the application behaves smoothly and then here we're also setting current stages and that's something that's going to allow us to be at different stages for example we start at stage zero and then we show this line right here once we move to stage one we show a different one so that's the only think it is but yeah in general this was only to normalize the way we drag and drop our plane one thing that I've missed right here in this use effect is to add a con canvas is equal to g.d element what I've done here is I've only attached these elements to the regular Dom but we have to attach them to a canvas instead because once we click here we're not touching the regular Dom we're touching the canvas remember we're wrapping everything inside of a canvas so we have to define the canvas and then for these first three we have to say canvas. add element and then canvas. remove element because we're not touching the screen we're touching the canvas but still if you try to scroll it's not going to do its work so we have to look into the handle pointer up and I think I've made a mistake here the only thing that the handle pointer up has to do is stop the rotation nothing else so that's it this has to happen within the handle move so we can copy all of this delete it from here and then move it to the handle pointer move instead of this handle pointer up so we can say if is rotating and then we can paste all of these other things and since it's still not working we can go ahead and go inspect and go to the console reload the page and you can see e. stop pration is not a function here it's supposed to say propagation oh my God there we go we got it and we have to fix it in all three places propagation there we go and now if you reload you can see that it actually moves around so we can move it around with our Mouse as well as with the key presses I know I know it doesn't look like it does on the final website but don't worry we're going to get there one thing we have to do is also collapse all of these functions for easier View and then we can go into our use frame and here we can use this rotation speed to slow it down the way to do that is say Island ref. current. rotation doy plus equal to rotation speed do current so this is going to apply that slowing down of the plane as we scroll so now if I move it you can see how much more smooth it is there we go that's much much better we can also expand it to admire it in its full Glory there we go this is looking good but of course our plane is looking a bit plain uh what we can do is we can activate it so for now we're done with the island let's go to our home and let's move into our plane working with our plane is going to be much simpler since it's a primitive so what we have to do is load up the scene and animations we also have to load up something known as actions which is equal to use animations coming from react tree Dre to which we have to pass the animations and then a ref to the original mesh so here we can say const ref is equal to we can import use ref from react and now we can attach it right here by saying ref is equal equal to ref now we have access to these actions and based off of the actions we can play a model some models come with some pre-play actions such as the rotating blade here for this plane so let's use a use effect right here we can create a callback function and as a dependency array we can say actions and is rotating we're passing that through props then if it is rotating we can do something like actions take 001 doplay and else we can do something like actions take 001 do stop so this is going to turn on our plane and turn it off as you can see currently we have an error but we can fix it by going to inspect console and we can see what's happening in saying that use effect is not defined that's a simple fix we can simply import it right right here from react by saying use effect and now if you drag and draw well it's not spinning yet so let's figure out why that is the case we are calling these actions take 001 and calling the dot play on it actions is directly taking the animations from our original plane scene and a reference to the model and then the plane is coming from assets 3D plane glb so everything is looking good here but maybe is rotating is not working so let's see if we're properly passing it is rotating is rotating so what we can do is simply consol log that is rotating and then see if we're getting true and false as we turn it on and off so we can go right here to the console and we can see Set current stage is not defined so this is breaking within our I believe Island that's that's going to be for these popups that appear we need to know on which one are we on so that's a simple fix right at the top we can declare a new use State and say current stage and Set current stage at the start equal to one then we can pass that over to the island Set current stage and that can be equal to set current stage so now as we move through it these errors should no longer occur and as we move the plane oh Set current stage is still not defined that's because we are passing it but we have to accept it right here by saying Set current stage coming from props if we now reload hopefully won't have any more errors and as you scroll it really looks like it's flying through the air this is amazing now to make this even more realistic what we can do is also rotate the sky so we can say in the sky if is rotating is equal to is rotating we can move into the sky and accept this prop right here is rotating we can define a ref by importing use ref from react as well as use frame remember that function it allows us to do something on each and every frame and that is coming from react 3 fiber now let's define the sky ref is equal to use ref we can attach it to this mesh by saying const ref by saying ref is equal to Sky ref and now we can use the use frame function give it a callback function and say if is rotating then we can say skyre do current. rotation do y plus equal to 0.25 time the Delta and the Delta comes directly as the second argument to our use frame function or the parameter so we can just get it from here now if we rotate you can see the sky is moving as well you can make it move slower or Faster by modifying this Factor right here this is way too fast if we do something like 0.15 this is going to look good and now we can see we're flying through the air as the sky and the cloud moves as well as the island and the plane how cool is this so now we're done with all of the major parts of our homepage but of course we don't have this beautiful bird flying in so what do you say that we do the bird next let's hop into the bird and this is going to be a real test for you to see if you've learned something about 3js we're going to use similar things we've used so far we're going to import use ref from react as well as use effect we can immediately declare that ref by saying con bird ref is equal to use ref and we can add it to our mesh by saying ref is equal to bird ref we can put this in multiple lines so it's easier to see now we're going to start the animation by turning on this use effect so whenever it just opens that means on an empty dependency array we simply want to trigger a specific action and to get to the actions for a specific 3D model you need to do the following you need to get its animations from used gltf by passing a specific scene and then say const actions is equal to use animations which is coming from react Tre Dre and you have to pass the animations and the ref to the model that you want one animate it all works so nicely together then you can say actions take 001 doplay and this is going to automatically Play the Bird animation we might need to increase the screen size a bit so we can see it oh there we go it's standing at its place right now and Swinging its swings so what we need to do is we need to make it move around right that's the key part right here so how do we make it move around well once again we can use the use frame function which accepts the Delta as the second parameter and here we can update the position of the bird to simulate the flight now of course we can do something simple like bird ref. rotation. y plus equal to 0.15 time the Delta meaning the difference and of course import the used frame from reactor three Dre you'll be able to see that the bird kind of stays here right doesn't really move that much what if we change the X right here yeah it's moving a bit I think it around itself but what I'm trying to say is we cannot really do a simple movement right here we have to do something more complicated we have to make it Move Like a Bird which is not easy so I spoke with Chad GPT just a bit and came up with a function that's going to update the Y position to simulate the flight moving in a sinus wave yep that's right once again we have a bit of math a sinus wave moves like this so it's a wave it's moving predictably but it changes it's not just a linear line so to implement that sinus wave you can do do something like this bird ref. currentposition doy is equal to math. sin and you want to move it by a specific expression it can be a number but also we can extract something from the used frame it gives us access to the clock as well as the camera and we can play with those two properties by passing The Clock do elapsed time and this is going to keep track of the total time the clock has been running so it's going to move as the time moves it's going to change the value so we can say elapse time and we can add any number to make it look better like 0.2 + 2 so now if we save it you can see it's still standing in its place that's because we have to change the X position as well so to move it around we can check if bird ref do current. rotation doy is triple equal to zero in that case we want to move forward by saying bird ref. current. rotation we want to modify the x axis by saying plus equal to 0.01 and then we want to do the same thing for the Z or Z axis but we want to move it to minus direction if we do this it slowly starts to fly around itself we can do similar thing to make it move backwards right here by simply copying those two and then replacing them the first one is minus equal to and the second one is plus equal to but the most important thing is to change the X Direction so it actually moves across the island so to do that we can say if bird ref. current. position dox is greater than camera. position dox plus 10 meaning if it has exited our camera then we want to change the direction to go backwards and rotate the bird 180° so bird ref do current. rotation doy is equal to math. Pi so we simply rotate the bird else if if it hasn't reached the end we can say bird ref. current. position X is lower than camera. positionx - 10 it means it's still in the screen and we want to move it forward by saying bird ref. current. rotation doy is equal to zero if we save this and reload you can see it still moves around something is wrong it's just flying over right here it went away and then it's rotating one more time what if I increase the width yep it looks like like it's just doing some crazy stuff right here who would have said that you're going to do some math with a bird not you right the reason why it's being around is because here to move it forward we don't need to modify the rotation but rather the position so four times here we need to say position. X Plus equal to 1 and so on so if we modify this you'll be able to see that the bird is actually going to fly right in and it's going to get smaller as it moves into the screen how cool is this and if you rotate you can see that you can follow the bird or go away from it this is pretty cool it gets smaller and as it approaches the end of the screen it's going to rotate and come back now I know we've done a lot of stuff so let's repeat what does this use frame do with adding some special comments I'm going to paste this code right here and check this out I'm going to increase the code so let's go through it one more time again doing math with the bird so first we want to update the Y position to simulate birdlike motion using a sine wave we just increase this math sinus as the time goes and we multiply it by some values then we have to check if the bird has reached a certain end point relative to the camera if so we change direction backwards and rotate the bird 180° else we just keep it going forward and finally to move it forward or backwards we can use these positioning values the entire code of this project including this bird file is going to be in the GitHub directory so feel free to refer to it if you're stuck if the bird is not moving like it should for you you can definitely just copy the bird jsx file and paste it over here so our plane is flying our bird is flying in as well the last last thing we have to do is Implement these phenomenal popups that are going to show up once we reach a specific point of our portfolio and then allow us to open up some more pages so let's do that next by closing the bird and then in our home we can bring back this popup that we have created before let's copy it and then paste it right here above our canvas we can uncomment it save it and you can see popup as we move it's always there but somehow we'll have to make it show only if it should be showing so to do that let's create a new component inside of our components folder called home info. jsx and run rafc inside of it then we can use it right here by opening a new Dynamic block of code and check if current stage exists then Rend the home info component as a self-closing component like this you have to import it and we need to pass the current stage into it as a prop so current stage is equal to current stage now if we save it it's showing at the start it's saying home info and as we move it appears only once you reach a specific Milestone such as this water well right here the these foxes these carrots and so much more so now let's move into the home info and let's start implementing it to start implementing our home info we're going to make it as reusable as it can be and in the process of doing so I'm going to show you a couple of cool react tips and tricks first we can return our home info and home info is going to return just one thing and that that one thing is going to be a new object called render content which is an object that has a couple of things it has one which is going to be content one that's going to look like this just a simple H1 that's going to say something like one for now and then we can duplicate this three more times 2 3 4 and modify the content to say two three and then four as well so now we have four different contents that we can render a cool thing about this is that now we can render this render content and as props we're getting the current stage so what we can say is say render content and then access the current stage number or else return null so what this means is if we save this now and if we scroll through it you can see that it says one right now but as we go to the second stage you can see that it says two right here that's because it's rendering the second stage and then showing the second content so this is a really cool thing to make it reusable it says three four and then again one so now let's create an info box that's going to show up once we reach a specific section const info box is equal to it's going to be an Arrow function of course an arrow function with an instant return so you don't have to put curly braces and say return you can just immediately return something the info box is going to accept a text link and a BTN text essentially only the things that are changing from a popup to a popup as you can see the color the background all of that is the same but it's the text and the button text that is changing so to implement it we can also just render the text right here for now and specifically in the first step we won't be using this info box because the first step is a bit different but what we can do is give it a class name equal to on small devices text- excl on small devices also leading Das snug this is going to change the line height text- Center Neo brutalism Das blue padding y of four padding x of8 text- white and margin X of five this is going to create this nice square and right within it we can say hi I am and then we can create a new span element inside of which we can say Adrien or you can put your own name that can have a class name equal to font D semi bold and after the span you can simply go to Google search for waving pan emoji and just paste it after this pan then you can add a Break Tag and after it you can say a software engineer from Croatia of course feel free to put your own country right there and now I can unzoom it so it all looks great now for the second third and the fourth one we'll be using this info box so let's copy it and let's put it above the render content as we'll be referencing it within it within our info box we're rendering text and then below the text we're going to render a link component which has to be imported from react rouer Dom it has to have a two property which in this case is going to be link and it has to have a BTN text property and now we can refer to this info box right here as a self-closing component let's scroll to it and there we go you can see an empty box let's give it a text property equal to let's do something like worked with many companies and picked up many skills along the way okay that sounds good to me there we go let's also give it a link equal to slab about and let's give it a BTN text equal to learn more okay now we can finalize the styles for our info Box by turning this text into a P tag that's going to have a class name equal to font Das medium on small devices text- excl and text- center the link is going to have a class name equal to Neo brutalism which is the style we're using Das white and neo- BTN and then the button can also have an image that has a source equal to Arrow which we have to import at the top so we can say import Arrow coming from do/ assets SL ions there we go that looks a bit better and let's also give it a class name equal to w- 4 h-4 and object contain there we go now I think you'll be able to see the purpose of reusing this box because now we can simply copy this duplicate it two more times right here indent it properly and now we can just change the text so for the third one we can say something like LED multiple projects a success over the years curious about the impact the link is going to go to projects and we can say something like visit my portfolio for the final one we can say something like need a project done or looking for a Dev I'm just a few keystrokes away that can go to contact and it can say something like let's talk now as you scroll through the website you can see this first one is learn more the second one is this visit my portfolio and then the third one is let's stock and then you get back to the first one so all of this now makes a lot of sense looks amazing and we have used the best reusable code practices in react definitely mark this down somewhere save it so you know when you have some reusable content how you can reuse it with that said we're now done with the home info and with that we're done almost with the entire home later on we're going to add some audio but now is the time that we go ahead and and focus on some other pages that we have here we have a phenomenal about section we have a project section but I want to do something else first I want us to focus on none other than the contact Section once you click let stock it redirects you to this phenomenal contact Section with email JS integration but more importantly with this crazy Fox that as you start typing it actually moves and then as you send an email it starts running so this is a lot of 3D manipulation we'll be doing and I'm sure you want to do that first and then focus on the other two pages so let's do exactly that we can go to our app component and then simply move to the contact page on which we can start working we've done a lot of 3D stuff for now so to get started with the contact Section let's first focus on these General jsx elements and then we can move to this crazy Fox so let's start by wrapping everything in a section and that section is going to have a class name equal to relative Flex on large devices Flex row usually Flex coal as you can see it is right now and a Max container let's see how does it look like if we go to Let's stock and now you can see we have nothing in there now we want to show a new div right here below and within it we want to have an H1 that's going to say get in touch there we go the div is going to have a class name equal to flex D1 Min dw- 50% and flex as well as flex-all the H1 is going to have a class name of head- text immediately within the H1 we're going to have a form the form is going to have a class name equal to w-o flex flex-all gap of seven between the elements and a margin top of 14 within it we can create a label for our first input so a label that's going to say name it's going to have a class name equal to text- black- 500 and f- semi bold right below the name we can create our first input this input is going to have a type equal to text name equal to name class name equal to input if we save it you see a real input right there a placeholder equal to John it's going to be a required field it has to have a value so let's go ahead and Define the value by creating a new use State field right at the top we can say use state is equal to use State snippet let's call it a form and set form at the start that form can be an empty object that has a name equal to an empty string email equal to an empty string as well and a message equal to an empty string we of course have to import use State from react right below this form we can also Define a handle change which for now we can leave as an empty callback function now in the value we can say form. name and on change we can call the handle change function also you can see that the fox is now steady but as soon as a focus on the input it starts walking so we'll somehow have to track the state of whether we're clicking on the input or not and to do that we can create two new functions const handle focus is equal to a function as well as handle blur the focus is called once you click on it and the blur is called once you click out so we can add those two functions to our input by saying on Focus equal to handle focus and on blur handle blur we can now duplicate this label two more times one two and the input within it the second time the type is going to be email the name is going to be email and the label is going to say email the placeholder is going to be John gmail.com just imagine having that email address and it's going to say form. email finally the last one is going to be your or message it's going to have a name equal to message it won't have a type and it's going to be a text area not an input it's going to have a placeholder here let me know how I can help you it will be required it will have rows equal to four and a class name of text area and the value will be form. message there we go finally we want to show a button right here below the last label and this button is going to have a type is equal to submit it's going to have a class name equal to BTN on Focus it's going to call the handle focus and on blur it's going to call the handle blur now sometimes while we're sending the request we need to have some kind of a loading state so let's create a new state called is loading loing use State snippet is loading set is loading at the start set to false so now we can add a disabled property and if is loading is true then the button should be disabled else we can look into the button and say if is loading in that case say sending dot dot dot else say something like send message there we go our button is done as well now before we start focusing on this gr Fox let's actually enable our email JS service so you can receive emails from your clients to do that we have to add a couple of properties to our form such as onsubmit we need to call a special handle submit function so this is the last function we're going to create const handle submit is equal to another function and we also want to attach a ref to it so we can define a new reference at the top con form ref is equal to use ref at the start set to null and we of course have to import use ref from react so now we can slowly start implementing our form specifically we have to implement the handle change the way the handle change works for all of these inputs is it's taking the key press event and then based off of that event it calls the set form function where it first spreads out all of the other properties and then within square brackets selects a specific field to update e. target. name and updates it to e. target. value so now this is going to update all of the properties from our form and now we can focus on the handle submit the handle submit gets the final event the key press event and we have to call e. prevent default to not reload our page after we submit it we want to initiate the loading process by saying set is loading to true and then we want to use email JS so let's go ahead and install the email JS package it's one of the simplest packages I know for enabling email communication so let's say mpm install add email JS SL browser install it and then you'll be able to import it at the top by saying import email Js from at emjs SL browser within our handle submit we can now call. emjs do send specifically we want to send an email but we have to have a couple of things we have to have the service ID the template ID and then the public key so where are we going to get these from well we of course had to head to email JS so just Google email Js go to it and then create a free account or log in once you're in you should be able to see a screen that looks like this you have 200 emails remaining which would be more than enough imagine getting emails about 200 job opportunities what would you do all day let's go ahead and click add new service and let's add Gmail then you have to copy the service ID and for now paste it right here in the code and click connect account and then once you give it access you'll be able to see connected finally you can click create service you're going to get a new email saying that everything works then you have to create an email template click create new email template and I'm fine with this basic email template saying hello to name you got a new message from from name and then the message right here so let's click save so let's go to settings and let's copy the template ID and we can paste it right here as the second parameter now we can go back to our app and we're not going to store these keys right here you never want to store any kind of keys within your application you need to create them within a EnV file that stands for environment variables specifically env. local you can paste them here and give them a name the first one is going to be vorea and it has to begin like that _ email jsor servicecore ID and you can just put an equal sign there we can do the similar thing for the template ID Vore appor Emil jsor templateor ID is equal to template ID and then you'll also need a public key so you'll have to go back to your account one more time right here and then copy this public key you can say vore appor emjs undoru uncore key and simply paste the key right here now if you go back you can finally close email JS and now we can pass all of these as specific environment variables the first one is the service ID so we can say importa env. vorea _ email jsor service ID the second one is going to be the same thing but the template ID the third thing is going to be the object containing all the things you have to pass such as the from name equal to form. name then we're going to have a two name equal to your name right here I'm going to put Adrien then we're going to have a from email which you want to get from the form by saying form. email then we're going to have a two email which is going to be your email email so you can put your contact whatever email it is and then you want to put the message equal to form. message finally the last parameter to the send form is going to be the public key so you can say import meta EnV Vore appcore emjs undoru uncore key there we go so now we're sending everything we need to do in our form and this is an a synchronous operation so we need to call a DOT then on it so what happens then so then we set the loading to be false because we're done and we can also show an alert so here I'm going to add a to-do for later to show success message and then also a to-do to hide an alert finally after the do then we can put a do catch that gets the error also sets the loading to false Kanza logs the error so we can see what's happening and also shows the alert so for now I can say show error message great so what do you say that we go ahead and test it out I'm going to collapse this right here and enter my name enter my second email and enter my message of does this work work by the way the fox is great let's go ahead and click Send sending okay that's good and it does appear to be stuck at sending so let's go to inspect let's go to console and it seems like the third parameter is expected to be the HTML form element so it's complaining about that third parameter within our email oh that's because I use send form it was just supposed to be sent my pad right here let's just copy this message reload and just try it one more time and click Send sending and immediately the loading went away so one thing we need to do here of course is also clear the form so we have to say set form and then clear it to default values but if you click it again it still doesn't clean it which means that we must be in the dot then and not the DOT catch so let's go to our inspect open up the console and it looks like we get an email JS response status the service ID is invalid I'm thinking that it's not invalid but we might need to reload our application for environment variables to take effect and then it will be able to read them so maybe that's it so let's reload the app by pressing contrl C and then y rerun it and let's give it one final go send message still nothing no let's see what do we get now in the console it's still the same error the service ID is not there let's see if we have spelled it correctly by going to EnV local and just checking it out V app service ID that is good and just to cross verify right here servicecore it looks good to me so it must mean that it's not getting read by V what we can do is we can conso log it right here this entire thing and just check if it's getting read by our compiler so now if I enter all the values one more time and click Send we do indeed get it but it says Service ID is invalid so let's go to this URL and it again leads us here is it possible that I copied it the wrong way so if I go go back here and if I just enter it oh my God there is a comma here never have commas in your environment variables as a matter of fact you don't need strings at all it's going to automatically take whatever is in the same line next to the equal sign so yeah we have that extra comma there now let's simply reload our terminal one more time just to be safe and let's go back and try it one final time and I'm going to pass the same message send message it still didn't get cleaned which means that we must have another error so if I go here now it's complaining about the template ID being invalid okay template ID let's go back here and look for our templates oh it looks like it didn't get saved for some reason so let's just do it one more time and I'm GNA press save oh no changes to save but hey I want to save what we have here looks like this is bad design they could have saved it immediately but no worries we can simply remove something from here by pressing code editor in the edit content and we can remove the email JS team and press apply and now press save there we go so so template has been saved and now we can get this new template ID which I'm going to pass to our EnV local there we go now we can go back and hopefully now it works if I enter all of my details make sure to reload the terminal once again if it doesn't work but in this case it worked and the email got delivered in like a millisecond I got it immediately so now that's great news our form is working and we are ready to get started with the fox to create our Fox we can create a new model component right here called fox. jsx inside of which we can run RFC for the fox we're going to do something similar to what we have done with the island because it's not going to be a primitive object it's going to be a real 3D model we want to interact with so can go to assets 3D rightclick the fox and then click revealing File Explorer or open in finder once you have the model we can go to the same website we used before it's this one right here where we can drag and drop your model so simply drag it and drop it this is going to give you an entire Fox Model that you can move around go to display exports and then copy to clipboard finally you can simply over override everything in the fox and paste this new Fox object great now let's do a couple of changes let's immediately import scene coming from do/ assets sl3d fox. glb through props we can accept the current animation as well daada do props meaning spread all the other props then we have the actions to modify the animations which is great so let's make use of them let's say use effect where we have a callback function and it's going to change whenever the action or the current animation change but you might be wondering what is this current animation before we get to that let's actually display the fox so we can go back to our contact page and then we can go below the div containing our form which is right here we can create a new div that's going to have a class name equal to on large devices w-1 over2 w- full on large devices H Auto on medium devices H as in height 550 pixels and usually height is 350 pixels so we want to modify the height of the fox so it looks good on all screen sizes then within this div we can display a canvas this canvas has to be imported from react 3 fiber and of course we know that we have to have a camera so let's say a camera and later on we're going to pass position as well as a matter of fact let's set it now to 0 05 finally we can display the Fox right here don't forget the suspense the suspense is going to allow us to load the fox nicely so we can say suspense that's going to have a fullback and then within it we can render the fox and of course at the top we have to import it from the models by saying import Fox from. models slf Fox once we get it in here we can also set the fullback to loader which we can import by saying import loader from data/ components forward SL loader now if we go down we have our Fox but we can also pass some props to it such as the position which is going to be equal to an array of 0.5 0.35 and 0er we can also give it a rotation equal to something like 12 0 0 and a scale equal to 0.5 0.5 0.5 now if you reload the screen everything is going to break so let's go to inspect and here we can see that the fox does not provide a default export so we need to go back to the fox at the bottom we have to remove this use gltf and say export default Fox and then at the top we have to say const fox is equal to an aror function now we're truly importing it and right here we can provide a full path to the scene there we go so if we save it and reload you can see it breaks again let's see why that is if we go to the console it's complaining about the use effect not being imported so let's import use effect from react then here I misspelled actions and if we do it you can see that we have some kind of a silhouette of a fox but it's not yet looking good do you know why that is well of course it's because of the lights we can also modify a couple of other things regarding the camera such as the fov or the field of view we can set it to 75 we can set the near to 0.1 and far to 1,000 if we reload everything is the same but now we can add the lights let's add one directional light with an intensity of 2.5 and a position of 0 0 1 there we go that's much better now let's rotate the fox a bit by saying minus 0.6 for the second parameter there we go and let's do 12.6 right here there we go so this is nicely going to position it on the screen you can play with this a bit more go even more precise in case you want to move it around you can also scale it if you want to to something like one and you can make it one by one because this is looking a bit weird imagine having five here that's not good but if you do 111 it's just going to get bigger in general I believe 0.5 is good let's focus on other lights as well we can also give it an ambient light that's going to look like this and we can give it an intensity equal to one there we go maybe that's a bit too much maybe we can do 0.5 there we go now it has some shadows and these are going to be old the lights that we need now how do we trigger different animations well let's go ahead and Define a new animation state so at the top we can say use State and we can say current animation and it's going to be equal to idle at the start so now we want to modify our functions called handle blur and handle Focus once we focus we want to set the current anim to walk and once we exit the input we want to bring it back to idle so now we're switching between idle and walk but let's also make it run once we submit the form so we can go inside of the handle submit in the error we can reset the current animation to idle so Set current animation to idle or there we had sad did you see that Visual Studio code recommended sad and then we can also do something like run once we first handle submit so Set current animation to something like run there we go I believe now we should be good so what we can do is we can pass the current animation right here into the fox current animation is equal to current animation now if we go into it we are accepting it as a prop and let's actually put it to good use let's first figure out out what the actions are by saying console.log actions now if we go to our console you can see that right here we get an object having hit idle and walk left so hit is going to be the running actually not run so I have to modify my form here to say hit and also you need to make sure that all the other ones are named the same now that we have those actions we have to get the key for each one of those actions and we have to stop them and we can do that by saying object. values to which we pass the actions so this is going to give us the function to call each of the actions and we can say for each action simply play the action. stop so this is going to stop all actions but then if there is actions and then we enter the current animation in that case we can call that animation and call theplay on it that's going to look like this actions current animation doplay so let's reload the page we don't have any errors or Warnings which is great we can go back to our contact and we can start typing or rather we don't you can see already it's wigging its tail so let's start typing and you can see how now it's walking but if I try to send something then it starts running this is great and then now we need to finally stop the run animation after some time so to do that we can go inside of this do den and then create a timeout that timeout is going to look like this set timeout where we have a call back function that's going to be called after a specific timeout in this case after 3,000 milliseconds or 3 seconds what do we want to do then we we want to set the current animation to idle and we want to clear the form so we can put this set form right here at the top another thing we want to do here is we also want to trigger some kind of an alert and for that I'm going to teach you how to create a custom hook yep you heard that right we're going to dive into some Advanced react creating a custom hook to create it you can create a new folder in your Source folder called Hooks and then you can create a new hook or new file called use alert. JS there you can run rafc and I'm going to teach you how to create this custom hook but why do we need a custom hook in the first place well because you'll most likely want to use it multiple times across the project so this is used to extract some of the Project's logic let's get the Ed State coming from react and let's define some new States by saying use State snippet alert and set alert it's going to be an object where show is set to false at the start text is set to an empty string and type is set to Danger that kind of means that it's going to be a red one and then we can create functions that are going to show or hide the alert by saying const show alert is equal to a function that simply calls the set alert and then it modifies the properties to this function we want to pass what we need to modify so we can destructure the values inside of an object like this by saying text and the type by default set to Danger unless we pass something else and then it's going to modify the alert to say show true it's going to modify the text and the type of the alert and finally want to have something like this for hide alert as well so we can say hide alert we don't need to get any of these parameters and we can say show to false text is going to be set to empty string and type is going to be set to Danger finally hooks don't return any jsx they return most often an object or an array to which you can pass all of these values such as alert show alert and hide alert now we can import those utility hooks right here within our code by saying const the structure alert show alert and hide alert is equal to use alert which we have to import from hooks use alert finally we can use it whenever we need to alert something in this case that's going to happen right here after descent show success message so we can say show alert to which we can pass show set to True text is equal to message sent successfully and type can be success and then in the time out we can call the Hide alert also we can then again call the show Alert in the catch to show the error message by saying show true we can say the text something like I didn't receive your message and type is going to be danger finally we're going to use what we get from the alert to show it right here on top of our section or right within it by saying if alert. show show is true then we want to render the alert component and pass all of the alert properties to it and this alert is a new component that we will create so so you can create a new component within components called alert. jsx run rafc and now we can import it in our contact Section coming from components alert for now let's make it show always so for now I'm going to Simply put it right here and you can see alert at the top so this allows us to style it let's give this div a class name equal to Absolute top-10 left d10 right- Z this is just for positioning let's make it a flex justify Dash Center and items Dash Center as well within it we can have a div that's going to give it some color so let's say class name is equal to it's going to be a dynamic template string where we need to look into the type so if the type is triple equal to Danger in that case we can return BG red 500 else we can return BG blue 800 now it looks like we have an error so let's go ahead and go to inspect and then here we can see that type is not defined that's because we're getting the type and text from props and we need to put them here so now if we reload and say something within this div such as test you can see the alert appear on top let's also give it a p of two for padding text- Indigo -100 leading - none on large devices rounded Das full flex and on large devices inline flex and we can give it a roll to this div is equal to alert finally let's style the test within it to be a P tag that's going to render the text we can give it a class name equal to margin right of two and text Dash left in this case it looks like there isn't any text getting passed in so if we go into our alert that is true because we're now fake calling it without updating the values using our hooks which is okay with us Above This P tag let's create a new P tag that's going to check the type and if the type is triple equal to Danger then it will return failed else it will return success there we go and now we can see failed let's also style this B tag a bit by giving it a class name equal to it's going to be a dynamic template string once again where we have to check for the type so let's copy the start of this string or we check for the type and then we can continue by giving it a flex rounded Das full uppercase padding X of two padding y of one font Das semi bold and margin right of three there we go so it's going to look much better once we actually complete it you can trust me on that and here on top instead of BG red 500 we can use red 800 and here we can use BG red 500 and BG blue 500 as well also we want to use text of XS right here so we can say text- XS finally let's give it a go with real data so we can remove this and only show it when it needs to be shown so let's test it one more time we start typing the Fox start walking we stop it stops we send an email and then it starts running and after 3 seconds we get a success message and it stops running EX exactly how it should be but I did see that it wasn't properly aligned so let me quickly bring back the alert we had right here so it's going to be a typical alert that looks like this but this time with the text element and there we go you can see it's not properly aligned so this div that's inside needs to have the items Das Center property as well and now it's perfect great so now we have alerts implemented as well as well as the this phenomenal Fox and as you know this is looking even better on a larger screen there we go we can look into fixing this empty space later on but for now on larger devices it's looking great and this fox really stands out once it's a bit bigger especially when it runs it's pretty cool to see how this is implemented with that said some of the coolest 3D elements of your application have been implemented and this is looking great later on we're going to fix how it moves across once you use your keyboard events such as left and right keys right now it's a bit jerky you can see how it jumps out we're going to fix that and now we can focus on the about and projects Pages these are more typical Pages you need to have in every single portfolio but here we try to keep them as professional as possible with some cool little details such as these hover events and this amazing work experience section so let's focus on the about section next by putting this to the side and navigating to our app and then control clicking the about section great work on coming this far into this build I'm sure you're going to love it once it's your name right here and it's deployed under your domain to get started with our about section we can wrap it in a section and we can give it a class name equal to Max Das container this is going to ensure that it takes the full width of the screen then right below we can create an H1 and this H1 is going to say hello for now let's move into our about so we can see what this is about and you can see Hello nicely right here we can give it a class name equal to head Dash text after hello you can say I am right so let's say hello I'm and then we can add a span element this span is going to say your name in this case Adrien and we can give it a class name equal to blue- gradient unor text font D semi bold and drop-shadow there we go this is looking really nice now below this H1 we can have a div and this div is going to render a P tag that's going to say something like software engineer based in you can put your country there specializing in technical education through Hands-On learning and building applications this is my tagline you can use anything else that you like explaining who you are as a developer and what your strong sides are once you enter your text there you can give this div a class last name equal to Mt of5 for margin top Flex flex-all Gap -3 in text- slate d500 there we go right below this div we can have another div that's going to have a class name equal to padding y of 10 flex and flex-all within it we can render an H3 that's going to say my skill let's also give it a class name equal to subhe head- text and if we spell it correctly you can see that now it looks like a subhead right below we want to create a div and this div is going to have a class name equal to Mt of 16 to divide it a bit from the top it's going to be a flex container and flex wrap so the elements nicely wrap to fit the width of the content and then a gap of 12 within here we want to Loop over our skills the question is where are we going to get our skills from for that we can use the special constants folder if you go to your Source folder you can create a new folder called constants and within it a new index.js file in the GitHub just down below you can find a modified constants index.js file so simply copy it and paste it right here we have a lot of lines of code here but it's zero Logic the only thing we have here is the content that you can update on your own so here we mentioned some of our best projects we also mention our Social Links as well as different experiences we've had so far of course these are my experiences what you can do is you can modify these to suit your needs same thing for the skills you can see that skills is simply an array of different image URLs and we have these images as assets names and types so what you can do in case you don't know Express you can simply remove it or you can exchange it for something else but now that we have those skills we can just use them here by saying skills of course we need to import them at the top by saying import skills coming from do/ constants and then we need to say skills. mmap where we map through each individual skill and for each skill we want to instantly return something so we can use just the regular parentheses right here for each skill we want to return a div within that div we're going to render another div and within that inner div we can render an image this image is going to have a source equal to skill do image URL it's also going to have an Al tag equal to skill. name and it's going to have a class name equal to w-1 over2 h-1 over2 and object Dash contain if we save this you can see all of these different Technologies appear here but let's make it look just a bit better by wrapping our outer div in a class name equal to block Das container we can also give it a w of 20 and H of 20 to make it a bit larger the inner div can have a class name equal to BTN D front rounded - excl Flex Justified - Center and items Das Center as well so now this is centered and you can see this nice animation appear above this div let's add one self-closing div that's going to have a class name equal to BTN dback and rounded D excl and this is going to give it this nice looking div so now we have these cool Technologies listed one after another since we're using Flex wrap you can see they nicely wrap and in case you increase the width of the screen they are nicely showcased right here this is great so now we have my skill section and we can move to the second section which is going to be work experience so let's go right below this entire div that talks about my skills and let's create a new div let's give it a class name equal to padding y of 16 within it we can have an H3 that's going to say work experience and we can give it a class name equal to subhead das text there we go and we can also copy this entire div that talks about our ptag here which we can paste below the age3 so that's going to be margin top of five Flex Flex column text slate 500 and we can nicely display it right here but this time we're going to render some other text we're going to say something like I've worked with all sorts of companies leveling up my skills and teaming up with smart people here's the rundown you don't have to say the same exact thing you can say something similar but essentially you're making the viewers anticipate the experience that's about to come so let's go below the speed tag and below the div and there we can create a final div that's going to have a class name equal to margin top of 12 to divide it a bit from the top and then a flex container within here we want to render this phenomenal experience list which looks good on mobile but looks even better on desktop and it even animates slowly for this we're going to use a package called react vertical timeline component you can see it right here react vertical timeline component it has 35,000 weekly downloads so the only thing we need to do to use it is install it by running mpm install react vertical timeline component so just type it out react D vertical Das timeline Das component and then we can copy its usage so first let's copy the Imports so at the top we can say import vertical timeline and vertical timeline element from react vertical timeline component and this is really important you also need to import react vertical timeline component style Min CSS this is going to style it to look good from our constants we can also import our experiences so we can map all over them and now that we imported this let's go ahead and put it to use what you have to do first is wrap everything in a vertical timeline that looks like this within it we want to call experiences. map where you map over each experience and then for each experience you want to return a vertical timeline element that looks like this inside of there for now let's render a div and within that div let's render an H3 that's going to render the experience. tile if we save this and go back you can see that we have react GS developer react native developer web developer and full stag developer and that's because these are coming from our experiences once again feel free to modify each one of these objects to work work for you where you worked and what did you do let's also give this H3 a class name equal to text Das black text- XL font Das Poppins and font D semi bold that's much better below the H3 let's create a P tag that's going to render experience do compor name so here we can see where did we work at let's give this B tag a class name equal to text- Black 500 font D medium and font Das Bas we also can give it a special style property equal to margin Z this is going to fix some of the default styling coming from vertical timeline element below this div we want to create a UL an unordered list that's going to have a class name equal to margin y of five for margin on top and bottom list- disk margin left of five and space- y-2 inside of here we want to show bullet point list of what did you do that company so here we can map over experience do points. map where we get each individual point and the index corresponding that point and for each point we want to return a list item that's going to render what that point says that's going to make it look like this let's style the lii a bit by giving it a class name equal to text- black- 500 over 50 as it doesn't have to be so black black font Das normal padding left of one and text- small let's also give it a key since We're looping over it equal to a template string of experience Dash Point Dash and then we can render the index now we also need to provide a key to each one of these vertical timeline elements since We're looping over them so let's give it a key equal to experience do company name because they're surely going to be unique we can also attach a date to each one equal to experience. date which is going to add it at the bottom we can also add the icon which is going to be a div a div that's going to render an image this image is going to have a source equal to experience. ion an I'll tag of experience. compan name and it's going to have a class name of w- 60% h- 60% and object Das contain now it looks like we have an error right here so let's go ahead and check it out what that is by going to our console and it looks like can not convert a symbol value to a string and that's happening in some kind of a span element interesting so we're still getting the span element error but it looks like it's connected to the icon it seems like it cannot get the icon so instead of saying icon style this right here was supposed to be an icon there we go so now we can see the icon is added but now that we have the icon we can add the icon style equal to an object where we put a a border bottom of 8 pixels a border style equal to solid a border bottom color equal to experience do icon BG and make sure to add a comma here and then a box shadow of none that's going to make it look a bit better but let's style this div to position our icon in the center of each one of these circles so let's give it a class name equal to flex justify Das center items Das Center w-f and h- full and now it's looking a bit better but we're far from being done you can see the icon is still not looking good so I made a mistake here this right here was supposed to be for the content as you can see the content is a bit Bland right now but we can say content style is this and then it's going to add this nice background at the bottom of each one of these contents but the icon style is going to be something different it's going to say background is equal to experience. ion BG and that's going to now fill the color of each one of these logos to look good with the icon itself and with that our about section is completely mobile responsive and also fully functional as you can see not only can your viewers see what technologies and skills you're proficient in they can hover over them but also see your entire work experience but what then what happens once they know what you've done and they want to hire you we want to add something known as a call to action where they can click it and they can immediately navigate to the contact Section so let's add this CTA right here at the bottom we can go to the last div and create something known as an HR a horizontal line with a class name of Border Das slate D200 this is going to create a nice line to divide what we have so far and below it we can create a new component so in the components folder create a component called ct. jsx run rafc and then within the about you can import it right here at the bottom CTA and of course import it from components CTA there we go so now we can style it by turning it in a section giving it a class name equal to CTA adding a P tag where you can say something like have a project in mind add a Brak tag then but this Brak tag is only going to be visible on small devices so if small then it's going to be block else it's going to be hidden and then after that we can say something like let's build something together there we go have a project in mind let's build something together let's also give it a class name equal to CTA text which is going to make it a bit bigger and below it we can render a link and this link has to be imported from react rouer Dom and it's going to have a two property pointing to forward SLC contact with a class name equal to BTN the only thing it's going to say is contact there we go looking amazing on mobile devices and looking even better on the final website if we click it we go to our nice Fox while we're here let's also figure out why our background is not taking 100% of the height of the screen we can go to inspect and then select this and you can see that the main element is not taking the full height so to fix it we can close the CTA we can close the about as well as we're done with it and we can give our main an age off 100 VH like this now if you save it it is looking wonderful with that said our homepage is looking great but the plane is not really positioned as it should be as you can notice if you compare it to the final version it is a bit bigger and it is a bit farther away right here so it looks like it's flying on the sides of the island whereas here it looks like it's flying on top this might look good as well but it's up to you we do need to make it a bit bigger though so let's go back to our app and let's go to our home and then adjust plain screen size here we can see that we're giving it a specific scale if the window is lower than 768 pixels and something else if it's larger than that so what we can do is we're passing these screen scale and Screen position for adjust plane for screen size and then we're getting the plain scale and plain position and then we're passing them over right here plain scale and plain position what we need to do though is not call them plain scale and plain position we just need to call them scale and position because we're passing these immediately to a mesh and mesh only takes account of them if they're called exactly like that as we're spreading them right here through props so now our plane is looking even better and it feels like we're flying over this island I also promise we're going to fix this left and right keys to make it look a bit less like we're moving pixel by pixel so let's go to the island and let's go to the handle key down once we press a key down we want to also modify the rotation so we can say rotation speed do current and then we want to modify it or make it equal to 0.0125 this value I found to work really good with arrow keys and then if we press Arrow right we want to do the same thing but set it to minus 0.0125 now if we move through it it's going to feel a bit more natural same thing if we move it through here going backwards great so this leaves us to do only one more thing and that is the projects so let's see what we have done by going here and clicking visit my portfolio for now this is empty but soon enough it's going to be filled with amazing projects to look exactly like it does right here to start with the projects we can copy the first part from the about as they're quite similar so let's go to app about and let's copy the section as well as the first div we can paste that right here there directly within the project and we can close our section now if we go back that's going to look like this but we want to change hello I'm Adrien into my and then in the span we can say projects there we go that's better then in this P tag below we can just say something like I've embarked on numerous projects throughout the years but these are the ones I hold Clos is to my heart many of them are open source so if you come across something that pequs your interest feel free to explore the code base and contribute your ideas for further enhancements your collaboration is highly valued of course maybe this is a bit over the top you can go with something a bit simpler anyway here you can explain your projects then we can go below this div and create a new div this div is going to have a class name equal to to flex flex-wrap margin y of 20 and the gap of 16 here we want to map over our projects so right at the top we can import projects coming from do slash constants like this now we can say projects. map where we get each individual project and we want to immediately return something here make sure to use just a regular parentheses and not a function block for each project we want to return a div that's going to have one more div within it and then within that second div we can have a self-closing div the self-closing div is going to have a class name equal to it's going to be dynamic of BTN back rounded DXL and project. theme so this is going to be dynamic immediately below this div we can also render another div and this one is going to render a self-closing image it's going to have a source equal to project. ion URL an Al tag of project icon and a class name of w-1 over2 h-1 over2 and object Das contain now if we save this you won't be able to see anything yet but as soon as we give this outer div a class name equal to on large devices with its 400 pixels and w- full and we have to give it a key since We're looping over it of projectname now you can start seeing the icons but they are really white and they're not that noticeable so this inner div can have a class name equal to block-c container and W of 12 and the height of 12 this is going to make them much smaller so they can fit nicely then this div containing the image has to have a class name equal to BTN front rounded DXL Flex justify Dash center items Dash Center and there we go now we have these wonderful looking icons that when you hover over them they look great right below these two divs we can create another div to provide more info about each project specifically we can give it a class name equal to margin top of five flex and flex-all immediately within we can render an H4 that's going to R render the project. name below the H4 we can render a P tag that's going to render the project. description and below the P tag we're going to have a div inside of which we can render a link this link has to be imported from react router Dom it's going to point to project. link it's going to open opening a new tab by giving it a Target ofor blank and if we're doing that we also have to give it a Rel of no opener no referer we can also give it a class name of font D semi bold and text- blue- 600 within the link we can say just that live link so this is going to point to our deployed website below the link we can also render an image that's going to have a source equal to arrow and we have to import it from assets icons an Al tag of Arrow as well as a class name of W-4 h-4 and object Das contain so now it's looking like this let's style those projects just a bit by styling this H4 we can give it a class name of text- to excel to make the title much bigger as it's important font Das Poppins and font Das semi bold the P tag can have a class name equal to margin top of two and text- slate d500 and then a div containing the link can have a class name of mt5 to divide it a bit from the top Flex items Das Center gap of two and font Das Poppins as well now this is looking wonderful on mobile devices but at the bottom going all the way down below this last div we want to create an HR a horizontal line with a class name of Border Das slate D200 and below it I think you already know it we can put a call to action which we can import from components CTA so now if somebody sees your about section they can contact you or if they check out your project they can contact you so you can do theirs and with that said believe it or not this is it for the project section so we can close it as well as the app and we can expand the website here it looks like we still have some issues it looks like it's not going all the way down right here so one fix for that is to go to app and then within the app give it the height of fool so h- fo now it's going to take the full height and it's going to work well with the about section but for contact it still breaks so we can go to contact and simply give our outer section an h-100 VH and now this is going to fill the entire screen so once again the home is now looking wonderful we can scroll through with the plane then we can visit the about section this is looking great as well we have the contact Section and now we have this new project section where you can hover over it you can see different projects that you have done of course please modify these projects the way you can do that is by going to our constants and then here you can modify not only your experiences or Social Links but also so the projects for example you can modify the icons the themes the names and even the descriptions and Links of the apps you built how cool is that this is a comprehensive portfolio and it is completely yours I want you to modify it deploy it and then even tag me on LinkedIn with a link to your own custom domain of the deploy portfolio it's not every day that you build build something so amazing and now is your perfect time to Showcase it before thousands of other people do so this is completely new it's something that has never been seen before so the last thing we have to do before we deploy it is just add one little extra touch and that is to add some sound to the application as well once you click it we can play some sound to let the user fully immerse into our 3D World so how are we going to do that well let's go to our home and let's start implementing audio to implement our sound we first have to have some audio so let's import Sakura which is the name of this audio I decided to use from assets SL sakura. MP3 feel free to use any MP3 file right here the only thing you have to do is just download it put it with within the assets and then put it right here and then refer to it right here once you have it you can import use effect as well as use ref coming from react then we can initialize this new audio ref const audio ref is equal to use ref at the start equal to new audio and then you can pass the audio of your choice we can immediately modify the volume by saying audio ref. current. volume is equal to 0.4 we don't want to make it too loud and also we want to set audio ref. current. Loop is set to true because we want it to Loop next we want to create a new use State field called is playing music set is playing music at the start set to false then we can also create a use effect this use effect is going to run whenever this new state changes so we can add the is playing music as the only element of the dependency array and then if is playing music is true we can simply call the audio. current. playay and otherwise we can return and then call the audio ref. current. now the question is how are we going to trigger it on and off and the answer is pretty simple we're going to create a simple button to do that for us so going all the way down we can go to our current website and then go below the canvas create a new div that's going to contain an image with a source equal to sound on like this which we need to import from assets icons this div can have a class name equal to Absolute bottom two and left two and now we can see this huge icon but if it's not currently playing music then we want to show sound off else we want to show sound on and make sure to also import sound off there we go we can give it an Al tag of something like sound we can give it a class name of w of 10 h of 10 and cursor Das pointer as well as object-- contain now you can see this little button but finally let's add an onclick that's going to trigger the cback function which is going to call the set is playing music and it's going to toggle this State on or off so right now you can see how it changes on or off and even though you cannot hear it in the recording as I'm wearing headphones right now I can see some nice music playing into my ears so I fully feel immersed into this world you can choose your own type of music to match this island and make it work but with that said that was it when it came to implementing the music and and with that also finalizing our entire application and if you click the button you'll be able to hear the music there we go I hope you can hear it I can hear it on my headphones it sounds great and I truly feel immersed into this world now yes it will stop if you go to some other page but that's totally okay we only want to have it once we are on our homepage and when the bird is flying the birds are chirping and we have a plane flying over it if we move that's okay here we want to focus on what matters which are your other projects but with that said I'm going to let the music keep playing I'm going to expand it to its full glory and hey with that said your full project is now complete this is amazing you can go over the island you can visit your portfolio reach the contact Section or do anything else the app is fully mobile compatible and it works well and just so you can hear me well I muted the music for now because we are preparing for one of the most important parts of this application besides developing it of course and that is deployment before we deploy it notice how we have to change the title and the favicon of our application to say your full name and then portfolio to do that you can close our home and then you can go to the index HTML and here you can modify the title to say something like your first or your full name and then something like portfolio finally you can modify this link to point to SL Source SL assets favicon.ico this is going to modify it to be this nice looking Island on top top left great finally we are ready for deployment or you can also say we are ready for takeoff so let's go ahead and deploy our phenomenal applications on hosting gears fast servers with a custom domain name and we are back on the setup for our 3D portfolio hosting once you're here go to the file manager enter the public HTML and then remove the default PHP this is where our build folder will go so let's go back to our application close all of the files and then open the terminal by going right here View and then terminal we can close the second terminal and we can stop the application from running by pressing contrl C now we can run mpm run build this is going to create an optimized version of our application ready for production this process usually takes just about a minute so let's leave it B and I'll be right back actually it took about 10 seconds right now so let's go to our file explorer and you'll be able to see a new this folder up rightclick it and then click revealing File Explorer or opening finder once you have it open it up and then simply drag and drop all the files into our hostinger H panel this is going to upload them one by one it's going to take a moment and that's it you can now close your H panel go back to your hosting and click on the domain name in a matter of seconds you'll see your portfolio load on your new domain and as you can see our connection is secure which means that we're using https security you can scroll through it as you usually would on your local host but now you can share this custom link with everyone you can also click learn more to go to different pages and notice that everything is working exactly as expected your portfolio is now online and you can share it with everyone in the world having a performant fast optimized and HTTP certified domain name definitely makes you stand out from the crowd this way your page is reliable and secure so now that you have your portfolio share it with your friends and employers but I want to give you an extra task and that is to go to LinkedIn establish your profile and share what you've done with the world also make sure to tag JavaScript Mastery many people already are creating their portfolios and projects and tagging us we always like to reshare everything our community has done so make some changes improvements the project you've seen and then tag us on LinkedIn I'll surely check it out and leave a comment on top of that if you came to the end of this video it means you truly are a perfect fit for our ultimate nextjs 14 course right now it's one of the only nextjs 14 courses in the world and it's going to make you a top one next year developer make sure to use these Black Friday discounts and level up your developer career so with that said once again huge congratulations on coming to the end of this video You Are are an amazing developer and this is just the beginning thank you so much for watching and have a wonderful day
Info
Channel: JavaScript Mastery
Views: 359,894
Rating: undefined out of 5
Keywords: javascript, javascript mastery, js mastery, master javascript, javascript mastery portfolio, react three fiber portfolio, react three fiber, 3d website design, 3d website portfolio, 3d website react, 3d website tutorial, 3d website three.js, react three fiber vs three js, 3d animation app, three js react, 3d react js, three js tutorial, react three js, react js, react portfolio tutorial, react portfolio, 3d website, react three fiber tutorial, 3d website figma
Id: FkowOdMjvYo
Channel Id: undefined
Length: 173min 53sec (10433 seconds)
Published: Fri Nov 10 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.