├── src
├── assets
│ ├── tech
│ │ ├── py.png
│ │ ├── aws.png
│ │ ├── css.png
│ │ ├── figma.png
│ │ ├── git.png
│ │ ├── html.png
│ │ ├── java.png
│ │ ├── neo.png
│ │ ├── node.webp
│ │ ├── raspi.png
│ │ ├── eslint.png
│ │ ├── github.png
│ │ ├── reactjs.png
│ │ ├── javascript.png
│ │ ├── postgresql.png
│ │ └── vite.svg
│ ├── logo
│ │ └── icon.png
│ ├── portfolio.png
│ ├── avatar
│ │ └── avatar.jpg
│ ├── projects
│ │ ├── memory.jpg
│ │ ├── skyspa.jpg
│ │ ├── foremen.jpg
│ │ ├── sybaris.jpg
│ │ └── calculator.jpg
│ ├── menu.svg
│ ├── close.svg
│ └── index.js
├── Components
│ ├── MarqueeCards.jsx
│ ├── Loader.jsx
│ ├── Particles
│ │ ├── HeroParticles.jsx
│ │ ├── ParticlesComponent.jsx
│ │ └── particlesOptions.js
│ ├── PreloadMedia.jsx
│ ├── elements
│ │ ├── ToggleButton.jsx
│ │ ├── Arrow.jsx
│ │ ├── HeroScroller.jsx
│ │ ├── BgQuote.jsx
│ │ └── ImageSlider.jsx
│ ├── SocialLinks.jsx
│ ├── SectionTitle.jsx
│ ├── HeroText.jsx
│ ├── SkillsCards.jsx
│ ├── nav
│ │ └── NavBar.jsx
│ ├── ContactForm.jsx
│ └── ProjectCards.jsx
├── App
│ ├── App.jsx
│ ├── index.jsx
│ └── index.css
├── Pages
│ ├── Projects.jsx
│ ├── Hero.jsx
│ ├── Skills.jsx
│ ├── Contact.jsx
│ └── About.jsx
├── styles.js
└── Constants
│ └── constants.js
├── public
├── Fonts
│ ├── Feogra
│ │ └── Feogra.ttf
│ ├── Mario
│ │ └── Brugty.ttf
│ └── Morganite
│ │ ├── License.pdf
│ │ ├── Morganite-Black.ttf
│ │ ├── Morganite-Bold.ttf
│ │ ├── Morganite-Book.ttf
│ │ ├── Morganite-Light.ttf
│ │ ├── Morganite-Thin.ttf
│ │ ├── Morganite-Medium.ttf
│ │ ├── Morganite-SemiBold.ttf
│ │ ├── Morganite-BoldItalic.ttf
│ │ ├── Morganite-BookItalic.ttf
│ │ ├── Morganite-ExtraBold.ttf
│ │ ├── Morganite-ExtraLight.ttf
│ │ ├── Morganite-ThinItalic.ttf
│ │ ├── Morganite-BlackItalic.ttf
│ │ ├── Morganite-LightItalic.ttf
│ │ ├── Morganite-MediumItalic.ttf
│ │ ├── Morganite-ExtraBoldItalic.ttf
│ │ ├── Morganite-SemiBoldItalic.ttf
│ │ ├── Morganite-ExtraLightItalic.ttf
│ │ └── morganiteFont.css
└── cv
│ └── SaraEcheverriasCV2024.pdf
├── postcss.config.js
├── vite.config.js
├── .gitignore
├── .eslintrc.cjs
├── tailwind.config.js
├── index.html
├── README.md
└── package.json
/src/assets/tech/py.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/py.png
--------------------------------------------------------------------------------
/src/assets/logo/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/logo/icon.png
--------------------------------------------------------------------------------
/src/assets/portfolio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/portfolio.png
--------------------------------------------------------------------------------
/src/assets/tech/aws.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/aws.png
--------------------------------------------------------------------------------
/src/assets/tech/css.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/css.png
--------------------------------------------------------------------------------
/src/assets/tech/figma.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/figma.png
--------------------------------------------------------------------------------
/src/assets/tech/git.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/git.png
--------------------------------------------------------------------------------
/src/assets/tech/html.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/html.png
--------------------------------------------------------------------------------
/src/assets/tech/java.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/java.png
--------------------------------------------------------------------------------
/src/assets/tech/neo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/neo.png
--------------------------------------------------------------------------------
/src/assets/tech/node.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/node.webp
--------------------------------------------------------------------------------
/src/assets/tech/raspi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/raspi.png
--------------------------------------------------------------------------------
/src/assets/tech/eslint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/eslint.png
--------------------------------------------------------------------------------
/src/assets/tech/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/github.png
--------------------------------------------------------------------------------
/src/assets/tech/reactjs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/reactjs.png
--------------------------------------------------------------------------------
/public/Fonts/Feogra/Feogra.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Feogra/Feogra.ttf
--------------------------------------------------------------------------------
/public/Fonts/Mario/Brugty.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Mario/Brugty.ttf
--------------------------------------------------------------------------------
/src/assets/avatar/avatar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/avatar/avatar.jpg
--------------------------------------------------------------------------------
/src/assets/projects/memory.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/projects/memory.jpg
--------------------------------------------------------------------------------
/src/assets/projects/skyspa.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/projects/skyspa.jpg
--------------------------------------------------------------------------------
/src/assets/tech/javascript.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/javascript.png
--------------------------------------------------------------------------------
/src/assets/tech/postgresql.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/tech/postgresql.png
--------------------------------------------------------------------------------
/src/assets/projects/foremen.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/projects/foremen.jpg
--------------------------------------------------------------------------------
/src/assets/projects/sybaris.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/projects/sybaris.jpg
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/public/Fonts/Morganite/License.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/License.pdf
--------------------------------------------------------------------------------
/public/cv/SaraEcheverriasCV2024.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/cv/SaraEcheverriasCV2024.pdf
--------------------------------------------------------------------------------
/src/assets/projects/calculator.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/src/assets/projects/calculator.jpg
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-Black.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-Bold.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-Book.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-Book.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-Light.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-Thin.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-Medium.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-SemiBold.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-BoldItalic.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-BookItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-BookItalic.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-ExtraBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-ExtraBold.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-ExtraLight.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-ExtraLight.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-ThinItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-ThinItalic.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-BlackItalic.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-LightItalic.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-MediumItalic.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-ExtraBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-ExtraBoldItalic.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-SemiBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-SemiBoldItalic.ttf
--------------------------------------------------------------------------------
/public/Fonts/Morganite/Morganite-ExtraLightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miketopeak/whoami/HEAD/public/Fonts/Morganite/Morganite-ExtraLightItalic.ttf
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 | import dotenv from 'dotenv';
4 |
5 | dotenv.config();
6 |
7 | export default defineConfig({
8 | plugins: [react()],
9 | server: {
10 | host: true,
11 | },
12 | });
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 | .env
15 |
16 | # Editor directories and files
17 | .vscode/*
18 | !.vscode/extensions.json
19 | .idea
20 | .DS_Store
21 | *.suo
22 | *.ntvs*
23 | *.njsproj
24 | *.sln
25 | *.sw?
26 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | browser: true,
4 | es2021: true,
5 | },
6 | extends: [
7 | 'plugin:react/recommended',
8 | 'airbnb',
9 | ],
10 | overrides: [
11 | ],
12 | parserOptions: {
13 | ecmaVersion: 'latest',
14 | sourceType: 'module',
15 | },
16 | plugins: [
17 | 'react',
18 | ],
19 | rules: {
20 | "import/prefer-default-export": "off",
21 | "semi": "off",
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/src/Components/MarqueeCards.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: MarqueeCards.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import Marquee from "react-fast-marquee";
11 |
12 | const MarqueeCards = ({children, direction}) => {
13 |
14 | return (
15 |
21 | {children}
22 |
23 | );
24 | };
25 |
26 | export default MarqueeCards;
27 |
--------------------------------------------------------------------------------
/src/Components/Loader.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: Loader.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import React from "react";
11 |
12 | const Loader = () => {
13 | return (
14 |
15 |
19 | M
20 |
21 |
22 |
23 | );
24 | };
25 |
26 | export default Loader;
27 |
--------------------------------------------------------------------------------
/src/App/App.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: App.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 02/06/2023
8 | */
9 |
10 | import NavBar from "../Components/nav/NavBar";
11 | import Hero from "../Pages/Hero";
12 | import Projects from "../Pages/Projects";
13 | import About from "../Pages/About";
14 | import Skills from "../Pages/Skills";
15 | import Contact from "../Pages/Contact";
16 |
17 | function App() {
18 | return (
19 | <>
20 |
21 |
22 |
23 |
24 |
25 |
26 | >
27 | );
28 | }
29 |
30 | export default App;
--------------------------------------------------------------------------------
/src/Components/Particles/HeroParticles.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: HeroParticles.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import ParticlesComponent from "./ParticlesComponent";
11 | import { heroOptions } from "./particlesOptions";
12 |
13 | const HeroParticles = () => {
14 | return (
15 |
22 | );
23 | };
24 |
25 | export default HeroParticles;
26 |
--------------------------------------------------------------------------------
/src/Pages/Projects.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: Projects.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 20/04/2024
8 | */
9 |
10 | import Works from "../Components/ProjectCards";
11 | import SectionTitle from "../Components/SectionTitle";
12 |
13 | const Projects = () => {
14 | return (
15 |
23 | );
24 | };
25 |
26 | export default Projects;
--------------------------------------------------------------------------------
/src/Components/PreloadMedia.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: PreloadMedia.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import {useState} from 'react'
11 | import Loader from './Loader';
12 |
13 | const PreloadMedia = ({images, children}) => {
14 | const [loaded, setLoaded] = useState(false);
15 |
16 | const onLoad = () => {
17 | setLoaded(true);
18 | }
19 |
20 | const imageElements = images.map((imageSrc) => {
21 | const img = new Image();
22 | img.src = imageSrc;
23 | img.onload = onLoad;
24 | return img;
25 | });
26 |
27 | return loaded ? children :
28 | }
29 |
30 | export default PreloadMedia;
--------------------------------------------------------------------------------
/src/Components/elements/ToggleButton.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: ToggleButton.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 02/06/2023
8 | */
9 |
10 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
11 | import { icons } from "../../Constants/constants";
12 |
13 | const ToggleButton = ({isActive, handleClick}) => {
14 | return (
15 |
16 |
17 |
18 | );
19 | };
20 |
21 | export default ToggleButton;
22 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | import tailwindcss from 'tailwindcss';
2 | import autoprefixer from 'autoprefixer';
3 |
4 | /** @type {import('tailwindcss').Config} */
5 | export default {
6 | content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
7 | theme: {
8 | extend: {
9 | dropShadow: {
10 | green: '0 0 10rem #29c26f',
11 | },
12 | },
13 | colors: {
14 | primary: {
15 | 200: '#ffffff', // almost white
16 | 400: '#B64D80', // dark pink
17 | 500: '#CD6899', // light pink
18 | 600: '#99235C', // wine
19 | },
20 | grayscale: {
21 | 25: '#E4E2DD', // beige
22 | 50: '#CD6899',
23 | 100: '#efefef',
24 | 200: '#FDFDFF',
25 | 950: '#16161b',
26 | },
27 | },
28 | },
29 | plugins: [tailwindcss, autoprefixer],
30 | };
31 |
--------------------------------------------------------------------------------
/src/styles.js:
--------------------------------------------------------------------------------
1 | /* Copyright (C), 2023-2024, Mikael Laine (mikael)
2 | @author Mikael Laine
3 | FileName: styles.js
4 | @version: I
5 | Creation: 02/06/2023
6 | Last modification: 03/06/2023 */
7 |
8 | const styles = {
9 | paddingX: 'sm:px-16 px-6',
10 | paddingY: 'sm:py-16 py-6',
11 | padding: 'sm:px-16 px-6 sm:py-16 py-10',
12 |
13 | heroHeadText:
14 | 'font-black text-white lg:text-[80px] sm:text-[60px] xs:text-[50px] text-[40px] lg:leading-[98px] mt-2',
15 | heroSubText:
16 | 'text-[#dfd9ff] font-medium lg:text-[30px] sm:text-[26px] xs:text-[20px] text-[16px] lg:leading-[40px]',
17 |
18 | sectionHeadText:
19 | 'text-white font-black md:text-[60px] sm:text-[50px] xs:text-[40px] text-[30px]',
20 | sectionSubText:
21 | 'sm:text-[18px] text-[14px] text-secondary uppercase tracking-wider',
22 | };
23 |
24 | export { styles };
25 |
--------------------------------------------------------------------------------
/src/App/index.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: index.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 02/06/2023
8 | */
9 |
10 |
11 | import React from "react";
12 | import ReactDOM from "react-dom/client";
13 | import { BrowserRouter } from "react-router-dom";
14 | import PreloadMedia from "../Components/PreloadMedia";
15 | import { media } from "../Constants/constants";
16 | import App from "./App";
17 | import "./index.css";
18 | import "font-awesome/css/font-awesome.min.css";
19 | import "../../public/Fonts/Morganite/morganiteFont.css";
20 |
21 | ReactDOM.createRoot(document.getElementById("root")).render(
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | );
30 |
--------------------------------------------------------------------------------
/src/Components/elements/Arrow.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: Arrow.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 02/06/2023
8 | */
9 |
10 | const Arrow = () => {
11 | return (
12 |
13 |
14 |
23 |
24 |
25 |
26 |
31 |
32 | );
33 | };
34 |
35 | export default Arrow;
36 |
--------------------------------------------------------------------------------
/src/Pages/Hero.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: Hero.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import { m, LazyMotion, domAnimation } from "framer-motion";
11 | import HeroText from "../Components/HeroText";
12 | import HeroParticles from "../Components/Particles/HeroParticles";
13 | import HeroScroller from "../Components/elements/HeroScroller";
14 |
15 | const Hero = () => {
16 | return (
17 |
18 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | );
30 | };
31 |
32 | export default Hero;
33 |
--------------------------------------------------------------------------------
/src/assets/menu.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Mike - Personal portfolio
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/Components/Particles/ParticlesComponent.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: ParticlesComponent.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 02/06/2023
8 | */
9 |
10 | import { useCallback } from "react";
11 | import Particles from "react-particles";
12 | import { loadFull } from "tsparticles";
13 |
14 | const ParticlesComponent = (props) => {
15 | const { particlesOptions, className, id } = props;
16 |
17 | let isInitialized = false;
18 |
19 | const particlesInit = useCallback(async (engine) => {
20 | if(!isInitialized) {
21 | await loadFull(engine);
22 | isInitialized = true;
23 | }
24 |
25 | }, []);
26 |
27 | const particlesLoaded = useCallback(async (container) => {
28 | await container
29 | }, []);
30 |
31 | return (
32 |
39 | );
40 | };
41 |
42 | export default ParticlesComponent;
43 |
--------------------------------------------------------------------------------
/src/Components/elements/HeroScroller.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: HeroScroller.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 02/06/2023
8 | */
9 |
10 | import { m } from "framer-motion";
11 |
12 | const HeroScroller = () => {
13 | return (
14 |
36 | );
37 | };
38 |
39 | export default HeroScroller;
40 |
--------------------------------------------------------------------------------
/src/Components/elements/BgQuote.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: BgQuote.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 02/06/2023
8 | */
9 |
10 | import { m, LazyMotion, domAnimation } from "framer-motion";
11 | import Arrow from "./Arrow";
12 |
13 | const BgQuote = (props) => {
14 | const { text } = props;
15 |
16 | return (
17 |
18 |
24 |
28 | {text}
29 |
30 |
33 |
34 |
35 | );
36 | };
37 |
38 | export default BgQuote;
39 |
--------------------------------------------------------------------------------
/src/assets/close.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/Components/SocialLinks.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: SocialLinks.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
11 | import { icons } from "../Constants/constants";
12 |
13 | const SocialLinks = () => {
14 | return (
15 |
35 | );
36 | };
37 |
38 | export default SocialLinks;
39 |
--------------------------------------------------------------------------------
/src/Pages/Skills.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: Skills.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import MarqueeCards from "../Components/MarqueeCards";
11 | import SectionTitle from "../Components/SectionTitle";
12 | import SkillsCards from "../Components/SkillsCards";
13 |
14 | const Skills = () => {
15 | return (
16 |
37 | );
38 | };
39 |
40 | export default Skills;
41 |
--------------------------------------------------------------------------------
/src/Components/SectionTitle.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: SectionTitle.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import { m, LazyMotion, domAnimation } from "framer-motion";
11 |
12 | const SectionTitle = (props) => {
13 | const { title, subtitle } = props;
14 |
15 | return (
16 |
17 |
23 |
32 | {subtitle}
33 |
34 |
38 | {title.split("").map((char, index) => {
39 | if(char === " ") {
40 | return " ";
41 | }
42 | return {char}
43 | })}
44 |
45 |
46 |
47 | );
48 | };
49 |
50 | export default SectionTitle;
51 |
--------------------------------------------------------------------------------
/src/assets/tech/vite.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Components/elements/ImageSlider.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: ImageSlider.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 02/06/2023
8 | */
9 |
10 | import { useEffect, useState, useRef } from "react";
11 | import { m, LazyMotion, domAnimation } from "framer-motion";
12 |
13 | const ImageSlider = ({ images }) => {
14 | const [index, setIndex] = useState(0);
15 | const [isInViewport, setIsInViewport] = useState(false);
16 | const imageRef = useRef(null);
17 |
18 | useEffect(() => {
19 | const interval = setInterval(() => {
20 | if (isInViewport) {
21 | setIndex((i) => (i + 1) % images.length);
22 | }
23 | }, 3000);
24 |
25 | return () => clearInterval(interval);
26 | }, [images, isInViewport]);
27 |
28 | useEffect(() => {
29 | const observer = new IntersectionObserver(
30 | ([entry]) => setIsInViewport(entry.isIntersecting),
31 | { threshold: 0 }
32 | );
33 |
34 | if (imageRef.current) {
35 | observer.observe(imageRef.current);
36 | }
37 |
38 | return () => observer.disconnect();
39 | }, []);
40 |
41 | return (
42 |
43 |
56 |
57 | );
58 | };
59 |
60 | export default ImageSlider;
61 |
--------------------------------------------------------------------------------
/src/Pages/Contact.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: Contact.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import { m, LazyMotion, domAnimation } from "framer-motion";
11 | import SectionTitle from "../Components/SectionTitle";
12 | import ContactForm from "../Components/ContactForm";
13 | import SocialLinks from "../Components/SocialLinks";
14 |
15 | const Contact = () => {
16 | return (
17 |
48 | );
49 | };
50 |
51 | export default Contact;
52 |
--------------------------------------------------------------------------------
/src/assets/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: index.js
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | // Logo
11 | import mikeIcon from './logo/icon.png';
12 |
13 | // Technologies
14 | import htmlIcon from './tech/html.png';
15 | import cssIcon from './tech/css.png';
16 | import jsIcon from './tech/javascript.png';
17 | import reactIcon from './tech/reactjs.png';
18 | import awsIcon from './tech/aws.png';
19 | import javaIcon from './tech/java.png';
20 | import gitIcon from './tech/git.png';
21 | import githubIcon from './tech/github.png';
22 | import figmaIcon from './tech/figma.png';
23 | import psqlIcon from './tech/postgresql.png';
24 | import eslintIcon from './tech/eslint.png';
25 | import viteIcon from './tech/vite.svg';
26 | import pyIcon from './tech/py.png';
27 | import nodeIcon from './tech/node.webp';
28 | import neoIcon from './tech/neo.png';
29 | import raspIcon from './tech/raspi.png';
30 | import close from './close.svg';
31 | import menu from './menu.svg';
32 |
33 | // Projects
34 | import memoryGame from './projects/memory.jpg';
35 | import sybaris from './projects/sybaris.jpg'
36 | import foremen from './projects/foremen.jpg';
37 | import calculator from './projects/calculator.jpg';
38 | import skyspa from './projects/skyspa.jpg'
39 |
40 | // Avatar
41 | import avatar from './avatar/avatar.jpg';
42 |
43 | export {
44 | menu,
45 | close,
46 | htmlIcon,
47 | cssIcon,
48 | jsIcon,
49 | reactIcon,
50 | awsIcon,
51 | javaIcon,
52 | gitIcon,
53 | githubIcon,
54 | eslintIcon,
55 | figmaIcon,
56 | psqlIcon,
57 | nodeIcon,
58 | pyIcon,
59 | viteIcon,
60 | neoIcon,
61 | raspIcon,
62 | memoryGame,
63 | foremen,
64 | calculator,
65 | skyspa,
66 | sybaris,
67 | avatar,
68 | mikeIcon,
69 | };
70 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Who's Mikael ?
2 | Welcome to my portfolio repository! This project showcases my skills using React, ESLint, Tailwind, and Vite. It includes a brief introduction about me, my projects, the technologies I've worked with, and my experience. You'll also find a contact form at the bottom and my social media links below it. Feel free to explore and connect with me!
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Features •
11 | Files •
12 | How To Use •
13 | Packages
14 |
15 |
16 | Try it out here
17 |
18 |
19 | ## Features
20 |
21 | * Vite
22 | ```bash
23 | # Install dependencies
24 | $ npm i
25 | # run the app
26 | $ npm run dev
27 | ```
28 |
29 | ## Files
30 |
31 | - src: the file that implements de solution.
32 | - assets: resources that are used in an application.
33 | - components: reusable pieces of code that define the appearance and behavior of a part of the UI.
34 | - pages: the different areas of the portfolio.
35 | - constants: values that cannot be altered by the program during normal execution.
36 |
37 |
38 | ## How To Use
39 |
40 | To clone and run this application, you'll need [Git](https://git-scm.com), [Node.js](https://nodejs.org/en) and [Vite](https://vitejs.dev/) installed on your computer. From your command line:
41 |
42 | ```bash
43 | # Clone this repository
44 | $ git clone https://github.com/miketopeak/whoami
45 |
46 | # Install dependencies
47 | $ npm i
48 |
49 | # Run the app
50 | $ npm run dev
51 | ```
52 |
53 | ## Packages
54 |
55 | This software uses the following open source packages:
56 |
57 | - [Vite](https://vitejs.dev/)
58 | - [React](https://reactjs.org/)
59 | - [Tailwind](https://tailwindcss.com/)
60 |
--------------------------------------------------------------------------------
/src/Components/HeroText.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: HeroText.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import { m, LazyMotion, domAnimation } from "framer-motion";
11 |
12 | const HeroText = () => {
13 | const name = "Mikael ?";
14 |
15 | return (
16 |
20 |
21 |
28 |
33 | WHO'S{" "}
34 |
35 |
40 | {name.split("").map((char, index) => {
41 | if (char === " ") {
42 | return " ";
43 | }
44 | return (
45 |
50 | {char}
51 |
52 | );
53 | })}
54 |
55 |
56 |
57 |
58 | );
59 | };
60 |
61 | export default HeroText;
62 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vs-portfolio",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "vite": "^4.2.0",
13 | "@vitejs/plugin-react": "^3.1.0",
14 | "@types/react-dom": "^18.0.11",
15 | "@emailjs/browser": "^3.11.0",
16 | "@fortawesome/fontawesome-svg-core": "^6.4.0",
17 | "@fortawesome/free-brands-svg-icons": "^6.4.0",
18 | "@fortawesome/free-solid-svg-icons": "^6.4.0",
19 | "@fortawesome/react-fontawesome": "^0.2.0",
20 | "@motionone/utils": "^10.15.1",
21 | "@react-hook/window-size": "^3.1.1",
22 | "emailjs": "^4.0.2",
23 | "emailjs-com": "^3.2.0",
24 | "font-awesome": "^4.7.0",
25 | "framer-motion": "^10.11.2",
26 | "gsap": "^3.11.5",
27 | "localforage": "^1.10.0",
28 | "lodash-move": "^1.1.1",
29 | "match-sorter": "^6.3.1",
30 | "normalize-wheel": "^1.0.1",
31 | "pathseg": "^1.2.1",
32 | "react": "^18.2.0",
33 | "react-dom": "^18.2.0",
34 | "react-fast-marquee": "^1.3.5",
35 | "react-globe.gl": "^2.24.1",
36 | "react-intersection-observer": "^9.4.3",
37 | "react-particles": "^2.9.3",
38 | "react-responsive": "^9.0.2",
39 | "react-router-dom": "^6.10.0",
40 | "react-scroll": "^1.8.9",
41 | "react-simple-typewriter": "^5.0.1",
42 | "react-tilt": "^1.0.2",
43 | "react-tsparticles": "^2.9.3",
44 | "react-use": "^17.4.0",
45 | "sort-by": "^0.0.2",
46 | "tsparticles": "^2.9.3",
47 | "tailwindcss": "^3.3.1",
48 | "autoprefixer": "^10.4.14",
49 | "dotenv": "^16.0.3"
50 | },
51 | "devDependencies": {
52 | "@types/react": "^18.0.28",
53 | "eslint": "^8.42.0",
54 | "eslint-config-airbnb": "^19.0.4",
55 | "eslint-plugin-import": "^2.27.5",
56 | "eslint-plugin-jsx-a11y": "^6.7.1",
57 | "eslint-plugin-react": "^7.32.2",
58 | "eslint-plugin-react-hooks": "^4.6.0",
59 | "postcss": "^8.4.21"
60 | },
61 | "description": "",
62 | "main": "postcss.config.js",
63 | "keywords": [],
64 | "author": "",
65 | "license": "ISC"
66 | }
67 |
--------------------------------------------------------------------------------
/src/Components/SkillsCards.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: SkillCards.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import { m, LazyMotion, domAnimation } from "framer-motion";
11 | import { skills } from "../Constants/constants";
12 |
13 | const SkillsCards = () => {
14 | return (
15 |
16 |
17 |
18 | {skills.map((skill, index) => (
19 |
34 |
35 |
40 |
47 | {skill.title}
48 |
49 |
57 | {skill.description}
58 |
59 |
60 |
61 | ))}
62 |
63 |
64 | );
65 | };
66 |
67 | export default SkillsCards;
--------------------------------------------------------------------------------
/public/Fonts/Morganite/morganiteFont.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "Morganite Black";
3 | src: url(/Fonts/Morganite/Morganite-Black.ttf);
4 | }
5 |
6 | @font-face {
7 | font-family: "Morganite Black Italic";
8 | src: url(/Fonts/Morganite/Morganite-BlackItalic.ttf);
9 | }
10 |
11 | @font-face {
12 | font-family: "Morganite Bold";
13 | src: url(/Fonts/Morganite/Morganite-Bold.ttf);
14 | }
15 |
16 | @font-face {
17 | font-family: "Morganite Bold Italic";
18 | src: url(/Fonts/Morganite/Morganite-BoldItalic.ttf);
19 | }
20 |
21 | @font-face {
22 | font-family: "Morganite Book";
23 | src: url(/Fonts/Morganite/Morganite-Book.ttf);
24 | }
25 |
26 | @font-face {
27 | font-family: "Morganite Book Italic";
28 | src: url(/Fonts/Morganite/Morganite-BookItalic.ttf);
29 | }
30 |
31 | @font-face {
32 | font-family: "Morganite Extra Bold";
33 | src: url(/Fonts/Morganite/Morganite-ExtraBold.ttf);
34 | }
35 |
36 | @font-face {
37 | font-family: "Morganite Extra Bold Italic";
38 | src: url(/Fonts/Morganite/Morganite-ExtraBoldItalic.ttf);
39 | }
40 |
41 | @font-face {
42 | font-family: "Morganite Extra Light";
43 | src: url(/Fonts/Morganite/Morganite-ExtraLight.ttf);
44 | }
45 |
46 | @font-face {
47 | font-family: "Morganite Extra Light Italic";
48 | src: url(/Fonts/Morganite/Morganite-ExtraLightItalic.ttf);
49 | }
50 |
51 | @font-face {
52 | font-family: "Morganite Light";
53 | src: url(/Fonts/Morganite/Morganite-Light.ttf);
54 | }
55 |
56 | @font-face {
57 | font-family: "Morganite Light Italic";
58 | src: url(/Fonts/Morganite/Morganite-LightItalic.ttf);
59 | }
60 |
61 | @font-face {
62 | font-family: "Morganite Extra Light Italic";
63 | src: url(/Fonts/Morganite/Morganite-ExtraLightItalic.ttf);
64 | }
65 |
66 | @font-face {
67 | font-family: "Morganite Medium";
68 | src: url(/Fonts/Morganite/Morganite-Medium.ttf);
69 | }
70 |
71 | @font-face {
72 | font-family: "Morganite Medium Italic";
73 | src: url(/Fonts/Morganite/Morganite-MediumItalic.ttf);
74 | }
75 |
76 | @font-face {
77 | font-family: "Morganite Semi Bold";
78 | src: url(/Fonts/Morganite/Morganite-SemiBold.ttf);
79 | }
80 |
81 | @font-face {
82 | font-family: "Morganite Semi Bold Italic";
83 | src: url(/Fonts/Morganite/Morganite-SemiBoldItalic.ttf);
84 | }
85 |
86 | @font-face {
87 | font-family: "Morganite Thin";
88 | src: url(/Fonts/Morganite/Morganite-Thin.ttf);
89 | }
90 |
91 | @font-face {
92 | font-family: "Morganite Thin Italic";
93 | src: url(/Fonts/Morganite/Morganite-ThinItalic.ttf);
94 | }
95 |
--------------------------------------------------------------------------------
/src/Pages/About.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: About.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import { m, LazyMotion, domAnimation } from "framer-motion";
11 | import SectionTitle from "../Components/SectionTitle";
12 | import { memoji } from "../Constants/constants";
13 | import { introduction } from "../Constants/constants";
14 | import ImageSlider from "../Components/elements/ImageSlider";
15 |
16 | const About = () => {
17 | return (
18 |
61 | );
62 | };
63 |
64 | export default About;
65 |
--------------------------------------------------------------------------------
/src/Components/nav/NavBar.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: NavBar.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 02/06/2023
8 | */
9 |
10 | import React, {useState } from "react";
11 | import { Link } from "react-router-dom";
12 | import {styles} from '../../styles.js';
13 | import { navLinks } from "../../Constants/constants";
14 | import { mikeIcon, menu, close } from "../../assets";
15 |
16 | const Navbar = () => {
17 | const [active, setActive] = useState("");
18 | const [toggle, setToggle] = useState(false);
19 |
20 | return (
21 |
27 |
28 |
{
32 | setActive("");
33 | window.scrollTo(0, 0);
34 | }}
35 | >
36 |
37 |
38 |
39 |
40 |
41 | {navLinks.map((link) => {
42 | return (
43 | setActive(link.title)}
49 | >
50 | {link.title}
51 |
52 | );
53 | })}
54 |
55 |
56 |
setToggle(!toggle)}
59 | src={toggle ? close : menu}
60 | alt={menu}
61 | />
62 |
67 |
68 | {navLinks.map((link) => {
69 | return (
70 | {
76 | setActive(link.title);
77 | setToggle(!toggle);
78 | }}
79 | >
80 | {link.title}
81 |
82 | );
83 | })}
84 |
85 |
86 |
87 |
88 |
89 | );
90 | };
91 |
92 | export default Navbar;
--------------------------------------------------------------------------------
/src/App/index.css:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: index.css
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 02/06/2023
8 | */
9 |
10 |
11 | @tailwind base;
12 | @tailwind components;
13 | @tailwind utilities;
14 |
15 | @font-face {
16 | font-family: "Feogra-Demo";
17 | src: url(/Fonts/Feogra/Feogra.ttf);
18 | }
19 |
20 | * {
21 | margin: 0;
22 | padding: 0;
23 | box-sizing: border-box;
24 | scroll-behavior: smooth;
25 |
26 | }
27 |
28 | body {
29 | background: url("https://uploads-ssl.webflow.com/62e3ee10882dc50bcae8d07a/631a5d4631d4c55a475f3e34_noise-50.png");
30 | background-color: #000;
31 | position: relative;
32 | overflow-x: hidden;
33 | -webkit-overflow-x: hidden;
34 | }
35 |
36 | .overflow-hidden-web {
37 | overflow: hidden;
38 | -webkit-overflow: hidden;
39 | }
40 |
41 | .message::after {
42 | content: " ";
43 | width: 10px;
44 | height: 10px;
45 | background: transparent;
46 | position: absolute;
47 | bottom: -10px;
48 | right: 0;
49 | border-radius: 0 0 0 100%;
50 | }
51 |
52 | #repulse-div {
53 | -webkit-appearance: none;
54 | appearance: none;
55 | -webkit-filter: drop-shadow(0 0 5rem #292D44);
56 | filter: drop-shadow(0 0 5rem #292D44);
57 | }
58 |
59 | #repulse-div > h1 {
60 | -webkit-filter: drop-shadow(0 0 5rem #292D44);
61 | filter: drop-shadow(0 0 5rem #292D44);
62 | }
63 |
64 | #journey-scroll::-webkit-scrollbar {
65 | display: none;
66 | }
67 |
68 | #journey-scroll {
69 | -ms-overflow-style: none;
70 | scrollbar-width: none;
71 | }
72 |
73 | .arrowpath,
74 | polyline {
75 | fill: none;
76 | stroke: #1e90ff;
77 | stroke-width: 2;
78 | }
79 |
80 | .arrowpath {
81 | stroke-dasharray: 11, 5;
82 | }
83 |
84 | .noselect {
85 | -webkit-touch-callout: none;
86 | -webkit-user-select: none;
87 | -khtml-user-select: none;
88 | -moz-user-select: none;
89 | -ms-user-select: none;
90 | user-select: none;
91 | }
92 |
93 | .blob {
94 | animation: morph 3.6s linear infinite;
95 | background: transparent;
96 | border-collapse: separate;
97 | background-size: cover;
98 | background-position: center;
99 | outline: 1px #1e90ff;
100 | }
101 |
102 | @keyframes morph {
103 | 0%,
104 | 100% {
105 | border-radius: 40% 60% 70% 30% / 40% 40% 60% 50%;
106 | -webkit-border-radius: 40% 60% 70% 30% / 40% 40% 60% 50%;
107 | -moz-border-radius: 40% 60% 70% 30% / 40% 40% 60% 50%;
108 | }
109 | 34% {
110 | border-radius: 70% 30% 50% 50% / 30% 30% 70% 70%;
111 | -webkit-border-radius: 70% 30% 50% 50% / 30% 30% 70% 70%;
112 | -moz-border-radius: 70% 30% 50% 50% / 30% 30% 70% 70%;
113 | }
114 | 67% {
115 | border-radius: 100% 60% 60% 100% / 100% 100% 60% 60%;
116 | -webkit-border-radius: 100% 60% 60% 100% / 100% 100% 60% 60%;
117 | -moz-border-radius: 100% 60% 60% 100% / 100% 100% 60% 60%;
118 | }
119 | }
120 |
121 | .bounce {
122 | color: #1e90ff;
123 | transition: all 0.3s ease-out;
124 | }
125 |
126 | .bounce:hover {
127 | display: inline-block;
128 | animation: rubberband 0.8s ease-out;
129 | color: #fff;
130 | }
131 |
132 | @keyframes rubberband {
133 | 0% {
134 | transform: scaleX(1);
135 | }
136 | 40% {
137 | transform: scaleX(1.12) scaleY(0.75);
138 | }
139 | 55% {
140 | transform: scaleX(0.85) scaleY(1);
141 | }
142 | 65% {
143 | transform: scaleX(1.09) scaleY(0.85);
144 | }
145 | 75% {
146 | transform: scaleX(0.9) scaleY(1);
147 | }
148 | 90% {
149 | transform: scaleX(1.05) scaleY(0.95);
150 | }
151 | 100% {
152 | transform: scaleX(1) scaleY(1);
153 | }
154 | }
155 |
156 | @media only screen and (min-width: 600px) {
157 | .drop-shadow-div {
158 | -webkit-appearance: none;
159 | appearance: none;
160 | -webkit-filter: drop-shadow(0 0 1.5rem #00f7ff);
161 | filter: drop-shadow(0 0 1.5rem #00f7ff);
162 | }
163 | }
164 |
165 | .loader {
166 | width: 100px;
167 | height: 100px;
168 | border: 5px solid #1e90ff;
169 | border-radius: 50%;
170 | display: inline-block;
171 | position: relative;
172 | animation: rotation 1s linear infinite;
173 | }
174 | .loader::after {
175 | content: '';
176 | position: absolute;
177 | left: 50%;
178 | top: 50%;
179 | transform: translate(-50%, -50%);
180 | width: 80px;
181 | height: 80px;
182 | border-radius: 50%;
183 | border: 5px solid;
184 | border-color: #1e90ff transparent;
185 | }
186 |
187 | @keyframes rotation {
188 | 0% {
189 | transform: rotate(0deg);
190 | }
191 | 100% {
192 | transform: rotate(360deg);
193 | }
194 | }
--------------------------------------------------------------------------------
/src/Components/ContactForm.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: ContactForm.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 03/06/2023
8 | */
9 |
10 | import { useRef, useState } from "react";
11 | import { Typewriter } from "react-simple-typewriter";
12 | import emailjs from "@emailjs/browser";
13 |
14 | const ContactForm = () => {
15 | const [isSent, setIsSent] = useState(false);
16 | const form = useRef();
17 |
18 | const sendEmail = (e) => {
19 | e.preventDefault();
20 |
21 | emailjs
22 | .sendForm("whoisbl33h", "template1", e.target, "JjC_Nnt4rUsjIsRtz")
23 | .then(
24 | (result) => {
25 | document.getElementById("contact_form").reset();
26 | setIsSent(true);
27 | alert("Thank you I will get back to you as soon as possible ! (:");
28 | },
29 | (error) => {
30 | console.error(error);
31 | setIsSent(false);
32 | }
33 | );
34 | };
35 |
36 | return (
37 |
47 |
48 |
52 |
53 |
54 |
55 |
56 |
138 |
139 | );
140 | };
141 |
142 | export default ContactForm;
143 |
--------------------------------------------------------------------------------
/src/Components/ProjectCards.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: ProjectCards.jsx
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 19/04/2024
8 | */
9 |
10 | import { motion } from "framer-motion";
11 | import { Tilt } from "react-tilt";
12 | import { projects } from "../Constants/constants";
13 | import { githubIcon } from "../assets";
14 |
15 | export const staggerContainer = (staggerChildren, delayChildren) => {
16 | return {
17 | hidden: {},
18 | show: {
19 | transition: {
20 | staggerChildren: staggerChildren,
21 | delayChildren: delayChildren || 0,
22 | },
23 | },
24 | };
25 | };
26 |
27 | export const textVariant = (delay) => {
28 | return {
29 | hidden: {
30 | y: -50,
31 | opacity: 0,
32 | },
33 | show: {
34 | y: 0,
35 | opacity: 1,
36 | transition: {
37 | type: "spring",
38 | duration: 1.25,
39 | delay: delay,
40 | },
41 | },
42 | };
43 | };
44 |
45 | export const fadeIn = (direction, type, delay, duration) => {
46 | return {
47 | hidden: {
48 | x: direction === "left" ? 100 : direction === "right" ? -100 : 0,
49 | y: direction === "up" ? 100 : direction === "down" ? -100 : 0,
50 | opacity: 0,
51 | },
52 | show: {
53 | x: 0,
54 | y: 0,
55 | opacity: 1,
56 | transition: {
57 | type: type,
58 | delay: delay,
59 | duration: duration,
60 | ease: "easeOut",
61 | },
62 | },
63 | };
64 | };
65 |
66 | export const zoomIn = (delay, duration) => {
67 | return {
68 | hidden: {
69 | scale: 0,
70 | opacity: 0,
71 | },
72 | show: {
73 | scale: 1,
74 | opacity: 1,
75 | transition: {
76 | type: "tween",
77 | delay: delay,
78 | duration: duration,
79 | ease: "easeOut",
80 | },
81 | },
82 | };
83 | };
84 |
85 | export const slideIn = (direction, type, delay, duration) => {
86 | return {
87 | hidden: {
88 | x: direction === "left" ? "-100%" : direction === "right" ? "100%" : 0,
89 | y: direction === "up" ? "100%" : direction === "down" ? "100%" : 0,
90 | },
91 | show: {
92 | x: 0,
93 | y: 0,
94 | transition: {
95 | type: type,
96 | delay: delay,
97 | duration: duration,
98 | ease: "easeOut",
99 | },
100 | },
101 | };
102 | };
103 |
104 | const ProjectCard = ({
105 | index,
106 | name,
107 | description,
108 | image,
109 | source_code_link,
110 | demo_link,
111 | }) => {
112 | return (
113 |
121 |
124 |
125 |
130 | {/*
131 |
window.open(source_code_link, "_blank")}
133 | className="w-8 h-8 rounded-full flex justify-center items-center cursor-pointer"
134 | >
135 |
140 |
141 |
*/}
142 |
143 |
144 |
145 |
{name}
146 |
147 | {description}
148 |
149 |
150 |
151 |
160 |
161 |
162 | );
163 | };
164 |
165 | const Works = () => {
166 | return (
167 |
168 | {projects.map((project, index) => (
169 |
170 | ))}
171 |
172 | );
173 | };
174 |
175 | export default Works;
--------------------------------------------------------------------------------
/src/Components/Particles/particlesOptions.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: particleOptions.js
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 02/06/2023
8 | */
9 |
10 | export const heroOptions = {
11 | autoPlay: true,
12 |
13 | fullScreen: {
14 | enable: false,
15 | zIndex: 0,
16 | },
17 |
18 | detectRetina: true,
19 | fpsLimit: 120,
20 |
21 | interactivity: {
22 | detectsOn: '#hero',
23 | events: {
24 | onDiv: [
25 | {
26 | selectors: '#repulse-div',
27 | enable: true,
28 | mode: 'bounce',
29 | type: 'circle',
30 | },
31 | {
32 | selectors: '#repulse-div',
33 | enable: true,
34 | mode: 'repulse',
35 | type: 'circle',
36 | },
37 | {
38 | selectors: '#repulse-span',
39 | enable: true,
40 | mode: 'repulse',
41 | type: 'circle',
42 | },
43 | {
44 | selectors: '#repulse-span',
45 | enable: true,
46 | mode: 'bounce',
47 | type: 'circle',
48 | },
49 | {
50 | selectors: '#togglebutton',
51 | enable: true,
52 | mode: 'repulse',
53 | type: 'circle',
54 | },
55 | {
56 | selectors: '#togglebutton',
57 | enable: true,
58 | mode: 'bounce',
59 | type: 'circle',
60 | },
61 | {
62 | selectors: '#scroller',
63 | enable: true,
64 | mode: 'repulse',
65 | type: 'circle',
66 | },
67 | {
68 | selectors: '#scroller',
69 | enable: true,
70 | mode: 'bounce',
71 | type: 'circle',
72 | },
73 | ],
74 |
75 | onHover: {
76 | enable: true,
77 | mode: 'bubble',
78 | parallax: {
79 | enable: true,
80 | force: 350,
81 | smooth: 20,
82 | },
83 | },
84 | resize: {
85 | delay: 0.5,
86 | enable: true,
87 | },
88 | },
89 |
90 | modes: {
91 | bounce: {
92 | distance: 100,
93 | },
94 | bubble: {
95 | distance: 100,
96 | duration: 0.4,
97 | size: 40,
98 | color: {
99 | value: '#1e90ff',
100 | },
101 | opacity: 8,
102 | mix: false,
103 | },
104 |
105 | repulse: {
106 | distance: 200,
107 | factor: 200,
108 | speed: 1,
109 | maxSpeed: 50,
110 | },
111 | },
112 | },
113 |
114 | particles: {
115 | collisions: {
116 | enable: true,
117 | mode: 'bounce',
118 | },
119 | color: {
120 | value: '#1e90ff',
121 | },
122 | move: {
123 | angle: {
124 | offset: 0,
125 | value: 90,
126 | },
127 | center: {
128 | x: 50,
129 | y: 50,
130 | mode: 'percent',
131 | radius: 0,
132 | },
133 | direction: ['top-left', 'bottom-left', 'bottom-right', 'top-right'],
134 | drift: 0,
135 | enable: true,
136 | random: false,
137 | size: false,
138 | speed: 0.8,
139 | outMode: 'bounce',
140 | },
141 | number: {
142 | limit: 0,
143 | value: 30,
144 | },
145 |
146 | opacity: {
147 | random: {
148 | enable: true,
149 | minimumValue: 0.4,
150 | maxValue: 0.6,
151 | },
152 | value: 0.6,
153 | animation: {
154 | count: 0,
155 | enable: true,
156 | speed: 0.2,
157 | decay: 0,
158 | sync: true,
159 | destroy: 'none',
160 | startValue: 'random',
161 | },
162 | },
163 |
164 | shape: {
165 | type: 'character',
166 | character: [
167 | {
168 | fill: true,
169 | font: 'Font Awesome 6 Brands',
170 | style: '',
171 | value: ['\uf3c6'],
172 | weight: '400',
173 | },
174 | {
175 | fill: true,
176 | font: 'Font Awesome 6 Brands',
177 | style: '',
178 | value: ['\uf17c'],
179 | weight: '400',
180 | },
181 | {
182 | fill: true,
183 | font: 'Font Awesome 6 Brands',
184 | style: '',
185 | value: ['\uf791'],
186 | weight: '400',
187 | },
188 | ],
189 | },
190 |
191 | size: {
192 | random: {
193 | enable: true,
194 | minimumValue: 25,
195 | maxValue: 35,
196 | },
197 | animation: {
198 | count: 0,
199 | enable: true,
200 | speed: 0.2,
201 | decay: 0,
202 | sync: true,
203 | destroy: 'none',
204 | startValue: 'random',
205 | },
206 | },
207 |
208 | lineLinked: {
209 | blink: false,
210 | color: {
211 | value: '#ffffff',
212 | },
213 | consent: true,
214 | distance: 100,
215 | enable: true,
216 | frequency: 10,
217 | opacity: 0.4,
218 | width: 1,
219 | },
220 | },
221 | pauseOnBlur: true,
222 | pauseOnOutsideViewport: true,
223 | smooth: true,
224 | };
225 |
--------------------------------------------------------------------------------
/src/Constants/constants.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C), 2023-2024, Mikael Laine (mikael)
3 | Author: Mikael Laine
4 | FileName: constants.js
5 | Version: I
6 | Creation: 02/06/2023
7 | Last modification: 18/12/2023
8 | */
9 |
10 | import { library } from '@fortawesome/fontawesome-svg-core';
11 | import {
12 | faX,
13 | faBars,
14 | faWindowRestore,
15 | faBagShopping,
16 | faDiceD6,
17 | faEnvelope,
18 | } from '@fortawesome/free-solid-svg-icons';
19 | import {
20 | faReact,
21 | faGithub,
22 | faSkype,
23 | } from '@fortawesome/free-brands-svg-icons';
24 |
25 | import {
26 | htmlIcon,
27 | cssIcon,
28 | jsIcon,
29 | reactIcon,
30 | awsIcon,
31 | javaIcon,
32 | gitIcon,
33 | githubIcon,
34 | psqlIcon,
35 | eslintIcon,
36 | pyIcon,
37 | viteIcon,
38 | nodeIcon,
39 | raspIcon,
40 | neoIcon,
41 | figmaIcon,
42 | memoryGame,
43 | foremen,
44 | calculator,
45 | skyspa,
46 | sybaris,
47 | avatar,
48 | } from '../assets';
49 |
50 | library.add(faX, faBars, faWindowRestore, faBagShopping, faDiceD6);
51 |
52 | const media = {
53 | htmlIcon,
54 | cssIcon,
55 | jsIcon,
56 | reactIcon,
57 | awsIcon,
58 | javaIcon,
59 | gitIcon,
60 | githubIcon,
61 | psqlIcon,
62 | eslintIcon,
63 | pyIcon,
64 | viteIcon,
65 | nodeIcon,
66 | raspIcon,
67 | neoIcon,
68 | figmaIcon,
69 | avatar,
70 | };
71 |
72 | const icons = {
73 | faBars,
74 | faX,
75 | faWindowRestore,
76 | faBagShopping,
77 | faDiceD6,
78 | faReact,
79 | faGithub,
80 | faSkype,
81 | faEnvelope,
82 | };
83 |
84 | const introduction = {
85 | text: [
86 | "I am Mikael, a seasoned Full-stack Developer.",
87 |
88 | "Seeking a position that utilizes abilities and skills in web development.",
89 | "Fast-paced, creative web developer with extensive knowledge in various front-end and back-end languages, responsive frameworks, databases, and best code practices.",
90 | "The aim is to become an exceptional Full- stack developer and make valuable contributions to the technology industry.",
91 | "Extremely flexible with communication and working hours.",
92 | "You can download my resume here."
93 | ],
94 | };
95 |
96 | export const navLinks = [
97 | {
98 | id: 'about',
99 | title: 'About',
100 | },
101 | {
102 | id: 'projects',
103 | title: 'Projects',
104 | },
105 | {
106 | id: 'skills',
107 | title: 'Skills',
108 | },
109 | {
110 | id: 'contact',
111 | title: 'Contact',
112 | },
113 | ];
114 |
115 | const projects = [
116 | {
117 | name: "Arasartara's Gallery",
118 | description: 'A memory game with an art theme implemented with React. Test your memory skills and enjoy beautiful artwork as you match pairs of cards in this engaging game.',
119 | image: memoryGame,
120 | source_code_link: 'https://github.com/bl33h/artMemoryGame',
121 | demo_link: 'https://arasarmemory.netlify.app/',
122 | },
123 | {
124 | name: 'Connect 4',
125 | description: 'This project implements Connect Four in Python and Pygame, featuring a GUI and gameplay modes for player vs. AI and AI vs. AI. The AI uses the MiniMax algorithm, with optional alpha-beta pruning for improved performance.',
126 | image: "https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExbjRkaWp6MDJ1cXNrZmMzaTZ2aXVhcWtndWJpNHg0djRpYWdtYjF3ZSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/p49LPwL9yAoZInx28N/giphy.gif",
127 | source_code_link: 'https://github.com/bl33h/connectFour',
128 | demo_link: 'https://youtu.be/CBceC2BXJyE',
129 | },
130 | {
131 | name: 'Sybaris Pull Suites',
132 | description: '--- The Best Romantic Getaway in the United States. A romantic paradise to ignite feelings, rekindle the romance and enjoy quality time together. --- Stack: WordPress, Elementor',
133 | image: sybaris,
134 | source_code_link: 'https://github.com/bl33h/pawsitive',
135 | demo_link: 'https://www.sybaris.com/',
136 | },
137 | {
138 | name: 'Client-Server Chat',
139 | description: 'This is a chat application that facilitates communication between multiple clients through a centralized server. The application is designed using socket programming and handles multiple client connections concurrently using threads.',
140 | image: "https://i.pinimg.com/originals/0e/4a/c3/0e4ac37acbff81cd087aa19692a07a9d.gif",
141 | source_code_link: 'https://github.com/bl33h/clientServerChat',
142 | demo_link: 'https://youtu.be/Mk1BNqPz1n4',
143 | },
144 | {
145 | name: 'Visit Our Lands',
146 | description: 'It is a recommendation system built with React and Supabase. This system focuses on providing tourist recommendations for various locations in Panama.',
147 | image: "https://res.cloudinary.com/worldpackers/image/upload/c_fill,f_auto,q_auto,w_1024/v1/guides/article_cover/uvd82gspopw8orvryulc",
148 | source_code_link: 'https://github.com/bl33h/visitOurLands',
149 | demo_link: 'https://visitourlands.netlify.app/',
150 | },
151 | {
152 | name: 'Foremen Fiefdom',
153 | description: '--- At Foremen Fiefdom, they provide smartest of the investment chances in the real estate market and offer products promising highest returns. --- Stack: Nuxt.js, Bootstrap, Laravel',
154 | image: foremen,
155 | source_code_link: 'https://github.com/bl33h/exploringTheSpace',
156 | demo_link: 'https://www.foremenfiefdom.com/',
157 | },
158 | {
159 | name: 'Basic Calculator',
160 | description: '--- A completely functional basic calculator website created with React. It allows you to perform mathematical calculations effortlessly. --- Stack: React.js',
161 | image: calculator,
162 | source_code_link: 'https://github.com/bl33h/disneyPlusReplica',
163 | demo_link: 'https://kimoto-calculator.netlify.app/',
164 | },
165 | {
166 | name: '7 Sky Spa',
167 | description: '--- You can expect the most modern treatment devices, internationally recognized French cosmetic products and a dynamic and competent team. --- Stack: HTML, CSS, JavaScript, PHP',
168 | image: skyspa,
169 | source_code_link: 'https://github.com/bl33h/deepDiveOdysseyRaycasting',
170 | demo_link: 'https://7skyspa.co.uk/',
171 | }
172 | ];
173 |
174 | const memoji = {
175 | image: [avatar],
176 | };
177 |
178 | const skills = [
179 | {
180 | id: 'html',
181 | title: 'HTML',
182 | icon: htmlIcon,
183 | description:
184 | 'I have a strong command of HTML for organizing web pages and generating meaningful content that can be accessed by all users.',
185 | },
186 | {
187 | id: 'css',
188 | title: 'CSS',
189 | icon: cssIcon,
190 | description:
191 | 'I possess expertise in utilizing CSS to design web pages and craft visually captivating layouts that enhance the overall user experience.',
192 | },
193 | {
194 | id: 'javascript',
195 | title: 'JavaScript',
196 | icon: jsIcon,
197 | description:
198 | 'I have substantial experience in employing JavaScript to introduce interactivity and functionality into web pages, resulting in dynamic user interfaces.',
199 | },
200 | {
201 | id: 'react',
202 | title: 'React',
203 | icon: reactIcon,
204 | description:
205 | 'I am well-versed in React, proficient in creating reusable components and managing application state using hooks and context.',
206 | },
207 | {
208 | id: 'java',
209 | title: 'Java',
210 | icon: javaIcon,
211 | description:
212 | 'I have extensive experience utilizing Java for object-oriented programming (OOP) and implementing data structures.',
213 | },
214 | {
215 | id: 'aws',
216 | title: 'Amazon Web Services',
217 | icon: awsIcon,
218 | description:
219 | 'I am certified in AWS and proficient in working with EC2 and RDS instances, leveraging the power of cloud computing for scalable and reliable infrastructure.',
220 | },
221 | {
222 | id: 'figma',
223 | title: 'Figma',
224 | icon: figmaIcon,
225 | description:
226 | 'In my Figma skills, I unleash creativity, designing captivating user interfaces and collaborating seamlessly with designers and developers.',
227 | },
228 | {
229 | id: 'git',
230 | title: 'Git',
231 | icon: gitIcon,
232 | description:
233 | 'I am proficient in Git, managing code changes, collaborating with others, and resolving conflicts effectively.',
234 | },
235 | {
236 | id: 'github',
237 | title: 'GitHub',
238 | icon: githubIcon,
239 | description:
240 | 'I am skilled in using GitHub for seamless project collaboration, code sharing, and issue tracking. Through GitHub, I efficiently create and manage repositories and effectively present my work to potential employers.',
241 | },
242 | {
243 | id: 'psql',
244 | title: 'Postgresql',
245 | icon: psqlIcon,
246 | description:
247 | 'I have a strong command of PostgreSQL, encompassing a wide range of skills such as database normalization, triggers, front-end connectivity, and data analysis using software like Power BI.',
248 | },
249 | {
250 | id: 'vite',
251 | title: 'Vite',
252 | icon: viteIcon,
253 | description:
254 | 'I have gained considerable experience working with Vite for approximately six months, leveraging its capabilities to build React websites and seamlessly deploy them on platforms like Netlify.',
255 | },
256 | {
257 | id: 'py',
258 | title: 'Python',
259 | icon: pyIcon,
260 | description:
261 | 'With 3 years of Python experience, I am adept at coding functions and creating graphic interfaces using Tkinter.',
262 | },
263 | {
264 | id: 'node',
265 | title: 'Node',
266 | icon: nodeIcon,
267 | description:
268 | 'When it comes to building web applications, I prefer using Node as my runtime environment over Yarn. I have expertise in leveraging Node.js to develop powerful and scalable web applications.',
269 | },
270 | {
271 | id: 'neo',
272 | title: 'Neo4j',
273 | icon: neoIcon,
274 | description:
275 | 'I am knowledgeable in Neo4j, the graph database management system. I have expertise in utilizing GraphOS to build robust recommendation systems, leveraging the strength of graph-based data modeling.',
276 | },
277 | {
278 | id: 'raspi',
279 | title: 'Raspberry Pi',
280 | icon: raspIcon,
281 | description:
282 | 'I have hands-on experience with Raspberry Pi, where I utilized a virtual Linux machine to execute programs written in assembly language. This allowed me to explore low-level computing and develop efficient code for the Raspberry Pi platform.',
283 | },
284 | {
285 | id: 'eslint',
286 | title: 'Eslint',
287 | icon: eslintIcon,
288 | description:
289 | 'I utilize ESLint to identify and resolve code issues, as well as standardize the structure of my projects. With ESLint, I ensure code quality and consistency throughout my development process.',
290 | },
291 | ];
292 |
293 | const markerSvg = `
294 |
295 |
296 | `;
297 |
298 | export {
299 | media,
300 | introduction,
301 | projects,
302 | memoji,
303 | skills,
304 | markerSvg,
305 | icons,
306 | };
307 |
--------------------------------------------------------------------------------