# Portfolio v2 — Analyse & plan d'action **Projet source :** `/home/johan/WebstormProjects/Portfolio_angular` **URL live :** https://johanleroy.fr **Date :** 20 avril 2026 --- ## 1. Analyse de l'existant ### Stack actuelle | Élément | Valeur | |---|---| | Framework | Angular 19.2 | | Styling | TailwindCSS 4 | | State / Data | Aucun (tout en dur dans les templates) | | Animations | Particules vanilla JS maison (`home.component.ts`) | | Icônes | PNG dans `/public/img/icon/` (pas de SVG, pas HiDPI) | | Icônes UI | Classes FontAwesome (`fa-gamepad`, `fa-film`) **sans lib chargée → cassées** | | Dark mode | Toggle manuel via `localStorage` | | SEO | Service custom `seo.service.ts` (title, description, OG, canonical) | | Router | Lazy-load `PublicModule`, view transitions activées | | Hébergement | Statique (`.htaccess` Apache dans `/public/`) | | Tests | Karma/Jasmine (0 test écrit) | ### Structure ``` src/app/ ├── _models/ particule.ts, seo.ts ├── _services/ seo.service.ts └── public/ ├── public-layout/ header + dark toggle + nav ├── public-routing.module.ts ├── public.module.ts └── pages/ ├── home/ (448 lignes HTML — accueil + skills + centres d'intérêt) ├── formations/ (169 lignes) ├── experience/ (417 lignes — 6 entreprises Actemium, SNCF, Cerema, Novoferm, PivotPoint, Almeria) ├── projets/ (104 lignes — 3 projets MonVoisinGeek, Techos, LPLV) └── not-found/ ``` ### Palette actuelle (`src/styles.css`) ```css --color-primary-dark: #181818 --color-primary-blue: #0A2463 --color-primary-light: #3E92CC --color-primary-white: #FFFAFF --color-primary-accent: #D8315B ``` ### Problèmes identifiés 1. **Stack disproportionnée** — Angular + Zone.js pour un portfolio statique = bundle lourd (warning 500 kB dans `angular.json`), overkill pour du contenu vitrine. 2. **Décalage avec ta stack actuelle** — tu bosses maintenant sur Next.js/Nuxt/NestJS, Angular n'est plus dans aucun de tes projets en mémoire. 3. **Contenu 100 % hardcodé dans les templates** — chaque modif de texte, techno, projet ou date d'expérience impose de recompiler + redéployer. 4. **Animations minimalistes** — juste des particules en `requestAnimationFrame`, pas d'effets wow (scroll reveal, parallax, 3D, text morphing, cursors custom…). 5. **Icônes PNG** — flou sur écrans HiDPI, poids réseau élevé, pas de teinte dynamique possible. 6. **FontAwesome référencé mais jamais chargé** → les 4 icônes des centres d'intérêt sont invisibles. 7. **Tests inexistants** malgré la config Karma — bruit dans `package.json`. 8. **Pas de PWA** (manifest.json, service worker) alors que c'est trivial sur du statique. ### Ce qui marche bien et à conserver - La structure de navigation (Accueil / Formations / Expérience / Projets). - La palette existante (tu peux la reprendre ou l'enrichir). - Le `SeoService` et ses meta tags dynamiques. - Dark mode par défaut selon préférence système. - Export statique déployé sur Plesk via Apache. - Le CV PDF téléchargeable. --- ## 2. Choix techno recommandé ### Option A — **Astro 5 + React islands** ⭐ recommandé **Pourquoi :** - 0 JS par défaut → Lighthouse 100 presque gratuit. - Islands pattern : tu charges React + Framer Motion uniquement sur les sections animées. - Content Collections typées (Zod) → ton JSON devient un contrat validé au build. - SSG pur, déploiement Plesk identique à l'actuel (export statique). - Supporte nativement les endpoints SSR si tu veux un mini-admin. **Stack complète :** - Astro 5 (router fichiers, layouts) - React 19 (îlots interactifs) - TailwindCSS 4 (continuité palette) - Framer Motion (micro-interactions déclaratives) - GSAP + ScrollTrigger (timelines paillettes) - Lenis (smooth scroll) - @react-three/fiber + @react-three/drei (effets 3D type scène accueil) - Lucide React (icônes UI) + Simple Icons via iconify (logos techno vectoriels) - TypeScript strict ### Option B — **Next.js 15 + App Router** Pertinent si tu veux un vrai mini-back-office plus tard (auth JWT, API routes, ISR). Plus lourd qu'Astro pour un simple portfolio. ### Option C — **Nuxt 4** Si tu préfères rester côté Vue. Excellent mais tu connais déjà Vue 3 (Amarea, TrackSniff), donc pas de challenge. ### Recommandation **Astro 5** — le meilleur rapport puissance/légèreté pour un portfolio. Tu ajoutes Next.js à ton CV avec Techos, Astro te donne un 3e framework frontend moderne à afficher, et tu gagnes une killer app de perf. --- ## 3. Système de contenu éditable sans rebuild ### Architecture proposée ``` public/ ├── content/ │ ├── profile.json (nom, titre, accroche, photo, CV) │ ├── skills.json (catégories + items avec niveau, logo iconify) │ ├── experiences.json (tableau d'expériences pro) │ ├── formations.json (tableau de formations) │ ├── projects.json (tableau de projets + images + liens) │ ├── interests.json (centres d'intérêt) │ └── site.json (meta SEO, couleurs, switches features) └── img/ (assets éditables) ``` ### Principe - Les fichiers JSON sont servis **en statique** par ton Plesk (pas dans le bundle). - Côté client, un `ContentService` fait un `fetch('/content/profile.json')` au mount. - Les composants React affichent les données via Suspense. - **Modif en production = éditer le JSON sur le serveur → rechargement navigateur = MAJ immédiate. Zéro rebuild.** ### Schémas typés (Zod) Les mêmes schémas servent : - au build (validation SSG des données si tu veux injecter au build) - au runtime (parsing des JSON fetchés) - à l'admin (génération de formulaires) Exemple `content/profile.json` : ```json { "name": "Johan Leroy", "title": "Développeur Fullstack", "tagline": "Dev le jour, DJ la nuit", "hero": { "photo": "/img/pp/pp3.png", "cta": [ { "label": "Télécharger mon CV", "href": "/assets/cv.pdf" }, { "label": "Voir mes projets", "href": "/projets" } ] }, "socials": { "email": "leroyjohan3@gmail.com", "github": "https://github.com/JohanLeroy", "gitea": "https://git.lidge.fr/johanleroy", "website": "https://johanleroy.fr" } } ``` ### 3 niveaux d'édition (à choisir) | Niveau | Outil | Usage | |---|---|---| | **1. Terminal / SFTP** | FTP Plesk + éditeur texte | MAJ rapide, zéro surcouche. Le plus simple. | | **2. Mini-admin web** | `/admin` protégé par mot de passe (cookie httpOnly côté endpoint Astro SSR) | Formulaire qui édite `content/*.json` en live sur le serveur | | **3. Gitea as CMS** | Un repo `johan-portfolio-content` dédié. L'admin web pousse via l'API Gitea. | Historisation automatique, rollback possible, build-free par cron `git pull` côté Plesk. | **Reco pour toi :** niveau 2 ou 3. Le niveau 3 est le plus élégant car tu gardes un vrai git history sans polluer le repo code. ### Ce que l'admin web permettrait - Édition inline du profil (nom, titre, bio) - Ajout/édition/suppression de projets (drag-drop pour réordonner) - Ajout d'une expérience pro - Changement du thème de couleur (live preview) - Toggle du mode "embauche disponible" (badge vert sur le site) - Upload de nouvelles images (vers `/public/img/` via endpoint SSR) - Export / import du JSON (backup) --- ## 4. UX "paillettes dans les yeux" — direction créative ### Accueil - **Hero 3D** avec @react-three/fiber : scène minimaliste type "disco ball" qui tourne lentement, sensible au mouvement de souris (parallax). Nod subtil à ton univers DJ. - **Texte morphing** (GSAP SplitText) — "Dev" se transforme en "DJ" puis en "Dev" en boucle lente. - **Curseur custom** qui suit la souris avec un léger lag, change de forme sur les liens. - **Gradient animé** en arrière-plan type aurore boréale (shader ou CSS `conic-gradient` animé). ### Scroll - **Lenis smooth scroll** partout. - **Scroll-triggered animations** : sections qui révèlent leur contenu en cascade (fade + translate-y + blur-out). - **Pin + horizontal scroll** sur la section Projets (GSAP ScrollTrigger, type showcase Awwwards). - **Progress bar** en haut de page. ### Section skills - Cards avec effet **hover 3D tilt** (vanilla-tilt ou React équivalent). - Icônes SVG des technos avec **glow au survol**. - Compteur de maîtrise animé (ring progress) au scroll. ### Timeline expérience - Layout type **métro parisien** (une ligne verticale animée, stations = expériences). - Cards qui s'ouvrent en accordéon au scroll. ### Projets - Carousel horizontal pinned avec images **zoom parallax**. - Badge techno avec micro-logos simple-icons colorés. - Hover : overlay gradient + CTA "voir projet". ### Detail bonus - **Mode "party"** (easter egg) : un bouton discret qui active un strobe + particles + glitch texts → clin d'œil DJ. - **Konami code** → affiche ton set DJ en fond sonore discret. - **Switch 3 thèmes** : Day, Night, Neon (le mode neon = pleine paillettes). --- ## 5. Plan d'exécution ### Phase 0 — Prérequis (décision utilisateur) - [ ] Valider le choix Astro vs Next.js vs Nuxt. - [ ] Valider le niveau d'édition (SFTP / admin web / Gitea). - [ ] Choisir nom de projet (`portfolio-v2`, `johanleroy-fr`, `portfolio-astro`, …). - [ ] Palette : garder l'actuelle ou refaire ? (je peux proposer 3 palettes). ### Phase 1 — Bootstrap (1 jour) - Scaffold Astro + TS strict + Tailwind 4 + React integration. - Setup ESLint + Prettier + configs héritées de Techos (cohérence). - Créer les 6 schémas Zod + JSON de contenu initial (repris du site actuel). - Layout global + router fichier (`/`, `/formations`, `/experience`, `/projets`). - Migrer `SeoService` vers un composant `` Astro. ### Phase 2 — Contenu & structure (1–2 jours) - Extraire tout le contenu des templates actuels vers les JSON. - Migrer les PNG d'icônes → Iconify (Simple Icons + Lucide). - Migrer les images projets/entreprises (optimisation avec `astro:assets`). - Pages statiques sans animations pour valider la structure. ### Phase 3 — Animations & paillettes (2–3 jours) - Intégration Lenis + configuration smooth scroll globale. - Installation Framer Motion + GSAP + ScrollTrigger. - Hero 3D @react-three/fiber. - Scroll-triggered reveals sur chaque section. - Curseur custom + cards 3D tilt + timeline métro. - Carousel projets pinned horizontal. - Thèmes Day / Night / Neon. ### Phase 4 — Admin d'édition (1–2 jours, optionnel selon niveau choisi) - Endpoint Astro SSR `/api/content/:file` (GET/PUT). - Protection par mot de passe + cookie httpOnly. - Page `/admin` : formulaires dynamiques générés depuis les schémas Zod. - Upload d'images. - Export / import JSON. - (Variante Gitea) : intégration Gitea API pour push auto. ### Phase 5 — Polish & deploy (1 jour) - PWA (manifest + service worker). - Audit Lighthouse (objectif 100/100/100/100). - Sitemap auto + robots.txt. - Meta tags Open Graph + Twitter Cards. - Build production. - Déploiement Plesk (remplacement `/dist` existant). - Redirections 301 si URLs changent. ### Phase 6 — Extras plus tard - Blog MDX (écriture d'articles techniques). - Page contact avec vrai formulaire (via endpoint SSR ou Formspree). - Section "Now" (what I'm up to, mis à jour mensuel). - Stats GitHub/Gitea live (commits, streaks). - Page `/jeux` ou `/bacs` pour expériences DJ. --- ## 6. Estimation totale | Phase | Charge | |---|---| | 0 — Décisions | 30 min | | 1 — Bootstrap | 1 jour | | 2 — Contenu & structure | 1–2 jours | | 3 — Animations | 2–3 jours | | 4 — Admin (optionnel) | 1–2 jours | | 5 — Polish & deploy | 1 jour | | **Total sans admin** | **5–7 jours** | | **Total avec admin** | **6–9 jours** | --- ## 7. Questions initiales — réponses validées ✅ | # | Question | Réponse | |---|---|---| | 1 | Framework | ✅ **Astro 5** | | 2 | Système d'édition | ✅ **Admin web** (option 2) | | 3 | Palette / identité | ✅ **Refonte DEV/DJ/Neon** | | 4 | Hébergement | ✅ **Plesk** (stay put) — ISR à creuser selon contraintes | | 5 | Niveau "paillettes" | ✅ **Wow mais pro** (pas d'effets dans tous les sens) | | 6 | Contenu à rafraîchir | ✅ **Ajouter projets récents** (sauf Beehelp = pro/NDA) | | 7 | Nom du repo | ✅ `portfolio` | --- ## 8. Setup technique dérivé des choix | Élément | Valeur | |---|---| | Mode Astro | **Hybrid** — SSG pour pages publiques, SSR pour `/admin` et `/api` | | Déploiement | **Plesk Node.js hosting** (même pattern que `techos_api`) | | Persistance contenu | `/public/content/*.json` édités par endpoints SSR protégés | | Auth admin | Mot de passe + cookie httpOnly (JWT ou session simple) | | MAJ contenu en prod | Admin web → PUT JSON → **fetch runtime côté client, zéro rebuild** | | ISR — note Plesk | Plesk = serveur Node permanent, on a l'équivalent d'ISR gratuit. Pas d'ISR Next.js-style mais re-fetch JSON runtime = effet identique | --- ## 9. Direction artistique — 3 palettes néon à trancher ### Option A — **Cyberpunk Dark** (blade-runner / tekno industrielle) ``` bg: #0A0A0F (noir profond) accent 1: #00F0FF (cyan électrique) accent 2: #FF2A6D (rose magenta) accent 3: #D1F7FF (blanc bleuté) texte: #E0E0FF ``` ### Option B — **Rave / Miami** (90's, fun, coloré) ``` bg: #0D0221 (violet nuit) accent 1: #FF00C8 (pink néon) accent 2: #00FFC8 (mint laser) accent 3: #FFD600 (jaune flash) texte: #FFF8F0 ``` ### Option C — **Tech Minimal + 1 néon** ⭐ reco pro ``` bg: #0B0B0E (charbon) surface: #16161D accent: #39FF14 (vert néon strobe) — UN SEUL pop texte: #EAEAEA secondaire: #8A8F98 ``` **Reco :** Option C pour recruteurs (le plus pro), Option A si on assume la vibe DJ. --- ## 10. Liste projets à afficher — proposition | # | Projet | Statut | Action | |---|---|---|---| | 1 | **Techos** (asso hébergement) | Live `techos-asso.fr` | ✅ Inclure | | 2 | **TrackSniff** | Privé (invitation) | ⚠️ À trancher | | 3 | **Amarea Tattoo** | Client (studio tatouage) | ✅ Inclure | | 4 | **Lidge** | Perso, auto-hébergé | ✅ Inclure | | 5 | **Portfolio v2** (méta) | En cours | ✅ Classique circulaire | | 6 | **MonVoisinGeek / LPLV** (anciens) | Live actuellement | ⚠️ Keep or drop ? | | ❌ | **Beehelp** | Pro / NDA | ❌ Exclu (validé) | --- ## 11. Questions finales — réponses validées ✅ | # | Question | Réponse | |---|---|---| | 1 | **Palette** | ✅ **Option A — Cyberpunk Dark** (`#0A0A0F / #00F0FF / #FF2A6D / #D1F7FF / #E0E0FF`) | | 2 | TrackSniff affiché ? | ❌ **Non** (privé, on n'affiche pas) | | 3 | Portfolio v2 (self-reference) | ❌ **Non** | | 4 | MonVoisinGeek / LPLV | ✅ **Garder** — mais marqués **"Projet fermé / archivé"**, infos présentes, liens morts | | 5 | Projet supplémentaire | ✅ **Ajouter "Bot Discord KSauce"** | | 6 | Nouvelle expérience/formation | — (à compléter au moment de migrer le contenu) | ### Liste finale des projets affichés | # | Projet | État | Lien | |---|---|---|---| | 1 | **Techos** | Live | techos-asso.fr | | 2 | **Amarea Tattoo** | Live | (à confirmer) | | 3 | **Lidge** | Live perso | (à confirmer) | | 4 | **Bot Discord KSauce** | (à préciser) | — | | 5 | **MonVoisinGeek** | 🔒 Archivé | — | | 6 | **LPLV** | 🔒 Archivé | — | --- ## 12. Plan d'implémentation détaillé — GO **Répertoire cible :** `/home/johan/WebstormProjects/portfolio` (nouveau, à côté de l'ancien `Portfolio_angular`) ### Étape 1 — Bootstrap Astro hybrid ⬜ - [ ] `npm create astro@latest portfolio` (template `minimal`, TS strict) - [ ] Installer intégrations : `@astrojs/react`, `@astrojs/tailwind`, `@astrojs/node` (adapter SSR) - [ ] Configurer `astro.config.mjs` mode `hybrid` + adapter Node standalone (Plesk) - [ ] Setup Prettier + ESLint (aligné sur Techos) - [ ] `.gitignore`, `.editorconfig`, `README.md` ### Étape 2 — Design system Cyberpunk Dark ⬜ - [ ] `tailwind.config` + CSS custom properties (palette Option A) - [ ] Typographies : **heading** = Space Grotesk / **body** = Inter / **mono accent** = JetBrains Mono - [ ] Utilitaires `glow-cyan`, `glow-pink`, `neon-border`, `scanlines`, `noise-overlay` - [ ] Cursor custom (composant React island) - [ ] Dark only (pas de light mode — la vibe cyberpunk ne s'y prête pas) ### Étape 3 — Schémas Zod + contenu JSON ⬜ - [ ] `src/content/schemas/` : `profile.ts`, `skills.ts`, `experiences.ts`, `formations.ts`, `projects.ts`, `interests.ts`, `site.ts` - [ ] `public/content/*.json` : contenu extrait des templates Angular actuels + MAJ - [ ] `ContentService` (fetch runtime) côté client - [ ] Validation Zod au parsing (garde-fou si JSON mal formé) ### Étape 4 — Pages publiques + layout ⬜ - [ ] Layout global : `Header` (nav + logo glitch), `Footer`, `CursorCustom`, `LenisProvider` - [ ] `/` — Hero 3D disco-ball (R3F), scroll reveals, skills, centres d'intérêt - [ ] `/formations` — Timeline métro verticale - [ ] `/experience` — Timeline métro + cards accordéon (6 entreprises) - [ ] `/projets` — Carousel pinned horizontal + badges techno Iconify - [ ] `/404` — Page glitch 404 ### Étape 5 — Animations paillettes ⬜ - [ ] Lenis smooth scroll global - [ ] Framer Motion : reveals + micro-interactions - [ ] GSAP + ScrollTrigger : timelines pinned - [ ] Hero R3F : disco ball parallax souris - [ ] SplitText : morphing "Dev / DJ / Dev" - [ ] Cards skills : 3D tilt (hover) - [ ] Gradient conic animé en bg ### Étape 6 — Admin SSR ⬜ - [ ] `/admin/login` — form password → cookie httpOnly - [ ] Middleware `src/middleware.ts` : protection route `/admin/*` - [ ] `/admin` — dashboard, liste des sections éditables - [ ] `/admin/edit/[section]` — formulaires générés depuis Zod schemas - [ ] `/api/content/[section]` — GET/PUT (lecture + écriture JSON serveur) - [ ] `/api/upload` — upload images vers `public/img/` - [ ] `/api/export` + `/api/import` — backup/restore JSON ### Étape 7 — SEO + PWA + déploiement ⬜ - [ ] Composant `` (title, description, OG, canonical, Twitter) - [ ] `sitemap.xml` auto - [ ] `manifest.json` + service worker (PWA) - [ ] Redirections 301 depuis anciennes URLs si nécessaire - [ ] Build prod + test local - [ ] Script déploiement Plesk Node (équivalent Techos API) - [ ] Remplacement sur `johanleroy.fr` ### Étape 8 — Post-déploiement ⬜ - [ ] Audit Lighthouse (objectif 95+) - [ ] Test admin web en prod - [ ] Rédiger `docs/ADMIN.md` (comment éditer le contenu) - [ ] Snapshot initial dans git du contenu actuel - [ ] Mettre à jour `CLAUDE.md` du projet --- **GO ✅** — scaffold démarré. --- ## 13. État d'implémentation (suivi) | Étape | Status | |---|---| | 1 — Bootstrap Astro hybrid (React + Tailwind 4 + Node adapter) | ✅ | | 2 — Design system Cyberpunk Dark (palette, glow, néon, fonts) | ✅ | | 3 — Schémas Zod + JSON contenu extrait | ✅ | | 4 — Layout + pages publiques (/, /formations, /experience, /projets, /404) | ✅ | | 5 — Animations (Lenis, Framer Motion, R3F hero disco, morph, curseur) | ✅ | | 6 — Admin SSR protégé + API CRUD JSON + upload | ✅ | | 7 — SEO + build prod + workflow Gitea + README déploiement | ✅ | ### Livrables - `/home/johan/WebstormProjects/portfolio/` (projet Astro 6 + React 19 + Tailwind 4) - Build production OK → `dist/server/entry.mjs` (startup Plesk Node) - Dev testé sur **http://localhost:3100** - Workflow `.gitea/workflows/deploy.yml` déclenché sur push `main` - Contenu projets mis à jour : Techos, Amarea Tattoo, Lidge, Bot Discord KSauce, LPLV (archivé), MonVoisinGeek (archivé) ### Prochaines étapes côté utilisateur 1. `cd ~/WebstormProjects/portfolio && npm run dev` → vérifier sur http://localhost:3100 2. `npm run hash:password -- monMotDePasse` → copier `ADMIN_PASSWORD_HASH` + `ADMIN_JWT_SECRET` dans un `.env` local 3. Tester `/admin/login` puis `/admin` 4. Initialiser git et pousser sur `main` vers Gitea 5. Configurer les secrets Gitea (`FTP_HOST`, `FTP_USER`, `FTP_PASSWORD`, `FTP_TARGET_DIR`) 6. Configurer Plesk Node.js : startup file `dist/server/entry.mjs`, variables d'env admin, Node 22 7. Pousser sur `main` → CI déploie → redémarrer l'app Node dans Plesk