The idea to realize this project came because I wanted to find something original. So I found Adrian Hajdin's online portfolio which gave me the inspiration to create my 3D Portfolio. I followed all the steps to make this project fonctional and great. This project is entierly build with React.js, Three.js and Tailwind CSS.
Be sure that your development environnment is ready to start. Then create a folder and inside it run the command below :
npm create vite@latest ./ -- --template reactThis command will make a vierge project with React.js and Vite.
Before the commands npm install and npm run dev you need to install the frameworks Tailwind CSS
In the project folder run the commands :
npm install -D tailwindcss
npx tailwindcss initTo build a 3D canvas model, you need some additionals packages. To make that, run the command below :
npm install --legacy-peer-deps @react-three/fiber @react-three/drei maath react-tilt react-vertical-timeline-component @emailjs/browser @fortawesome/free-brands-svg-icons @fortawesome/react-fontawesome @fortawesome/fontawesome-svg-core framer-motion react-router-domTo build your website in multilanguages, you need some additionals packages. To make that, run the command below :
npm install --legacy-peer-deps i18next react-i18nextYou need to install two packages for Tailwind when you use React.js. They are postcss and autoprefixer
npm install --legacy-peer-deps -D postcss autoprefixer
npx tailwindcss init -pIn this project you have two differents folders :
srcwhich contains all the files of the project.publicwhich contains the index.html file and all canvas models. You can customize your project in thesrcfolder and add all the components and the assets.
There are some files to replace to make the project fonctional. You can find them in a GitHub Gist Code Snippets here.
Here you can copy the content of index.css GitHub Gist code
In the src/ folder you create a new file style.js and copy the style.js content from GitHub Gist
At the PATH of the project you replace the tailwind.config.cjs content from GitHub Gist file
In the src/ folder you create the utils/ folder. Inside that the motion.js file then replace the content from GitHub Gist file
In the src/ folder you create the constants/ folder. Inside that the index.js which containt the constants.js content from GitHub Gist file
After repalce all files and folders, you can run
npm run dev # to run the project in development modeTo make the routing in the project you use the package react-router-dom that you installed before.
In the src folder you create a file called main.jsx.
I show you my file to make the routing in the project :
import {
createBrowserRouter,
createRoutesFromElements,
Route,
RouterProvider,
} from 'react-router-dom'
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import Technologies from './Technologies'
import Articles from './Articles'
import Projs from './Proj'
import Mentions from './Mentions'
import './index.css'
const router = createBrowserRouter(
createRoutesFromElements(
<>
<Route path="/" element={<App />} />
<Route path="/technologies" element={<Technologies />} />
<Route path="/mentions" element={<Mentions />} />
<Route path="/projects" element={<Projs />} />
<Route path="/news" element={<Articles />} />
</>,
),
)
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>,
)In this file i import the package react-router-dom and the components of the project. Then i create a router with the package react-router-dom and i add the components in the router.
You can add the Canvas component in the Hero section. To build a 3D model Canvas you have to import some things in the section like :
import React, { Suspense, useEffect, useState } from 'react'
import { Canvas } from '@react-three/fiber'
import { OrbitControls, Preload, useGLTF } from '@react-three/drei'After that you can give a look in the React-Three-Fiber to optimize the quality of lights and orbits for the 3D model
You can add a loader to the Canvas component to wait the 3D model is loaded.
In the Loader.jsx you can import the Html component from the package @react-three/drei to add a loader in the Canvas component.
import { Html, useProgress } from '@react-three/drei'You can add a folder called hoc in src folder, to add a component called SectionWrapper.jsx to stylize your sections.
import { motion } from 'framer-motion'
import { styles } from '../styles'
import { staggerContainer } from '../utils/motion'
const StarWrapper = (Component, idName) =>
function HOC() {
return (
<motion.section
variants={staggerContainer()}
initial="hidden"
whileInView="show"
viewport={{ once: true, amount: 0.25 }}
className={`${styles.padding} max-w-7xl mx-auto relative z-0`}
>
<span className="hash-span" id={idName}>
</span>
<Component />
</motion.section>
)
}
export default StarWrapperTo export this file, you need to create an index.js file in the hoc folder.
import SectionWrapper from './SectionWrapper'
export { SectionWrapper }In the Experience section you need to import some libraries to build the timeline.
import {
VerticalTimeline,
VerticalTimelineElement,
} from 'react-vertical-timeline-component'
import { motion } from 'framer-motion'
import 'react-vertical-timeline-component/style.min.css'
import { styles } from '../styles'
import { experiences, school } from '../constants'
import { SectionWrapper } from '../hoc'
import { textVariant } from '../utils/motion'In the Tech skills section you need to import some libraries to build the skills cards.
import React, { Suspense } from 'react'
import { Canvas } from '@react-three/fiber'
import {
Decal,
Float,
OrbitControls,
Preload,
useTexture,
} from '@react-three/drei'
import CanvasLoader from '../Loader'In the Projects and News section you need to import some libraries to build the projects and news cards.
import Tilt from 'react-tilt'
import { motion } from 'framer-motion'
import { styles } from '../styles'
import { cdn } from '../assets'
import { SectionWrapper } from '../hoc'
import { projects, news } from '../constants'
import { fadeIn, textVariant } from '../utils/motion'For the contact section you need to import some libraries to build the contact form.
import { useRef, useState } from 'react'
import { motion } from 'framer-motion'
import emailjs from '@emailjs/browser'
import { styles } from '../styles'
import { PlanetCanvas } from './canvas'
import { SectionWrapper } from '../hoc'
import { slideIn } from '../utils/motion'First of all you need to create an account on EmailJS In this website you can Add New Service create a template for your email and get the service ID, template ID and public key.
In your Contact.jsx section you build two constants :
const handleChange = (e) => {}
const handleSubmit = (e) => {}The first one is to handle the change of the input and the second one is to handle the submit of the form.
In the handleSubmit function you need to call the emailjs.send function with the service ID, template ID and public key from your own account.
You can also include the .then and .catch functions to handle the response of the email.
const handleSubmit = (e) => {
e.preventDefault()
setLoading(true)
emailjs
.send(
'(your service ID)',
'(your template ID)',
{
from_name: form.name,
to_name: '(your name)',
from_email: form.email,
to_email: '(your email)',
message: form.message,
},
'(your public key)',
)
.then(() => {
setLoading(false)
alert(
'Thank you for your message ! I will get back to you as soon as possible.',
)
setForm(
{
name: '',
email: '',
message: '',
},
(error) => {
setLoading(false)
console.log(error)
alert('Something went wrong, please try again later.')
},
)
})
}In the Footer section you need to import some libraries to build the footer.
import React, { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
// For the social media icons
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {
faGithub,
faLinkedin,
faFacebook,
faInstagram,
} from '@fortawesome/free-brands-svg-icons'
import { styles } from '../styles'
import { footLinks } from '../constants'In your main.jsx file you can add the routing for the 404 page.
<Route path="*" element={<Error404 />} />Then you create the Error404.jsx file in the src folder who call your page.
You can redirect client to error page with the code below :
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<RouterProvider router={router}>
<Navigate to="/404" />
</RouterProvider>
</React.StrictMode>,
)When you finish dev your project, you can build it with the command below :
npm run buildA build folder will be created in your project called dist.
In dist you can find your index.html file and yours index.js and index.css files in the assets folder.
You can send this folder to your server.
If you are using Apache you can create a .htaccess file in the dist folder with the code below :
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.html [L]
</IfModule>In your package.json file you can add a homepage property to specify the url of your website.
{
"name": "portfolioreact",
"private": true,
"version": "0.0.0",
"type": "module",
+ "homepage": "https://[your-website-url]",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
...
}- Vladimir SACCHETTO alias @VladimirSacchetto
