├── src
├── fonts
│ └── moonhouse.woff2
├── assets
│ └── images
│ │ ├── cloud.png
│ │ └── noise.gif
├── components
│ ├── CustomCursor.js
│ ├── Home.js
│ ├── SectionTitle.js
│ ├── Bio.js
│ ├── Footer.js
│ ├── NotFound.js
│ ├── Socials.js
│ ├── Hero.js
│ ├── About.js
│ ├── Project.js
│ ├── Skills.js
│ ├── Navbar.js
│ ├── Contact.js
│ └── Projects.js
├── index.js
├── hooks
│ ├── useHoverEffect.js
│ ├── useSmoothScroll.js
│ ├── useCustomCursor.js
│ └── gsap.js
├── App.js
└── index.css
├── tailwind.config.js
├── .gitignore
├── package.json
├── README.md
└── public
└── index.html
/src/fonts/moonhouse.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/masudranashawon/personal-portfolio/HEAD/src/fonts/moonhouse.woff2
--------------------------------------------------------------------------------
/src/assets/images/cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/masudranashawon/personal-portfolio/HEAD/src/assets/images/cloud.png
--------------------------------------------------------------------------------
/src/assets/images/noise.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/masudranashawon/personal-portfolio/HEAD/src/assets/images/noise.gif
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: ["./src/**/*.{js,jsx,ts,tsx}"],
4 | theme: {
5 | extend: {},
6 | },
7 | plugins: [],
8 | };
9 |
--------------------------------------------------------------------------------
/src/components/CustomCursor.js:
--------------------------------------------------------------------------------
1 | const CustomCursor = ({ innerCursorRef, outerCursorRef }) => {
2 | return (
3 | <>
4 |
5 |
6 | >
7 | );
8 | };
9 |
10 | export default CustomCursor;
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # misc
12 | .DS_Store
13 | .env
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import { BrowserRouter } from "react-router-dom";
4 | import App from "./App";
5 | import "./index.css";
6 |
7 | const root = ReactDOM.createRoot(document.getElementById("root"));
8 | root.render(
9 |
10 |
11 |
12 |
13 |
14 | );
15 |
--------------------------------------------------------------------------------
/src/hooks/useHoverEffect.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import hoverEffect from "hover-effect";
3 | import cloud from "../assets/images/cloud.png";
4 |
5 | export const useHoverEffect = (el, img1, img2) => {
6 | useEffect(() => {
7 | new hoverEffect({
8 | parent: el.current,
9 | image1: img1,
10 | image2: img2,
11 | displacementImage: cloud,
12 | intensity: 0.3,
13 | });
14 | }, [el, img1, img2]);
15 | };
16 |
--------------------------------------------------------------------------------
/src/components/Home.js:
--------------------------------------------------------------------------------
1 | import Bio from "./Bio";
2 | import Hero from "./Hero";
3 | import Projects from "./Projects";
4 | import Skills from "./Skills";
5 | import About from "./About";
6 | import Contact from "./Contact";
7 |
8 | const Home = () => {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | );
19 | };
20 |
21 | export default Home;
22 |
--------------------------------------------------------------------------------
/src/components/SectionTitle.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { useSectionTitleReveal } from "../hooks/gsap";
3 |
4 | const SectionTitle = ({ title }) => {
5 | const sectionTitleRef = useRef(null);
6 |
7 | useSectionTitleReveal(sectionTitleRef);
8 |
9 | return (
10 |
11 |
12 | {title}
13 |
14 |
15 | );
16 | };
17 |
18 | export default SectionTitle;
19 |
--------------------------------------------------------------------------------
/src/hooks/useSmoothScroll.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import Lenis from "@studio-freight/lenis";
3 |
4 | export const useSmoothScroll = () => {
5 | useEffect(() => {
6 | const lenis = new Lenis({
7 | duration: 1.3,
8 | easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
9 | direction: "vertical",
10 | smooth: true,
11 | });
12 |
13 | function raf(time) {
14 | lenis.raf(time);
15 | requestAnimationFrame(raf);
16 | }
17 |
18 | requestAnimationFrame(raf);
19 | }, []);
20 | };
21 |
--------------------------------------------------------------------------------
/src/components/Bio.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { useBioReveal } from "../hooks/gsap";
3 |
4 | const Bio = () => {
5 | const bioRef = useRef(null);
6 |
7 | useBioReveal(bioRef, 2);
8 |
9 | return (
10 |
11 |
12 | Passionate Full Stack developer based in Bangladesh, consistently
13 | pushing boundaries through impactful projects. I am dedicated to
14 | embracing new technologies and solving complex problems with a logical
15 | mindset. Committed to honest innovation, I strive to make a positive
16 | societal impact through my work.
17 |
18 |
19 | );
20 | };
21 |
22 | export default Bio;
23 |
--------------------------------------------------------------------------------
/src/components/Footer.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { HashLink } from "react-router-hash-link";
3 | import { useFooterReveal } from "../hooks/gsap";
4 |
5 | const Footer = () => {
6 | const footerRef = useRef(null);
7 |
8 | useFooterReveal(footerRef);
9 |
10 | return (
11 |
24 | );
25 | };
26 |
27 | export default Footer;
28 |
--------------------------------------------------------------------------------
/src/hooks/useCustomCursor.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 |
3 | export const useCustomCursor = (innerCursorRef, outerCursorRef) => {
4 | useEffect(() => {
5 | document.addEventListener("mousemove", moveCursor);
6 |
7 | function moveCursor(e) {
8 | let x = e.clientX;
9 | let y = e.clientY;
10 |
11 | innerCursorRef.current.style.left = `${x}px`;
12 | innerCursorRef.current.style.top = `${y}px`;
13 | outerCursorRef.current.style.left = `${x}px`;
14 | outerCursorRef.current.style.top = `${y}px`;
15 |
16 | let links = Array.from(document.querySelectorAll("a"));
17 |
18 | links.forEach((link) => {
19 | link.addEventListener("mouseover", () => {
20 | innerCursorRef.current.classList.add("grow");
21 | });
22 |
23 | link.addEventListener("mouseleave", () => {
24 | innerCursorRef.current.classList.remove("grow");
25 | });
26 | });
27 | }
28 | }, [innerCursorRef, outerCursorRef]);
29 | };
30 |
--------------------------------------------------------------------------------
/src/components/NotFound.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { useGsapDownStagger } from "../hooks/gsap";
3 |
4 | const NotFound = () => {
5 | const errorFirst4Ref = useRef(null);
6 | const bombImgRef = useRef(null);
7 | const errorLast4Ref = useRef(null);
8 | const pageNotFoundRef = useRef(null);
9 | const error404Arr = [errorFirst4Ref, bombImgRef, errorLast4Ref];
10 | const pageNotFoundRefArr = [pageNotFoundRef];
11 |
12 | useGsapDownStagger(error404Arr, 1.8);
13 | useGsapDownStagger(pageNotFoundRefArr, 2.7);
14 |
15 | return (
16 |
17 |
18 | 4
19 |
20 |
26 | 4
27 |
28 | page Not Found
29 |
30 | );
31 | };
32 |
33 | export default NotFound;
34 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "personal-portfolio",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@emailjs/browser": "^3.10.0",
7 | "@studio-freight/lenis": "^0.2.21",
8 | "@testing-library/jest-dom": "^5.16.5",
9 | "@testing-library/react": "^13.4.0",
10 | "@testing-library/user-event": "^13.5.0",
11 | "gsap": "^3.11.4",
12 | "hover-effect": "^1.1.0",
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0",
15 | "react-router-dom": "^6.8.0",
16 | "react-router-hash-link": "^2.4.3",
17 | "react-scripts": "5.0.1",
18 | "react-toastify": "^9.1.1",
19 | "three": "^0.149.0",
20 | "web-vitals": "^2.1.4"
21 | },
22 | "scripts": {
23 | "start": "react-scripts start",
24 | "build": "react-scripts build",
25 | "test": "react-scripts test",
26 | "eject": "react-scripts eject"
27 | },
28 | "eslintConfig": {
29 | "extends": [
30 | "react-app",
31 | "react-app/jest"
32 | ]
33 | },
34 | "browserslist": {
35 | "production": [
36 | ">0.2%",
37 | "not dead",
38 | "not op_mini all"
39 | ],
40 | "development": [
41 | "last 1 chrome version",
42 | "last 1 firefox version",
43 | "last 1 safari version"
44 | ]
45 | },
46 | "devDependencies": {
47 | "tailwindcss": "^3.2.4"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { Route, Routes } from "react-router-dom";
3 | import { useSmoothScroll } from "./hooks/useSmoothScroll";
4 | import { useCustomCursor } from "./hooks/useCustomCursor";
5 | import { ToastContainer } from "react-toastify";
6 |
7 | import Home from "./components/Home";
8 | import Navbar from "./components/Navbar";
9 | import Footer from "./components/Footer";
10 | import Socials from "./components/Socials";
11 | import CustomCursor from "./components/CustomCursor";
12 | import NotFound from "./components/NotFound";
13 |
14 | import "react-toastify/dist/ReactToastify.css";
15 |
16 | const App = () => {
17 | const innerCursorRef = useRef(null);
18 | const outerCursorRef = useRef(null);
19 |
20 | useSmoothScroll();
21 | useCustomCursor(innerCursorRef, outerCursorRef);
22 |
23 | return (
24 |
25 |
26 |
27 |
31 |
32 |
33 |
34 | } />
35 | } />
36 |
37 |
38 |
39 |
40 | );
41 | };
42 |
43 | export default App;
44 |
--------------------------------------------------------------------------------
/src/components/Socials.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { useSocialReveal } from "../hooks/gsap";
3 |
4 | const data = [
5 | {
6 | id: 1,
7 | title: "Facebook",
8 | url: "https://www.facebook.com/masudranashawon786",
9 | },
10 | {
11 | id: 2,
12 | title: "Instagram",
13 | url: "https://instagram.com/masudranashawon786",
14 | },
15 | { id: 3, title: "Twitter", url: "https://twitter.com/MasudRanaShawo1" },
16 | {
17 | id: 4,
18 | title: "LinkedIn",
19 | url: "https://www.linkedin.com/in/masudranashawon1/",
20 | },
21 | { id: 5, title: "GitHub", url: "https://github.com/masudranashawon" },
22 | { id: 6, title: "LeetCode", url: "https://leetcode.com/masudranashawon" },
23 | ];
24 |
25 | const Socials = () => {
26 | const socialRef = useRef(null);
27 |
28 | useSocialReveal(socialRef, 2.5);
29 |
30 | return (
31 |
47 | );
48 | };
49 |
50 | export default Socials;
51 |
--------------------------------------------------------------------------------
/src/components/Hero.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { useHoverEffect } from "../hooks/useHoverEffect";
3 | import { useImageReveal, useHeadlineReveal } from "../hooks/gsap";
4 |
5 | const data = {
6 | img1: "https://res.cloudinary.com/drgxflcsb/image/upload/v1676030149/Personal%20Portfolio/masud-image2_xhvc03.jpg",
7 | img2: "https://res.cloudinary.com/drgxflcsb/image/upload/v1676030149/Personal%20Portfolio/masud-image1_rejzqv.jpg",
8 | };
9 |
10 | const Hero = () => {
11 | const heroImageRef = useRef(null);
12 | const heroHeadline1Ref = useRef(null);
13 | const heroHeadline2Ref = useRef(null);
14 |
15 | const headlLines = [heroHeadline1Ref, heroHeadline2Ref];
16 |
17 | useHoverEffect(heroImageRef, data.img1, data.img2);
18 | useImageReveal(heroImageRef, 0.5);
19 | useHeadlineReveal(headlLines, 1.5);
20 |
21 | return (
22 |
26 |
27 |
28 |
Full Stack
29 |
30 |
31 |
Developer
32 |
33 |
34 |
35 |
36 | );
37 | };
38 |
39 | export default Hero;
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Personal Portfolio
2 |
3 | This repository contains code for a personal portfolio website built using React, GSAP, WebGL, Three.js, and Tailwind CSS. The website showcases the developer's skills and work in an interactive and engaging manner.
4 |
5 | ## Features
6 | The portfolio website comes with the following features:
7 |
8 | - **Creative artistic UI:** Interactive and engaging design using React, GSAP, WebGL, Three.js, and Tailwind CSS.
9 | - **Easy navigate:** Easy-to-navigate portfolio sections that showcase the developer's work.
10 | - **Dynamic Contact form:** Contact form for potential clients or collaborators.
11 | - **Intuitive and Streamlined UI:** User interface is designed to be both intuitive and streamlined, making project management a breeze. The clean and modern design of the interface allows users to easily navigate the app's many features, while also providing a visually pleasing and enjoyable user experience.
12 |
13 | ## Tools
14 |
15 | Personal Portfolio is built using the React, featuring the following powerful tools:
16 |
17 | - **React:** A powerful and popular frontend JavaScript library, ideal for building user interfaces.
18 | - **GSAP:** A powerful animation library for JavaScript.
19 | - **@studio-freight/lenis:** A lightweight and flexible library for creating scroll animations
20 | - **WebGL:** A JavaScript API for rendering interactive 2D and 3D graphics within any compatible web browser
21 | - **React Toastify:** A library for creating customizable toast notifications in React apps
22 | - **Tree.js:** A popular JavaScript library used for creating and rendering 3D animations and graphics in web browsers. It provides an easy-to-use API for building complex 3D scenes using WebGL, which allows for hardware-accelerated rendering.
23 | - **Tailwind CSS:** A highly customizable CSS framework, designed to make building sleek and intuitive user interfaces a breeze.
24 |
25 | ## Installation
26 |
27 | To install Personal portfolio, Follow the simple steps below:
28 |
29 | 1. Clone the repository using
30 |
31 | ```
32 | git clone https://github.com/masudranashawon/proxima-client.git`
33 | ```
34 |
35 | 2. Install the required dependencies in the directorie by running
36 |
37 | ```
38 | npm install
39 | ```
40 |
41 | **Or**
42 |
43 | ```
44 | npm i
45 | ```
46 |
47 | 3. Start the development server running
48 |
49 | ```
50 | npm start
51 | ```
52 |
53 | ## Link
54 |
55 | - [Live Demo](https://masudranashawon.netlify.app/)
56 |
57 | ## Thanks for visiting this repository!
58 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Masud Rana Shawon - Full Stack Developer
9 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
22 |
24 |
25 |
26 |
27 |
28 |
29 |
31 |
33 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/components/About.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { useHoverEffect } from "../hooks/useHoverEffect";
3 | import { useProjectLeftRightReveal } from "../hooks/gsap";
4 | import SectionTitle from "./SectionTitle";
5 |
6 | const data = {
7 | img1: "https://res.cloudinary.com/drgxflcsb/image/upload/v1676030150/Personal%20Portfolio/masud-image3_vxmpd0.jpg",
8 | img2: "https://res.cloudinary.com/drgxflcsb/image/upload/v1676030148/Personal%20Portfolio/masud-image4_cbbkzc.jpg",
9 | };
10 |
11 | const About = () => {
12 | const aboutLeftRef = useRef(null);
13 | const aboutRightRef = useRef(null);
14 |
15 | const aboutRefs = [aboutLeftRef, aboutRightRef];
16 |
17 | useHoverEffect(aboutLeftRef, data.img1, data.img2);
18 | useProjectLeftRightReveal(aboutRefs);
19 |
20 | return (
21 |
22 |
23 |
24 |
25 |
26 |
27 | Welcome to my portfolio! I'm deeply passionate about JavaScript and
28 | its power in creating dynamic web applications. My journey into web
29 | development began in July 2022, and since then, I've immersed myself
30 | in Full Stack development. Constantly learning and pushing
31 | boundaries, I thrive on building innovative solutions. My insatiable
32 | curiosity drives me to stay updated with the latest developments,
33 | ensuring I contribute to technological advancement through impactful
34 | projects.
35 |
36 |
37 | As a Full Stack developer based in Bangladesh, I am committed to
38 | honing my skills and solving complex problems with logic. I approach
39 | every project with a dedication to honest innovation, aiming for a
40 | positive societal impact. My goal is to not only meet but exceed
41 | expectations, delivering excellence in every endeavor.
42 |
43 |
49 | View My Resume
50 |
51 |
52 |
53 |
54 | );
55 | };
56 |
57 | export default About;
58 |
--------------------------------------------------------------------------------
/src/components/Project.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { useProjectLeftRightReveal } from "../hooks/gsap";
3 | import { useHoverEffect } from "../hooks/useHoverEffect";
4 |
5 | const Project = ({ project }) => {
6 | const projectRightRef = useRef(null);
7 | const projectLeftRef = useRef(null);
8 |
9 | const projetRefs = [projectRightRef, projectLeftRef];
10 |
11 | useHoverEffect(projectRightRef, project.image1, project.image2);
12 | useProjectLeftRightReveal(projetRefs);
13 |
14 | return (
15 |
16 |
20 |
21 | {String(project.id).padStart(2, 0)}
22 |
23 |
24 | {project.title}
25 |
26 |
{project.description}
27 |
28 | {project.tools.map((tool, i) => (
29 | {tool}
30 | ))}
31 |
32 |
75 |
76 |
80 |
81 | );
82 | };
83 |
84 | export default Project;
85 |
--------------------------------------------------------------------------------
/src/components/Skills.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { useSkillLineReveal, useSkillTextReveal } from "../hooks/gsap";
3 | import SectionTitle from "./SectionTitle";
4 |
5 | const data = [
6 | { id: 1, title: "HTML" },
7 | { id: 2, title: "CSS" },
8 | { id: 3, title: "SCSS/SASS" },
9 | { id: 4, title: "Bootstrap" },
10 | { id: 5, title: "Tailwind CSS" },
11 | { id: 6, title: "JavaScript" },
12 | { id: 7, title: "jQuery" },
13 | { id: 8, title: "TypeScript" },
14 | { id: 9, title: "PHP" },
15 | { id: 10, title: "React.js" },
16 | { id: 11, title: "Next.js" },
17 | { id: 12, title: "Redux.js/Redux Toolkit" },
18 | { id: 13, title: "Firebase Auth" },
19 | { id: 14, title: "Next Auth" },
20 | { id: 15, title: "GSAP" },
21 | { id: 16, title: "Framer Motion" },
22 | { id: 17, title: "Node.js" },
23 | { id: 18, title: "Express.js" },
24 | { id: 19, title: "Laravel" },
25 | { id: 20, title: "MySQL" },
26 | { id: 21, title: "MongoDB" },
27 | { id: 22, title: "Prisma" },
28 | { id: 23, title: "Mongoose" },
29 | { id: 24, title: "Stripe Payment" },
30 | ];
31 |
32 | const Skills = () => {
33 | const skillItemRef = useRef([]);
34 | const skillTextRef = useRef([]);
35 | const skillItem2Ref = useRef([]);
36 | const skillText2Ref = useRef([]);
37 |
38 | useSkillLineReveal(skillItemRef.current);
39 | useSkillLineReveal(skillItem2Ref.current);
40 | useSkillTextReveal(skillItemRef.current);
41 | useSkillTextReveal(skillItem2Ref.current);
42 |
43 | return (
44 |
91 | );
92 | };
93 |
94 | export default Skills;
95 |
--------------------------------------------------------------------------------
/src/components/Navbar.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { HashLink } from "react-router-hash-link";
3 | import { useLinkReveal } from "../hooks/gsap";
4 |
5 | const Navbar = ({ footerNav }) => {
6 | const link1Ref = useRef(null);
7 | const link2Ref = useRef(null);
8 | const link3Ref = useRef(null);
9 | const link4Ref = useRef(null);
10 | const link5Ref = useRef(null);
11 | const link6Ref = useRef(null);
12 | const link7Ref = useRef(null);
13 | const link8Ref = useRef(null);
14 | const link9Ref = useRef(null);
15 |
16 | const links = [
17 | link1Ref,
18 | link2Ref,
19 | link3Ref,
20 | link4Ref,
21 | link5Ref,
22 | link6Ref,
23 | link7Ref,
24 | link8Ref,
25 | link9Ref,
26 | ];
27 |
28 | useLinkReveal(links, 2);
29 |
30 | return (
31 |
36 |
37 |
38 | {footerNav ? "Go to top" : "Masud Rana Shawon"}
39 |
40 | {footerNav && (
41 |
54 | )}
55 |
56 |
57 |
58 |
59 | Home
60 |
61 |
62 |
63 |
64 | My Projects
65 |
66 |
67 |
68 |
69 | My Skills
70 |
71 |
72 |
73 |
74 | About Me
75 |
76 |
77 |
78 |
79 | Contact Me
80 |
81 |
82 |
83 |
90 | My Resume
91 |
92 |
93 |
94 |
101 | New Portfolio
102 |
103 |
104 |
105 |
106 | );
107 | };
108 |
109 | export default Navbar;
110 |
--------------------------------------------------------------------------------
/src/components/Contact.js:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 | import { useInputReveal } from "../hooks/gsap";
3 | import { toast } from "react-toastify";
4 | import emailjs from "@emailjs/browser";
5 | import SectionTitle from "./SectionTitle";
6 |
7 | const Contact = () => {
8 | const formRef = useRef(null);
9 | const input1Ref = useRef(null);
10 | const input2Ref = useRef(null);
11 | const input3Ref = useRef(null);
12 | const input4Ref = useRef(null);
13 |
14 | const inputsRef = [input1Ref, input2Ref, input3Ref, input4Ref];
15 |
16 | useInputReveal(inputsRef);
17 |
18 | const sendMail = (e) => {
19 | e.preventDefault();
20 |
21 | //Email JS integration
22 | emailjs
23 | .sendForm(
24 | process.env.REACT_APP_SERVICE_ID,
25 | process.env.REACT_APP_TEMPLATE_ID,
26 | formRef.current,
27 | process.env.REACT_APP_PUBLIC_ID
28 | )
29 | .then(
30 | () => {
31 | toast("Message send successfully!", {
32 | position: "bottom-left",
33 | autoClose: 5000,
34 | hideProgressBar: false,
35 | closeOnClick: true,
36 | pauseOnHover: true,
37 | draggable: true,
38 | progress: undefined,
39 | theme: "light",
40 | });
41 | },
42 | () => {
43 | toast.error("Message failed! Try again letter", {
44 | position: "bottom-left",
45 | autoClose: 5000,
46 | hideProgressBar: false,
47 | closeOnClick: true,
48 | pauseOnHover: true,
49 | draggable: true,
50 | progress: undefined,
51 | theme: "colored",
52 | });
53 | }
54 | );
55 |
56 | //Clear input
57 | e.target.querySelector(".fullname").value = "";
58 | e.target.querySelector(".email").value = "";
59 | e.target.querySelector(".massage").value = "";
60 | };
61 |
62 | return (
63 |
115 | );
116 | };
117 |
118 | export default Contact;
119 |
--------------------------------------------------------------------------------
/src/components/Projects.js:
--------------------------------------------------------------------------------
1 | import Project from "./Project";
2 | import SectionTitle from "./SectionTitle";
3 |
4 | const data = [
5 | {
6 | id: 1,
7 | title: "Learnify: An Online Learning Platform",
8 | image1:
9 | "https://res.cloudinary.com/drgxflcsb/image/upload/v1692032065/Personal%20Portfolio/learnify-1_gybje8.png",
10 | image2:
11 | "https://res.cloudinary.com/drgxflcsb/image/upload/v1692032065/Personal%20Portfolio/learnify-2_oneneu.png",
12 | description:
13 | "Experience a transformative online learning journey with Learnify, The cutting-edge Next.js app! Explore a diverse range of courses, engage with interactive lessons, and embrace a seamless user experience. With Learnify, acquiring new skills and knowledge has never been easier. Join us today and unlock the full potential of your learning endeavors.",
14 | tools: [
15 | "Next.js",
16 | "React.js",
17 | "MongoDB",
18 | "Stripe",
19 | "Prisma",
20 | "GCP",
21 | "Tailwind CSS",
22 | "AOS",
23 | ],
24 | liveLink: "https://learnify-pro.vercel.app",
25 | fullStackLink: "https://github.com/masudranashawon/learnify",
26 | frontEndLink: "",
27 | backEndLink: "",
28 | },
29 | {
30 | id: 2,
31 | title: "Proxima: Project Management Web Application",
32 | image1:
33 | "https://res.cloudinary.com/drgxflcsb/image/upload/v1679669817/Personal%20Portfolio/proxima-one_rzufpn.png",
34 | image2:
35 | "https://res.cloudinary.com/drgxflcsb/image/upload/v1679669817/Personal%20Portfolio/proxima-two_zrwmos.png",
36 | description:
37 | "Proxima is a project management application built using the MERN Stack. The application allows users to create, update, and delete their own projects with ease. Proxima is designed with high-level security in mind, featuring strong JWT authentication and front-end route protection to ensure the safety and privacy of user data.",
38 | tools: [
39 | "React.js",
40 | "Tailwind CSS",
41 | "Node.js",
42 | "Express.js",
43 | "MongoDB",
44 | "JWT",
45 | ],
46 | liveLink: "https://proxima-application.netlify.app",
47 | fullStackLink: "",
48 | frontEndLink: "https://github.com/masudranashawon/proxima-client",
49 | backEndLink: "https://github.com/masudranashawon/proxima-server",
50 | },
51 | {
52 | id: 3,
53 | title: "Tech Alpha: Online Electronics Accessories Store",
54 | image1:
55 | "https://res.cloudinary.com/drgxflcsb/image/upload/v1675615229/Personal%20Portfolio/tech-alpha-1_lgzxvt.png",
56 | image2:
57 | "https://res.cloudinary.com/drgxflcsb/image/upload/v1675615227/Personal%20Portfolio/tech-alpha-2_tlagyh.png",
58 | description:
59 | "Tech Alpha is an online electronic accessories store that offers the latest and greatest electronic accessories. Our website features a clean, modern design, an easy-to-use interface and a robust shopping functionality built using Redux.js. All the product data has been served via JSON server and fetched using Axios.",
60 | tools: ["React.js", "Tailwind CSS", "Redux.js", "Redux Toolkit", "Axios"],
61 | liveLink: "https://tech-alpha-masud.netlify.app",
62 | fullStackLink: "",
63 | frontEndLink: "https://github.com/masudranashawon/tech-alpha",
64 | backEndLink: "https://github.com/masudranashawon/tech-alpha-server",
65 | },
66 | {
67 | id: 4,
68 | title: "Foodverse: A Recipe Finder Web Application",
69 | image1:
70 | "https://res.cloudinary.com/drgxflcsb/image/upload/v1675615230/Personal%20Portfolio/foodverse-1_mkf88w.png",
71 | image2:
72 | "https://res.cloudinary.com/drgxflcsb/image/upload/v1675615230/Personal%20Portfolio/foodvarse-2_qekgne.png",
73 | description:
74 | "Foodverse is a recipe web application, where a user can search for a variety of recipes and find the ingredients and quantities needed to make each recipe item. Also, favorite recipe items can be saved in the browser's local storage. It is easy to find different recipes for vegetarians and meat eaters, as well as those who want to lose weight.",
75 | tools: ["React.js", "React Router", "Tailwind CSS"],
76 | liveLink: "https://food-verse-masud.netlify.app/",
77 | fullStackLink: "",
78 | frontEndLink: "https://github.com/masudranashawon/foodverse",
79 | backEndLink: "",
80 | },
81 | ];
82 |
83 | const Projects = () => {
84 | return (
85 |
86 |
87 |
88 | {data.map((project) => (
89 |
90 | ))}
91 |
92 |
93 | );
94 | };
95 |
96 | export default Projects;
97 |
--------------------------------------------------------------------------------
/src/hooks/gsap.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import { gsap } from "gsap";
3 | import { ScrollTrigger } from "gsap/ScrollTrigger";
4 |
5 | gsap.registerPlugin(ScrollTrigger);
6 |
7 | export const useImageReveal = (el, delay = 0) => {
8 | useEffect(() => {
9 | gsap.fromTo(
10 | el.current,
11 | {
12 | y: "-100vh",
13 | },
14 | {
15 | y: 0,
16 | duration: 2,
17 | delay,
18 | ease: "power4.out",
19 | }
20 | );
21 | }, [el, delay]);
22 | };
23 |
24 | export const useHeadlineReveal = (items, delay = 0) => {
25 | useEffect(() => {
26 | const el = items.map((item) => item.current);
27 |
28 | gsap.fromTo(
29 | el,
30 | {
31 | y: 500,
32 | },
33 | {
34 | y: 0,
35 | duration: 1,
36 | delay,
37 | ease: "power4.out",
38 | stagger: 0.2,
39 | }
40 | );
41 | }, [items, delay]);
42 | };
43 |
44 | export const useLinkReveal = (items, delay = 0) => {
45 | useEffect(() => {
46 | const el = items.map((item) => item.current);
47 |
48 | gsap.fromTo(
49 | el,
50 | {
51 | opacity: 0,
52 | },
53 | {
54 | opacity: 1,
55 | duration: 2,
56 | delay,
57 | ease: "power4.out",
58 | stagger: 0.2,
59 | scrollTrigger: {
60 | trigger: el,
61 | },
62 | }
63 | );
64 | }, [items, delay]);
65 | };
66 |
67 | export const useBioReveal = (el, delay = 0) => {
68 | useEffect(() => {
69 | gsap.fromTo(
70 | el.current,
71 | {
72 | y: 500,
73 | },
74 | {
75 | y: 0,
76 | duration: 1.5,
77 | delay,
78 | ease: "power4.out",
79 | }
80 | );
81 | }, [el, delay]);
82 | };
83 |
84 | export const useSocialReveal = (el, delay = 0) => {
85 | useEffect(() => {
86 | gsap.fromTo(
87 | el.current,
88 | {
89 | x: -500,
90 | },
91 | {
92 | x: 0,
93 | duration: 1.5,
94 | delay,
95 | ease: "power4.out",
96 | }
97 | );
98 | }, [el, delay]);
99 | };
100 |
101 | export const useSectionTitleReveal = (el, delay = 0) => {
102 | useEffect(() => {
103 | gsap.fromTo(
104 | el.current,
105 | {
106 | y: 200,
107 | },
108 | {
109 | y: 0,
110 | duration: 1.5,
111 | delay,
112 | ease: "power4.out",
113 | scrollTrigger: {
114 | trigger: el.current,
115 | },
116 | }
117 | );
118 | }, [el, delay]);
119 | };
120 |
121 | export const useProjectLeftRightReveal = (items, delay = 0) => {
122 | useEffect(() => {
123 | const el = items.map((item) => item.current);
124 |
125 | gsap.fromTo(
126 | el,
127 | {
128 | y: 500,
129 | },
130 | {
131 | y: 0,
132 | duration: 2,
133 | delay,
134 | ease: "power4.out",
135 | stagger: 0.3,
136 | scrollTrigger: {
137 | trigger: el,
138 | },
139 | }
140 | );
141 | }, [items, delay]);
142 | };
143 |
144 | export const useSkillLineReveal = (items) => {
145 | useEffect(() => {
146 | items.forEach((el) =>
147 | gsap.to(el, {
148 | scrollTrigger: {
149 | trigger: el,
150 | onEnter() {
151 | el.classList.add("reveal");
152 | },
153 | },
154 | })
155 | );
156 | }, [items]);
157 | };
158 |
159 | export const useSkillTextReveal = (el) => {
160 | useEffect(() => {
161 | gsap.fromTo(
162 | el,
163 | {
164 | y: 200,
165 | },
166 | {
167 | y: 0,
168 | duration: 1,
169 | ease: "power4.out",
170 | stagger: 0.3,
171 | scrollTrigger: {
172 | trigger: el,
173 | },
174 | }
175 | );
176 | }, [el]);
177 | };
178 |
179 | export const useFooterReveal = (el) => {
180 | useEffect(() => {
181 | gsap.fromTo(
182 | el.current,
183 | {
184 | y: -100,
185 | },
186 | {
187 | y: 0,
188 | duration: 1,
189 | ease: "power4.out",
190 | stagger: 0.3,
191 | scrollTrigger: {
192 | trigger: el.current,
193 | },
194 | }
195 | );
196 | }, [el]);
197 | };
198 |
199 | export const useInputReveal = (items, delay = 0) => {
200 | useEffect(() => {
201 | const el = items.map((item) => item.current);
202 |
203 | gsap.fromTo(
204 | el,
205 | {
206 | y: 200,
207 | },
208 | {
209 | y: 0,
210 | duration: 2,
211 | delay,
212 | ease: "power4.out",
213 | stagger: 0.2,
214 | scrollTrigger: {
215 | trigger: el,
216 | },
217 | }
218 | );
219 | }, [items, delay]);
220 | };
221 |
222 | export const useGsapDownStagger = (arr, delay = 0) => {
223 | useEffect(() => {
224 | const el = arr.map((item) => item.current);
225 |
226 | gsap.fromTo(
227 | el,
228 | {
229 | y: "-100%",
230 | opacity: 0,
231 | },
232 | {
233 | y: 0,
234 | opacity: 1,
235 | duration: 1.5,
236 | stagger: 0.1,
237 | ease: "power4.out",
238 | delay: delay,
239 | scrollTrigger: {
240 | trigger: el,
241 | },
242 | }
243 | );
244 | }, [arr, delay]);
245 | };
246 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300..700&display=swap");
2 |
3 | @tailwind base;
4 | @tailwind components;
5 | @tailwind utilities;
6 |
7 | @font-face {
8 | font-family: "Moonhouse";
9 | src: url("./fonts/moonhouse.woff2") format("woff2");
10 | }
11 |
12 | :root {
13 | --color-dark: #050505;
14 | --color-light: #f7f7f7;
15 | }
16 |
17 | ::-webkit-scrollbar {
18 | width: 5px;
19 | }
20 |
21 | ::-webkit-scrollbar-thumb {
22 | height: 10%;
23 | background-color: rgba(247, 247, 247, 0.5);
24 | border-radius: 50px;
25 | }
26 |
27 | ::-webkit-scrollbar-thumb:hover {
28 | background-color: var(--color-light);
29 | }
30 |
31 | ::-webkit-scrollbar-track {
32 | background-color: var(--color-dark);
33 | }
34 |
35 | ::selection {
36 | background-color: #22d3ee;
37 | color: var(--color-dark);
38 | }
39 |
40 | *,
41 | *::after,
42 | *::before {
43 | cursor: none;
44 | }
45 |
46 | html,
47 | body {
48 | overflow-x: none;
49 | }
50 |
51 | html {
52 | font-size: 62.5%;
53 | }
54 |
55 | body {
56 | background-color: var(--color-dark);
57 | color: var(--color-light);
58 | font-family: "Space Grotesk", sans-serif;
59 | font-size: 1.6rem;
60 | line-height: 1.6;
61 | }
62 |
63 | .inner-cursor {
64 | background-color: var(--color-light);
65 | width: 10px;
66 | height: 10px;
67 | position: fixed;
68 | left: 10px;
69 | z-index: 9999;
70 | border-radius: 50%;
71 | transform: translate(-50%, -50%);
72 | mix-blend-mode: difference;
73 | pointer-events: none;
74 | transition: width 0.5s, height 0.5s;
75 | }
76 |
77 | .inner-cursor.grow {
78 | width: 25px;
79 | height: 25px;
80 | }
81 |
82 | .outer-cursor {
83 | position: fixed;
84 | left: 10px;
85 | width: 25px;
86 | height: 25px;
87 | z-index: 9999;
88 | border-radius: 50%;
89 | transform: translate(-50%, -50%);
90 | mix-blend-mode: difference;
91 | pointer-events: none;
92 | border: 1px solid var(--color-light);
93 | transition: 0.1s;
94 | }
95 |
96 | .app {
97 | position: relative;
98 | }
99 |
100 | input[type="submit"] {
101 | letter-spacing: inherit;
102 | word-spacing: inherit;
103 | }
104 |
105 | input,
106 | textarea,
107 | button {
108 | letter-spacing: 2px;
109 | word-spacing: 3px;
110 | }
111 |
112 | .link-item {
113 | position: relative;
114 | }
115 |
116 | .link-item::before {
117 | content: "";
118 | position: absolute;
119 | width: 0%;
120 | height: 1px;
121 | background-color: var(--color-light);
122 | left: 50%;
123 | bottom: -2px;
124 | transform: translateX(-50%);
125 | transition: all 0.3s;
126 | }
127 |
128 | .link-item:hover::before {
129 | width: 100%;
130 | }
131 |
132 | .hero {
133 | position: relative;
134 | }
135 |
136 | .hero-image,
137 | .project-right,
138 | .about-left {
139 | width: 500px;
140 | height: 500px;
141 | overflow: hidden;
142 | }
143 |
144 | .noise {
145 | background-image: url("./assets/images/noise.gif");
146 | position: fixed;
147 | width: 100vw;
148 | height: 100vh;
149 | z-index: -9999;
150 | top: 0;
151 | left: 0;
152 | bottom: 0;
153 | right: 0;
154 | opacity: 0.07;
155 | }
156 |
157 | .circle-left,
158 | .circle-right {
159 | width: 60vw;
160 | aspect-ratio: 1/1;
161 | position: fixed;
162 | border: 1px dashed var(--color-light);
163 | border-radius: 50%;
164 | opacity: 0.2;
165 | z-index: -9998;
166 | animation: spin 90s infinite linear;
167 | }
168 |
169 | .circle-left {
170 | top: -40%;
171 | left: -20%;
172 | }
173 |
174 | .circle-right {
175 | bottom: -40%;
176 | right: -20%;
177 | }
178 |
179 |
180 |
181 | .shutter {
182 | position: absolute;
183 | z-index: 100;
184 | font-family: Moonhouse, serif;
185 | }
186 |
187 | .shutter h1 {
188 | font-size: 13rem;
189 | }
190 |
191 | .shutter-left {
192 | top: 0;
193 | left: 0;
194 | }
195 |
196 | .shutter-right {
197 | bottom: 0;
198 | right: 0;
199 | }
200 |
201 | .section-title {
202 | font-size: 10vw;
203 | line-height: 1;
204 | font-family: Moonhouse, serif;
205 | }
206 |
207 | .skill-item {
208 | position: relative;
209 | }
210 |
211 | .skill-item::after,
212 | .skill-item::before {
213 | content: "";
214 | position: absolute;
215 | height: 1px;
216 | bottom: 0;
217 | left: 0;
218 | background-color: var(--color-light);
219 | }
220 |
221 | .skill-item::before {
222 | width: 0%;
223 | opacity: 0.2;
224 | transition: 1.5s;
225 | }
226 |
227 | .skill-item.reveal::before {
228 | width: 100%;
229 | }
230 |
231 | .skill-item::after {
232 | width: 0%;
233 | transition: all 0.5s;
234 | background-color: #22d3ee;
235 | }
236 |
237 | .skill-item:hover::after {
238 | width: 100%;
239 | }
240 |
241 | .skill-number {
242 | font-size: 5rem;
243 | }
244 |
245 | .skill-title {
246 | font-size: 2rem;
247 | }
248 |
249 | .shutter h1 {
250 | font-size: 12rem;
251 | }
252 |
253 | .section-title {
254 | font-size: 12rem;
255 | }
256 |
257 | @keyframes spin {
258 | to {
259 | transform: rotate(360deg);
260 | }
261 | }
262 |
263 | @media screen and (max-width: 1366px) {
264 | .shutter h1 {
265 | font-size: 10rem;
266 | }
267 |
268 | .section-title {
269 | font-size: 9rem;
270 | }
271 | }
272 |
273 | @media screen and (max-width: 768px) {
274 |
275 | .hero::before,
276 | .hero::after {
277 | font-size: 8rem;
278 | }
279 |
280 | .section-title {
281 | font-size: 8rem;
282 | }
283 |
284 | .shutter h1 {
285 | font-size: 8rem;
286 | }
287 | }
288 |
289 | @media screen and (max-width: 640px) {
290 |
291 | .circle-left,
292 | .circle-right {
293 | width: 80vw;
294 | }
295 |
296 | html {
297 | font-size: 50%;
298 | }
299 |
300 | .container {
301 | padding: 0 2rem;
302 | }
303 |
304 | .hero::before,
305 | .hero::after {
306 | font-size: 6rem;
307 | }
308 |
309 | .hero-image,
310 | .about-left {
311 | width: 100%;
312 | height: 500px;
313 | }
314 |
315 | .project-right {
316 | width: 100%;
317 | height: 300px;
318 | }
319 |
320 | .shutter h1 {
321 | font-size: 12vw;
322 | }
323 | }
324 |
325 | @media screen and (max-width: 500px) {
326 | html {
327 | font-size: 40%;
328 | }
329 |
330 | .circle-left,
331 | .circle-right {
332 | width: 90vw;
333 | }
334 |
335 | .hero::before,
336 | .hero::after {
337 | font-size: 5rem;
338 | }
339 |
340 | .section-title {
341 | font-size: 6.5rem;
342 | }
343 |
344 | .shutter h1 {
345 | font-size: 14vw;
346 | }
347 | }
--------------------------------------------------------------------------------