Compare commits

...

12 Commits

Author SHA1 Message Date
ploc 4759a88cd9 Update email 2026-02-07 23:01:32 +01:00
ploc 82990df5d7 update 2025-08-15 12:51:26 +02:00
ploc a975cc12e2 Added latest project 2025-04-20 09:43:15 +02:00
Ploc300 1b1d6553a1 Remove Google Tag Manager integration from index.html 2025-02-24 14:29:09 +01:00
Ploc300 5b994aeb33 Add Google Tag Manager integration to index.html 2025-02-24 13:31:06 +01:00
Ploc300 a034ef8d3b Fix typos and improve descriptions in Contact and Projects sections 2025-02-20 17:52:13 +01:00
Ploc300 710c283136 Hopeffuly fixed all reponsive problems 2025-02-18 14:50:17 +01:00
Ploc300 c192a6c12f Fix Contanct not responsive on small screen 2025-02-18 14:38:58 +01:00
Ploc300 48a4122eb2 Enhance RevealOnScroll to show content without animation on small screens 2025-02-18 14:26:19 +01:00
Ploc300 6059b35237 Merge branch 'main' of ssh://gitlab.plocserv.fr:2222/ploc300/portfolio_v2 2025-02-18 14:19:47 +01:00
ploc300 61ff25dda7 Fixed Dockerfile missing dep "Vite" 2025-02-13 15:32:31 +01:00
ploc300 06c798ba62 Edit Contact.jsx 2025-02-13 14:14:22 +00:00
8 changed files with 133 additions and 137 deletions
+1
View File
@@ -11,6 +11,7 @@ node_modules
dist dist
dist-ssr dist-ssr
*.local *.local
package-lock.json
# Editor directories and files # Editor directories and files
.vscode/* .vscode/*
+5 -4
View File
@@ -2,12 +2,13 @@ FROM node:23.7.0-alpine3.21 as builder
WORKDIR /app WORKDIR /app
COPY package*.json . COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force RUN npm ci && npm cache clean --force
COPY . . COPY . ./
RUN npm run build RUN npm install -g vite
RUN npx vite build
FROM nginx:alpine FROM nginx:alpine
+2 -55
View File
@@ -311,7 +311,6 @@
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"aix" "aix"
@@ -327,7 +326,6 @@
"cpu": [ "cpu": [
"arm" "arm"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
@@ -343,7 +341,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
@@ -359,7 +356,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
@@ -375,7 +371,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
@@ -391,7 +386,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
@@ -407,7 +401,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"freebsd" "freebsd"
@@ -423,7 +416,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"freebsd" "freebsd"
@@ -439,7 +431,6 @@
"cpu": [ "cpu": [
"arm" "arm"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -455,7 +446,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -471,7 +461,6 @@
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -487,7 +476,6 @@
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -503,7 +491,6 @@
"cpu": [ "cpu": [
"mips64el" "mips64el"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -519,7 +506,6 @@
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -535,7 +521,6 @@
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -551,7 +536,6 @@
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -567,7 +551,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -583,7 +566,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"netbsd" "netbsd"
@@ -599,7 +581,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"netbsd" "netbsd"
@@ -615,7 +596,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"openbsd" "openbsd"
@@ -631,7 +611,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"openbsd" "openbsd"
@@ -647,7 +626,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"sunos" "sunos"
@@ -663,7 +641,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@@ -679,7 +656,6 @@
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@@ -695,7 +671,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@@ -963,7 +938,6 @@
"cpu": [ "cpu": [
"arm" "arm"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
@@ -976,7 +950,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
@@ -989,7 +962,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
@@ -1002,7 +974,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
@@ -1015,7 +986,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"freebsd" "freebsd"
@@ -1028,7 +998,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"freebsd" "freebsd"
@@ -1041,7 +1010,6 @@
"cpu": [ "cpu": [
"arm" "arm"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -1054,7 +1022,6 @@
"cpu": [ "cpu": [
"arm" "arm"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -1067,7 +1034,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -1080,7 +1046,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -1093,7 +1058,6 @@
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -1106,7 +1070,6 @@
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -1119,7 +1082,6 @@
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -1132,7 +1094,6 @@
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -1145,7 +1106,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -1158,7 +1118,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -1171,7 +1130,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@@ -1184,7 +1142,6 @@
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@@ -1197,7 +1154,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@@ -1457,8 +1413,7 @@
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
"dev": true
}, },
"node_modules/@types/gensync": { "node_modules/@types/gensync": {
"version": "1.0.4", "version": "1.0.4",
@@ -2240,7 +2195,6 @@
"version": "0.24.2", "version": "0.24.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
"integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==",
"dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
"esbuild": "bin/esbuild" "esbuild": "bin/esbuild"
@@ -2580,7 +2534,6 @@
"version": "2.3.3", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"optional": true, "optional": true,
"os": [ "os": [
@@ -3652,7 +3605,6 @@
"version": "3.3.8", "version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@@ -3881,8 +3833,7 @@
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
"dev": true
}, },
"node_modules/possible-typed-array-names": { "node_modules/possible-typed-array-names": {
"version": "1.1.0", "version": "1.1.0",
@@ -3897,7 +3848,6 @@
"version": "8.5.2", "version": "8.5.2",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz",
"integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -4064,7 +4014,6 @@
"version": "4.34.6", "version": "4.34.6",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.6.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.6.tgz",
"integrity": "sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ==", "integrity": "sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ==",
"dev": true,
"dependencies": { "dependencies": {
"@types/estree": "1.0.6" "@types/estree": "1.0.6"
}, },
@@ -4307,7 +4256,6 @@
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -4601,7 +4549,6 @@
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz",
"integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==",
"dev": true,
"dependencies": { "dependencies": {
"esbuild": "^0.24.2", "esbuild": "^0.24.2",
"postcss": "^8.5.1", "postcss": "^8.5.1",
+1 -1
View File
@@ -17,7 +17,7 @@ function App() {
return ( return (
<> <>
{!isLoaded && <LoadingScreen onComplete={() => setIsLoaded(true)} />} {!isLoaded && <LoadingScreen onComplete={() => setIsLoaded(true)} />}
<div className={`min-h-screen min-w-sc transition-opacity duration-700 ${isLoaded ? "opacity-100" : "opacity-0"} bg-black text-gray-100`}> <div className={`min-h-screen max-w-sc transition-opacity duration-700 ${isLoaded ? "opacity-100" : "opacity-0"} bg-black text-gray-100`}>
<Navbar menuOpen={menuOpen} setMenuOpen={setMenuOpen} /> <Navbar menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
<MobileMenu menuOpen={menuOpen} setMenuOpen={setMenuOpen} /> <MobileMenu menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
<Home /> <Home />
+9 -1
View File
@@ -5,9 +5,17 @@ function RevealOnScroll({ children }) {
useEffect(() => { useEffect(() => {
const isSmallScreen = window.innerWidth < 1080; const isSmallScreen = window.innerWidth < 1080;
if (isSmallScreen) {
// Directly show content without animation on small screens.
if (ref.current) {
ref.current.classList.add("visible");
}
return;
}
const observerOptions = { const observerOptions = {
threshold: 0.2, threshold: 0.2,
rootMargin: isSmallScreen ? "0px" : "0px 0px -50px 0px" rootMargin: "0px 0px -50px 0px",
}; };
const observer = new IntersectionObserver(([entry]) => { const observer = new IntersectionObserver(([entry]) => {
+46 -44
View File
@@ -7,7 +7,7 @@ import { FaSchool } from "react-icons/fa6";
function About() { function About() {
const cybersecuritySkills = { const cybersecuritySkills = {
"skils": [ "skills": [
"Penetration testing", "Penetration testing",
"Security auditing", "Security auditing",
"Network security", "Network security",
@@ -22,93 +22,94 @@ function About() {
} }
const programmationSkills = { const programmationSkills = {
"skils": [ "skills": [
"Python", "Python",
"HTML/PHP/CSS", "HTML/PHP/CSS",
"Bash", "Bash",
"Powershell", "Powershell",
"Lerning C/C++/Node.js (Vite/React + Tailwind CSS)", "Learning C/C++/Node.js (Vite/React + Tailwind CSS)"
], ],
"projects": [ "projects": [
"Python Softphone (Client/Server)", "Python Softphone (Client/Server)",
"Python Portfolio", "Python Portfolio",
"Vite / React / Tailwind Portfolio", "Vite / React / Tailwind Portfolio",
"Task automation", "Task automation",
"Cybersecurity challenge (Python / C)", "Cybersecurity challenge (Python / C)"
] ]
} }
const networkSkills = { const networkSkills = {
"skils": [ "skills": [
"Design", "Design",
"Implementation", "Implementation",
"Troubleshouting", "Troubleshooting",
"VPN IPSec / SSL", "VPN IPSec / SSL",
"Firewall (Stormshield CSNA Certified)", "Firewall (Stormshield CSNA Certified)",
"Cisco / Aruba / Stormshield", "Cisco / Aruba / Stormshield"
], ],
"projects": [ "projects": [
"Creation of a school network from scratch", "Creation of a school network from scratch",
"Creation of a secured network (ACL and Firewalls)", "Creation of a secured network (ACL and Firewalls)"
] ]
} }
const systemSkills = { const systemSkills = {
"skils": [ "skills": [
"Linux", "Linux",
"Arch Linux /w Hyprland", "Arch Linux /w Hyprland",
"Debian /w/o gui", "Debian /w/o GUI",
"Windows", "Windows",
"Windows Active Directory", "Windows Active Directory",
"LDAP", "LDAP",
"Postfix", "Postfix",
"Poste.io", "Poste.io",
"Virtualisation", "Virtualization",
"Docker", "Docker",
"VirutalBox", "VirtualBox",
"VMWare Worstation", "VMware Workstation",
"VMWare vSphere / ESXI", "VMware vSphere / ESXi",
"Orchestration", "Orchestration",
"Portainer", "Portainer",
"CI/CD", "CI/CD",
"Gitlab", "GitLab",
"Jenkins", "Jenkins",
"Gerrit", "Gerrit"
], ],
"projects": [ "projects": [
"Lab Work: Active Directory, LDAP, VMware, VCenter, Docker", "Lab Work: Active Directory, LDAP, VMware, vCenter, Docker",
"HomeLab with Dockerized services on Debian", "HomeLab with Dockerized services on Debian",
"Personal CI/CD using Gitlab and Jenkins (and Portainer for auto deployment)", "Personal CI/CD using GitLab and Jenkins (and Portainer for auto deployment)",
"Reverse proxy using Nginx", "Reverse proxy using Nginx",
"Personal mail server using Poste.io", "Personal mail server using Poste.io",
"Personal Desktop on Windows 11 / Kali Linux (Dual Boot)", "Personal Desktop on Windows 11 / Kali Linux (Dual Boot)",
"Personal Laptop on Arch Linux /w Hyprland", "Personal Laptop on Arch Linux /w Hyprland"
] ]
} }
const projectManagementSkills = { const projectManagementSkills = {
"skils": [ "skills": [
"Reporting", "Reporting",
"Gantt Chart", "Gantt Chart",
"Team Management", "Team Management"
], ],
"projects": [ "projects": [
"Creation of a school network from scratch", "Creation of a school network from scratch",
"Team Management in different school projects", "Team management in different school projects"
] ]
} }
const languageSkills = { const languageSkills = {
"skils": [ "skills": [
"French: Native language", "French: Native language",
"English: B1+", "English: B1+"
], ],
"projects": [ "projects": [
"Educational trip to London, hosted in local homes with English-speaking families", "Educational trip to London, hosted in local homes with English-speaking families",
"Competitive Video Games (Communication in English)", "Competitive video games (communication in English)"
] ]
} }
const education = [ const education = [
{ {
"name": "General Baccalaureate with honors", "name": "General Baccalaureate with honors",
@@ -132,11 +133,11 @@ function About() {
"graduation_year": "2025", "graduation_year": "2025",
"graduated": false "graduated": false
}, },
]; ]
const certifications = [ const certifications = [
{ {
"name": "Stormhield CSNA", "name": "Stormshield CSNA",
"city": "Lannion (22)", "city": "Lannion (22)",
"date_obtained": "December 2024", "date_obtained": "December 2024",
"expiration": "December 2027" "expiration": "December 2027"
@@ -151,8 +152,8 @@ function About() {
"place": "Lannion (22)", "place": "Lannion (22)",
"tasks": [ "tasks": [
"Correction of Python code to meet PEP8 standards", "Correction of Python code to meet PEP8 standards",
"Writting unitary test", "Writing unit tests",
"Technical writing", "Technical writing"
] ]
}, },
{ {
@@ -163,7 +164,7 @@ function About() {
"tasks": [ "tasks": [
"Customer service", "Customer service",
"Stock management", "Stock management",
"Store maintenance", "Store maintenance"
] ]
}, },
{ {
@@ -172,11 +173,12 @@ function About() {
"period": "2022", "period": "2022",
"place": "Hennebont (56)", "place": "Hennebont (56)",
"tasks": [ "tasks": [
"Responsible for cleaning various residential buildings, medical offices, and banks", "Responsible for cleaning various residential buildings, medical offices, and banks"
] ]
} }
] ]
return ( return (
<section id="about" className="min-h-screen flex items-center justify-center py-20"> <section id="about" className="min-h-screen flex items-center justify-center py-20">
<RevealOnScroll> <RevealOnScroll>
@@ -187,7 +189,7 @@ function About() {
<div className="rounded-xl p-8 border-white/30 border hover:border-white/50 hover:shadow-[0_2px_8px_rgba(59,130,246,0.2)] hover:-translate-y-1 transition-all"> <div className="rounded-xl p-8 border-white/30 border hover:border-white/50 hover:shadow-[0_2px_8px_rgba(59,130,246,0.2)] hover:-translate-y-1 transition-all">
<p className="text-gray-300 mb-6"> <p className="text-gray-300 mb-6">
Due to my passion for computer science and everything related, I managed to gather skills in multiple domains. Due to my passion for computer science and everything related, I have managed to acquire skills in multiple domains.
</p> </p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="rounded-xl p-6 hover:shadow-[6px_6px_8px_rgba(59,130,246,0.1)] hover:-translate-y-1 transition-all border border-white/10 hover:border-blue-500/30"> <div className="rounded-xl p-6 hover:shadow-[6px_6px_8px_rgba(59,130,246,0.1)] hover:-translate-y-1 transition-all border border-white/10 hover:border-blue-500/30">
@@ -197,8 +199,8 @@ function About() {
<div className="flex flex-col gap-2 "> <div className="flex flex-col gap-2 ">
<span className="text-lg">Skills</span> <span className="text-lg">Skills</span>
<ul className="flex flex-wrap flex-row space-x-2 space-y-2 list-inside mx-5"> <ul className="flex flex-wrap flex-row space-x-2 space-y-2 list-inside mx-5">
{cybersecuritySkills.skils.map((value, key) => ( {cybersecuritySkills.skills.map((value, key) => (
<li key={key} className="text-sm whitespace-nowrap bg-blue-500/10 text-blue-500 py-1 px-3 rounded-full hover:bg-blue-500/20 hover:shadow-[0_2px_8px_rgba(59,130,246,0.2)] transition">{value}</li> <li key={key} className="text-sm whitespace-normal bg-blue-500/10 text-blue-500 py-1 px-3 rounded-full hover:bg-blue-500/20 hover:shadow-[0_2px_8px_rgba(59,130,246,0.2)] transition">{value}</li>
))} ))}
</ul> </ul>
<span className="text-lg">Projects</span> <span className="text-lg">Projects</span>
@@ -216,8 +218,8 @@ function About() {
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<span className="text-lg">Skills</span> <span className="text-lg">Skills</span>
<ul className="flex flex-wrap flex-row space-x-2 space-y-2 list-inside mx-5"> <ul className="flex flex-wrap flex-row space-x-2 space-y-2 list-inside mx-5">
{programmationSkills.skils.map((value, key) => ( {programmationSkills.skills.map((value, key) => (
<li key={key} className="text-sm whitespace-nowrap bg-blue-500/10 text-blue-500 py-1 px-3 rounded-full hover:bg-blue-500/20 hover:shadow-[0_2px_8px_rgba(59,130,246,0.2)] transition">{value}</li> <li key={key} className="text-sm whitespace-normal bg-blue-500/10 text-blue-500 py-1 px-3 rounded-full hover:bg-blue-500/20 hover:shadow-[0_2px_8px_rgba(59,130,246,0.2)] transition">{value}</li>
))} ))}
</ul> </ul>
<span className="text-lg">Projects</span> <span className="text-lg">Projects</span>
@@ -235,8 +237,8 @@ function About() {
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<span className="text-lg">Skills</span> <span className="text-lg">Skills</span>
<ul className="flex flex-wrap flex-row space-x-2 space-y-2 list-inside mx-5"> <ul className="flex flex-wrap flex-row space-x-2 space-y-2 list-inside mx-5">
{networkSkills.skils.map((value, key) => ( {networkSkills.skills.map((value, key) => (
<li key={key} className="text-sm my-1 bg-blue-500/10 text-blue-500 py-1 px-3 rounded-full hover:bg-blue-500/20 hover:shadow-[0_2px_8px_rgba(59, 130, 246, 0.2)] transition">{value}</li> <li key={key} className="text-sm whitespace-normal my-1 bg-blue-500/10 text-blue-500 py-1 px-3 rounded-full hover:bg-blue-500/20 hover:shadow-[0_2px_8px_rgba(59, 130, 246, 0.2)] transition">{value}</li>
))} ))}
</ul> </ul>
<span className="text-lg">Projects</span> <span className="text-lg">Projects</span>
@@ -254,8 +256,8 @@ function About() {
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<span className="text-lg">Skills</span> <span className="text-lg">Skills</span>
<ul className="flex flex-wrap flex-row space-x-2 space-y-2 list-inside mx-5"> <ul className="flex flex-wrap flex-row space-x-2 space-y-2 list-inside mx-5">
{systemSkills.skils.map((value, key) => ( {systemSkills.skills.map((value, key) => (
<li key={key} className="text-sm my-1 bg-blue-500/10 text-blue-500 py-1 px-3 rounded-full hover:bg-blue-500/20 hover:shadow-[0_2px_8px_rgba(59, 130, 246, 0.2)] transition">{value}</li> <li key={key} className="text-sm whitespace-normal my-1 bg-blue-500/10 text-blue-500 py-1 px-3 rounded-full hover:bg-blue-500/20 hover:shadow-[0_2px_8px_rgba(59, 130, 246, 0.2)] transition">{value}</li>
))} ))}
</ul> </ul>
<span className="text-lg">Projects</span> <span className="text-lg">Projects</span>
@@ -273,8 +275,8 @@ function About() {
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<span className="text-lg">Skills</span> <span className="text-lg">Skills</span>
<ul className="flex flex-wrap flex-row space-x-2 space-y-2 list-inside mx-5"> <ul className="flex flex-wrap flex-row space-x-2 space-y-2 list-inside mx-5">
{projectManagementSkills.skils.map((value, key) => ( {projectManagementSkills.skills.map((value, key) => (
<li key={key} className="text-sm my-1 bg-blue-500/10 text-blue-500 py-1 px-3 rounded-full hover:bg-blue-500/20 hover:shadow-[0_2px_8px_rgba(59, 130, 246, 0.2)] transition">{value}</li> <li key={key} className="text-sm whitespace-normal my-1 bg-blue-500/10 text-blue-500 py-1 px-3 rounded-full hover:bg-blue-500/20 hover:shadow-[0_2px_8px_rgba(59, 130, 246, 0.2)] transition">{value}</li>
))} ))}
</ul> </ul>
<span className="text-lg">Projects</span> <span className="text-lg">Projects</span>
@@ -292,8 +294,8 @@ function About() {
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<span className="text-lg">Skills</span> <span className="text-lg">Skills</span>
<ul className="flex flex-wrap flex-row space-x-2 space-y-2 list-inside mx-5"> <ul className="flex flex-wrap flex-row space-x-2 space-y-2 list-inside mx-5">
{languageSkills.skils.map((value, key) => ( {languageSkills.skills.map((value, key) => (
<li key={key} className="text-sm my-1 bg-blue-500/10 text-blue-500 py-1 px-3 rounded-full hover:bg-blue-500/20 hover:shadow-[0_2px_8px_rgba(59, 130, 246, 0.2)] transition">{value}</li> <li key={key} className="text-sm =whitespace-normal my-1 bg-blue-500/10 text-blue-500 py-1 px-3 rounded-full hover:bg-blue-500/20 hover:shadow-[0_2px_8px_rgba(59, 130, 246, 0.2)] transition">{value}</li>
))} ))}
</ul> </ul>
<span className="text-lg">Projects</span> <span className="text-lg">Projects</span>
+3 -4
View File
@@ -1,7 +1,6 @@
import RevealOnScroll from "../RevealOnScroll"; import RevealOnScroll from "../RevealOnScroll";
import { FaLinkedin, FaGithub, FaGitlab } from "react-icons/fa"; import { FaLinkedin, FaGithub, FaGitlab } from "react-icons/fa";
import { CiMail } from "react-icons/ci";
import { PiMicrosoftOutlookLogoFill } from "react-icons/pi"; import { PiMicrosoftOutlookLogoFill } from "react-icons/pi";
@@ -19,13 +18,13 @@ function Contact() {
}, },
{ {
"icon": <FaGitlab className="inline text-3xl" />, "icon": <FaGitlab className="inline text-3xl" />,
"name": "Github", "name": "GitLab",
"link": "https://gitlab.plocserv.fr/ploc300", "link": "https://gitlab.plocserv.fr/ploc300",
}, },
{ {
"icon": <PiMicrosoftOutlookLogoFill className="inline text-3xl stroke-1" />, "icon": <PiMicrosoftOutlookLogoFill className="inline text-3xl stroke-1" />,
"name": "Mail", "name": "Mail",
"link": "mailto:alexis.pen@hotmail.com", "link": "mailto:alexis@pencrane.fr",
}, },
] ]
@@ -37,7 +36,7 @@ function Contact() {
<h2 className="text-3xl font-bold mb-8 bg-gradient-to-r from-blue-500 to-cyan-400 bg-clip-text text-transparent text-center"> <h2 className="text-3xl font-bold mb-8 bg-gradient-to-r from-blue-500 to-cyan-400 bg-clip-text text-transparent text-center">
Contact Me Contact Me
</h2> </h2>
<ul className="flex flex-row space-x-2 space-y-2 list-inside mx-5"> <ul className="flex flex-col md:flex-row space-x-2 space-y-2 list-inside mx-5">
{contacts.map((contact, key) => ( {contacts.map((contact, key) => (
<li key={key} className="text-3xl whitespace-nowrap text-blue-300 py-1 px-3 rounded-full hover:text-blue-500 transition"><a href={contact.link} target="_blank">{contact.icon} {contact.name}</a></li> <li key={key} className="text-3xl whitespace-nowrap text-blue-300 py-1 px-3 rounded-full hover:text-blue-500 transition"><a href={contact.link} target="_blank">{contact.icon} {contact.name}</a></li>
))} ))}
+63 -25
View File
@@ -7,79 +7,117 @@ function Projects() {
{ {
"name": "Portfolio", "name": "Portfolio",
"tech": [ "tech": [
"Node.Js", "Node.js",
"React", "React",
"Vite", "Vite",
"Tailwind CSS", "Tailwind CSS",
"Docker", "Docker"
], ],
"description": "This is the link to the gitlab repository of the portfolio you are currently viewing!", "description": "This is the link to the GitLab repository of the portfolio you are currently viewing!",
"visibility": "Public", "visibility": "Public",
"link": "https://gitlab.plocserv.fr/ploc300/portfolio_v2", "link": "https://gitlab.plocserv.fr/ploc300/portfolio_v2"
}, },
{ {
"name": "Challenges for Cyber club Angel", "name": "Challenges for Cyber Club Angel",
"tech": [ "tech": [
"Python", "Python",
"Bash", "Bash",
"Docker", "Docker",
"C/C++", "C/C++"
], ],
"description": "This project contain most of the challenges I made (not the few firsts) for the Cyber club of the Lannion IUT. Sadly I cannot let this repository in public or else my flags will be everywhere, but if you really want to see them you can still request access by contacting me!", "description": "This project contains most of the challenges I made (not the first few) for the Cyber Club of the Lannion IUT. Sadly, I cannot make this repository public or else my flags will be everywhere, but if you really want to see them, you can still request access by contacting me!",
"visibility": "Private", "visibility": "Private",
"link": "https://gitlab.plocserv.fr/club_cyber_angel/challenges", "link": "https://gitlab.plocserv.fr/club_cyber_angel/challenges"
}, },
{ {
"name": "Root-Me", "name": "Root-Me",
"tech": [ "tech": [
"Python", "Python",
"C/C++", "C/C++"
], ],
"description": "This project contain some of my latest solve on the Root-Me platform. All the solves inside this project have been automated with script (mostly in Python) so I can reuse them later when doing other challenges. This repository is Private and no access will be granted to it as it is againts root-me policy.", "description": "This project contains some of my latest solves on the Root-Me platform. All the solves inside this project have been automated with scripts (mostly in Python) so I can reuse them later when doing other challenges. This repository is private and no access will be granted to it as it is against Root-Me policy.",
"visibility": "Private", "visibility": "Private",
"link": "https://gitlab.plocserv.fr/ploc300/root-me", "link": "https://gitlab.plocserv.fr/ploc300/root-me"
}, },
{ {
"name": "Check Image Up-to-date", "name": "Check Image Up-to-date",
"tech": [ "tech": [
"Python", "Python"
], ],
"description": "This python script allows me to check if my stacks (docker-compose on Portainer) are Up-to-date. This script is run every morning inside my Jenkins and send me an email with the result. The repo is in private, but I can send you the script if you want, again just conatct me!", "description": "This Python script allows me to check if my stacks (Docker Compose on Portainer) are up-to-date. This script is run every morning inside my Jenkins and sends me an email with the result. The repo is private, but I can send you the script if you wantagain, just contact me!",
"visibility": "Private", "visibility": "Private",
"link": "https://gitlab.plocserv.fr/plocserv/check_images_up_to_date", "link": "https://gitlab.plocserv.fr/plocserv/check_images_up_to_date"
}, },
{ {
"name": "Pylint Disable Analyser", "name": "Pylint Disable Analyser",
"tech": [ "tech": [
"Python", "Python"
], ],
"description": "This cli tool has been wrote during my Intership at Nokia. It allow to run a single python script and analyse every python file in the sub-directories. After running a CSV report is generated with a global summary of all the pylint disable found as well as a report file by file. This project is Private and cannot be shared since it's a internal tool.", "description": "This CLI tool was written during my internship at Nokia. It allows running a single Python script and analyzing every Python file in the subdirectories. After running, a CSV report is generated with a global summary of all the pylint disables found, as well as a report file by file. This project is private and cannot be shared since it's an internal tool.",
"visibility": "Private", "visibility": "Private",
"link": "https://github.com/Ploc300/PylintDisableAnalyser", "link": "https://github.com/Ploc300/PylintDisableAnalyser"
}, },
{ {
"name": "RTPhone", "name": "RTPhone",
"tech": [ "tech": [
"Python", "Python",
"Tkinter", "Tkinter"
], ],
"description": "This is a group school project, the objective was to create a Softphone (like MS Teams, Discords, etc...). I realised most of the Server and my 2 teammates have focused the client. The final project was a bit buggy, but the main objectives, make a phone call, make a conference call, \"secure connection\" with token, user management and phone number change without conflict were working. I also added a complete GUI for the server using tkinter. The server code is not really great since I wasn't using Pylint for my projects at this time. This project is Public but unmaintained.", "description": "This is a group school project. The objective was to create a Softphone (like MS Teams, Discord, etc.). I worked mainly on the server, while my two teammates focused on the client. The final project was a bit buggy, but the main objectivesmaking a phone call, making a conference call, \"secure connection\" with tokens, user management, and phone number change without conflictwere working. I also added a complete GUI for the server using Tkinter. The server code is not great, since I wasn't using Pylint for my projects at that time. This project is public but unmaintained.",
"visibility": "Private", "visibility": "Private",
"link": "https://github.com/Ploc300/RTPhone", "link": "https://github.com/Ploc300/RTPhone"
}, },
{ {
"name": "Projet Cyber", "name": "Projet Cyber",
"tech": [ "tech": [
"Mestasploit", "Metasploit",
"Debian", "Debian"
], ],
"description": "This is the report for a school project. The project was too make a security audit on a machine (Basic Pentesting 1 on VulnHub). This was a really fun project too make as it helped me learning how to do a penetration test as well a writting a report for it. This repo is private, since this project is still made by new students, therefore you can request access if you want to read it!", "description": "This is the report for a school project. The project was to make a security audit on a machine (Basic Pentesting 1 on VulnHub). This was a really fun project to make, as it helped me learn how to do a penetration test as well as write a report for it. This repo is private, since this project is still made by new students. Therefore, you can request access if you want to read it!",
"visibility": "Private", "visibility": "Private",
"link": "https://github.com/Ploc300/ProjetCyber", "link": "https://github.com/Ploc300/ProjetCyber"
}, },
{
"name": "Pylint Disable Analyzer V2",
"tech": [
"C"
],
"description": "This is a rewrite of my older project \"Pylint Disable Analyzer\" to learn and improve my C skills. I have decided to make this since I wanted to learn C but I needed some project that could be usefull in the futur. Since the python version work but can be pretty slow on really big projects, I have decided to remake it entirely in C (which makes it way faster).",
"visibility": "Public",
"link": "https://gitlab.plocserv.fr/ploc300/pylintanalyzerv2"
}, {
"name": "Own-Os",
"tech": [
"Assembly",
"C"
],
"description": "As the title say, I'm trying to make my own os. The goal is not to make a fully functional os but more to learn about low-level programming, kernel, and everything related. It is based on the amazing repository: https://github.com/cfenollosa/os-tutorial",
"visibility": "Private",
"link": "https://gitlab.plocserv.fr/ploc300/own-os"
}, {
"name": "dCodeAbuser",
"tech": [
"Python",
"Website Scrapping"
],
"description": "While doing some CTF challenges, some friends of mine showed me an amazing website \"dcode.fr\". I have used it a lot but always thought it is missing something, a public API / a way to automate request. So I decided to make this tool to automate scrapping the result.",
"visibility": "Public",
"link": "https://gitlab.plocserv.fr/ploc300/dcodeabuser"
}, {
"name": "Arch Config",
"tech": [
"Python",
"Lua",
"Shell",
"CSS",
"Config Files"
],
"description": "After re-installing Arch Linux on my laptop, I wanted to synchronize my config with my desktop. Therefore, one of the easiest way to do that for me was to create a git repository. So here we are!",
"visibility": "Private",
"link": "https://gitlab.plocserv.fr/plocserv/arch_config"
}
] ]
return ( return (
<section id="projects" className="min-h-screen flex items-center justify-center py-20"> <section id="projects" className="min-h-screen flex items-center justify-center py-20">
<RevealOnScroll> <RevealOnScroll>