Logo

Dev Log

Journal des versions

Fonctionnalités livrées et correctifs appliqués, version par version. Dernière mise à jour : 04/05/2026

PERF FIX NEW FEAT — type de changement
V1.3.1
Patch 4 mai 2026

Umami Analytics & mise à jour des mentions légales

1 new 1 fix

Ajout de l'outil d'analyse d'audience Umami (sans cookies, sans données personnelles, conforme RGPD) et mise à jour des pages légales pour documenter cette collecte de statistiques anonymes.

NEW

Umami Analytics — suivi d'audience respectueux de la vie privée

layouts/Layout.astro

Intégration du script Umami Analytics (cloud.umami.is) dans le <head> du layout global via is:inline defer. Umami ne pose aucun cookie, ne collecte aucune donnée personnelle identifiable (pas d'IP stockée, pas de fingerprinting) et est conforme RGPD sans bandeau de consentement requis. Mesure uniquement des statistiques agrégées et anonymes : pages vues, référents, type d'appareil, navigateur.

FIX

Mentions légales & politique de confidentialité — ajout de la mention Umami

pages/mentionlega.astro pages/confidentialite.astro

Mise à jour de la section Données personnelles (mentions légales) et des sections Cookies/traceurs et Partage des données (politique de confidentialité) pour documenter l'usage d'Umami Analytics : outil sans cookies, sans collecte de données personnelles, conforme RGPD. Ajout d'Umami dans la liste des prestataires techniques.

V1.3
Patch 28 mars 2026

Migration VPS, sécurité renforcée & optimisations CDN

3 new 2 perf 3 fix

Migration complète de Netlify vers un VPS Node + Apache proxy, renforcement de la sécurité (middleware headers, rate limiting), suppression des CDN externes au profit de bundles npm, et corrections de compatibilité cross-browser.

NEW

Déploiement VPS — migration Netlify → Node standalone + Apache proxy

astro.config.mjs deploy.js

Remplacement de l'adapter @astrojs/netlify par @astrojs/node en mode standalone. Création d'un script deploy.js (Node.js cross-platform) qui build localement, envoie via scp et redémarre le service systemd sur le VPS. Ajout de security: { checkOrigin: false } dans astro.config.mjs pour contourner la vérification CSRF cassée par le proxy Apache (les headers X-Forwarded-Host et X-Forwarded-Proto sont transmis côté Apache). Ajout de getPublicOrigin() dans contact.ts pour reconstruire l'URL publique derrière le proxy.

NEW

Middleware sécurité — headers HTTP sur chaque réponse SSR

src/middleware.ts

Création de middleware.ts avec defineMiddleware. Ajoute systématiquement X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin et Permissions-Policy: camera=(), microphone=(), geolocation=() sur toutes les réponses SSR.

NEW

Rate limiting en mémoire — /api/contact et /api/chat

pages/api/contact.ts pages/api/chat.ts

Rate limiting par IP via une Map en mémoire. Limite : 5 req/min sur /api/contact, 20 req/min sur /api/chat. Réponse 429 Too Many Requests si dépassé. Pas de dépendance externe — logique embarquée directement dans chaque endpoint SSR.

PERF

Migration CDN → npm — Three.js importmap, GSAP et Lenis supprimés du <head>

layouts/Layout.astro js/lenis-init.js js/TDscript.js pages/index.astro

Suppression de l'importmap Three.js, des 4 balises <script> CDN GSAP/ScrollTrigger et du script CDN Lenis dans Layout.astro. Création de lenis-init.js (import Lenis npm, expose window.lenis). Ajout des imports gsap et ScrollTrigger en tête de TDscript.js. Scripts index.astro passés de <script type='module' src={url}> à <script>import '...'</script> pour être bundlés par Vite. Les preconnects jsdelivr/cdnjs/unpkg sont supprimés.

PERF

Loader coordonné avec le chargement du modèle GLB — 4 phases de progression

js/loader.js js/TDscript.js

Refonte du loader.js avec 4 phases : montée rapide 0→85% (800 ms), plateau, ease-out 85→95% (500 ms), puis attente du modèle 3D. TDscript.js dispatch l'événement custom modelLoaded à la fin du chargement GLB (success et error). Pendant l'attente, glissement lent 95→99% (CREEP_RATE). Quand modelReady, rush final 95→100% en 350 ms (easeOutCubic). Safety timer 10 s si le modèle ne se charge jamais.

FIX

Scroll projets cross-browser — compatibilité Lenis + getBoundingClientRect

js/GlobalIndex.js

Le scroll horizontal des projets était cassé sur Firefox et Safari car getBoundingClientRect() retourne des positions relatives à la viewport quand Lenis intercepte le scroll. Correction : cache de la position absolue sectionTop = getBoundingClientRect().top + window.scrollY (recalculé uniquement au resize), scroll calculé depuis window.scrollY. Hook Lenis direct via window.lenis.on('scroll', ...) avec flag lenisHooked pour éviter l'écoute double native/Lenis.

FIX

Chatbot mobile — fullscreen, bouton fermer et gestion du clavier natif

components/Chatbot.astro

Sur mobile (< 640 px) la fenêtre passe en fullscreen (inset: 0, height: 100dvh avec fallback 100vh). Le bouton toggle flottant est masqué quand le chat est ouvert (toggle.style.display = 'none'). Ajout d'un bouton fermer dans le header (visible uniquement sur mobile). La zone messages passe en flex-1 pour absorber l'espace restant quand le clavier natif réduit la viewport (dvh se contracte dynamiquement). Padding safe-area iOS via env(safe-area-inset-bottom).

FIX

Firefox — fallback backdrop-filter via @supports (sans !important)

styles/global.css

Firefox ne supporte pas backdrop-filter. Ajout d'un bloc @supports not (backdrop-filter: blur(1px)) dans global.css qui applique un fond opaque de substitution sur #header-inner, #mobile-overlay et #chatbot-window. Les sélecteurs ID ont une spécificité suffisante pour surcharger les classes Tailwind sans recourir à !important.

V1.2
Patch 14 mars 2026

Chatbot IA & sécurisation des variables d'environnement

1 new 1 fix

Intégration d'un assistant IA conversationnel dans le portfolio et migration des credentials sensibles en variables d'environnement.

NEW

Chatbot IA — bouton flottant + fenêtre de conversation

components/Chatbot.astro pages/api/chat.ts

Bouton cercle fixe en bas à droite avec icône chat. Au clic, une fenêtre de conversation apparaît en slide-up. L'historique des messages est conservé en mémoire JS côté client et renvoyé à chaque requête pour maintenir le contexte. Un sessionId est généré via crypto.randomUUID() au chargement. L'endpoint SSR /api/chat relaie les messages vers l'API externe en injectant la clé depuis les variables d'environnement — la clé ne transite jamais côté client. Le system prompt du chatbot est configuré directement dans PocketBase côté API.

FIX

Sécurisation — credentials Gmail migrés en variables d'environnement

pages/api/contact.ts .env

GMAIL_USER et GMAIL_APP_PASS étaient codés en dur dans le fichier source, exposant les credentials dans le dépôt git. Migrés en variables d'environnement lues via import.meta.env. À déclarer dans Netlify → Site settings → Environment variables pour la production.

V1.1.1
Patch 07 mars 2026

Correction du bug de la barre & amélioration du menu mobile

2 fix

Correctif du responsive header sur la page À propos et refonte de la disposition du menu mobile.

FIX

Header non responsive sur /apropos — ajout de `relative` sur la section

pages/apropos.astro

La <section> de la page À propos n'avait pas de position: relative. Les divs de glow (absolute inset-0) se positionnaient donc par rapport au body/viewport. L'élément interne w-[980px] débordait hors du viewport, ce qui empêchait les breakpoints md: de Tailwind de se déclencher correctement. Résultat : le header restait en mode desktop même sur mobile, uniquement sur cette page. Correction : ajout de la classe `relative` sur la section pour contenir les absolus.

FIX

Menu mobile — liens en haut, boutons réseaux en bas

components/Header.astro

Refonte de la disposition du menu mobile fullscreen. L'overlay passe en flex flex-col avec shrink-0 sur la top bar. La zone de contenu utilise flex-1 + justify-between pour placer les liens de navigation en haut (pt-16) et les boutons LinkedIn / Contact en bas (pb-12). Correction du bug d'overflow qui rendait les boutons CTA invisibles (h-full remplacé par flex-1).

V1.1
Patch 06 mars 2026

Correctifs & optimisations

4 perf 6 fix 5 new

Patch de performance et nettoyage de code. Zéro modification visuelle ou fonctionnelle — optimisations internes uniquement.

PERF

Google Fonts : @import CSS → <link> dans le <head>

TDstyles.css Layout.astro

La police Golos Text était chargée via @import dans TDstyles.css. Le navigateur ne peut découvrir cet import qu'après avoir parsé le CSS, créant une chaîne bloquante. Déplacé en <link rel="stylesheet"> dans le <head> avec deux preconnect sur fonts.googleapis.com et fonts.gstatic.com.

PERF

willChange sorti de la boucle de scroll

GlobalIndex.js

panel.style.willChange = "transform" était appliqué à chaque event scroll sur chaque panneau de projet. Déplacé à l'initialisation : exécuté une seule fois après la sélection des éléments.

PERF

Cache de getLoop() — élimination du reflow forcé à 60 fps

skills.js

getLoop() accédait à track.offsetWidth à chaque frame d'animation, forçant un recalcul de layout synchrone 60 fois par seconde. Remplacé par un cache cachedLoop mis à jour via computeLoop() uniquement à l'init et au resize (ResizeObserver).

PERF

Cache de trackWidth — élimination du reflow forcé dans le loader

js/loader.js

track.offsetWidth était lu à l'intérieur de la fonction render() appelée à chaque frame RAF du loader (environ 90 frames sur 1500 ms). Chaque lecture de offsetWidth force un recalcul de layout synchrone. Extrait en variable trackWidth initialisée une seule fois avant la boucle d'animation.

FIX

Suppression de dat.gui du import map

Layout.astro

dat.gui était déclaré dans l'import map Three.js mais jamais importé dans le code. Supprimé avec le preconnect unpkg.com devenu inutile.

FIX

Suppression de export const normalize (dead code)

menu.js

Une fonction normalize était exportée en tête du fichier mais jamais consommée : le script étant chargé via <script src>, ses exports ne sont pas accessibles à l'extérieur.

FIX

Corrections TypeScript — paramètres implicitement any

components/competences_card.astro components/projetscrol.astro pages/competences.astro pages/projets.astro

19 erreurs TypeScript liées à des paramètres sans annotation de type (implicit any) et à des tableaux initialisés en never[]. Ajout d'annotations explicites : any[], (v: any), (record: any, field: string). Remplacement de .filter(Boolean) par un type predicate .filter((x): x is T => x !== null) pour corriger le narrowing de type.

FIX

Correction TypeScript — dataset sur Element

pages/index.astro

document.querySelector retourne Element | null. La propriété .dataset n'existe que sur HTMLElement. Correction en utilisant querySelector<HTMLElement>() pour inférer le bon type et éviter les erreurs à la compilation.

FIX

Installation @types/nodemailer

pages/api/contact.ts package.json

Nodemailer v8 ne fournit pas de déclarations TypeScript intégrées. Installation du paquet @types/nodemailer en devDependency pour résoudre l'erreur « Could not find a declaration file for module 'nodemailer' ».

NEW

Page détail projet /projets/[id]

pages/projets/[id].astro

Page de détail dynamique SSR par ID PocketBase. Hero avec fond flou du premier mockup en arrière-plan + overlay gradient. Galerie adaptive : 1 image pleine largeur, 2 côte à côte, 3 avec grande image + 2 vignettes. Layout deux colonnes (description + cards collaborateurs / sidebar sticky technologies + lien). Collaborateur expand PocketBase avec avatar photo ou initiales, nom, lien profil. Redirection /404 si ID inconnu.

NEW

Cards projets cliquables — stretched link

pages/projets/index.astro

Chaque card de la grille /projets navigue vers /projets/[id] via un <a> en position absolute inset-0 z-0 (stretched link). Les liens internes (tags technologies, bouton Voir en ligne) passent en relative z-10 pour rester accessibles au-dessus de l'overlay.

FIX

Mockup champ Multiple — extraction de la première image

pages/projets/index.astro components/projetscrol.astro

Le champ mockup est passé en Multiple dans PocketBase (tableau de noms de fichiers). L'ancien code passait le tableau entier à pb.files.getURL(), générant une URL invalide. Correction : extraction du premier élément via asArray(p.mockup)[0] dans les cards et helper firstImg() dans le carousel.

NEW

Nouveau modèle 3D — saxophone + refonte de l'éclairage

js/TDscript.js public/models/MonModel.glb

Remplacement du modèle GLB par un saxophone. Auto-fit Box3 pour centrer et scaler automatiquement tout nouveau modèle quelle que soit sa taille native. Refonte de l'éclairage en 6 sources : ambiance chaude, key light blanc-crème haut-gauche, front fill, contre-jour rimlight, fill bleu froid, accent pavillon ambré. Tore principal bleu → rouge au scroll conservé ; ajout de 2 tori secondaires (incliné milieu corps + petit vertical près du pavillon) avec contra-rotation indépendante dans la boucle RAF.

NEW

Page /devlog — journal des versions

pages/devlog.astro

Historique des releases du portfolio, listant fonctionnalités et correctifs appliqués par version.

NEW

Page 404 personnalisée avec animation Three.js

pages/404.astro js/404script.js

Page d'erreur 404 dans le style du site avec canvas Three.js (tori flottants + bloom), wave effect et fade-in CSS. Gérée par Netlify via le routage SSR Astro.

V1.0
Release 23 février 2026

Lancement initial

14 feat

Première version publique du portfolio. Socle complet avec scène 3D, jeu Snake, canvas physique, filtres, formulaire de contact et SEO.

FEAT

Scène 3D — Three.js + Unreal Bloom

js/TDscript.js

Modèle GLB chargé via GLTFLoader avec post-processing Unreal Bloom. Tore animé emissive. Lumières multiples (spot, fill, rim). Animation de scroll GSAP ScrollTrigger (rotation, position, couleur). Pause sur onglet caché et canvas hors écran via IntersectionObserver.

FEAT

Jeu Snake intégré

pages/snake.astro js/snake.js

Jeu Snake complet jouable depuis /snake. Les compétences chargées depuis PocketBase constituent les collectibles de la partie.

FEAT

Canvas bulles compétences — physique + drag

js/skills.js

Canvas physique avec logos de compétences en bulles. Collisions, rebonds, drag pointer (PC + mobile via Pointer Events), propulsion au clic. Pause sur onglet caché.

FEAT

Stack scroll projets (défilement horizontal par scroll vertical)

components/projetscrol.astro js/GlobalIndex.js

Les 3 derniers projets défilent horizontalement, pilotés par le scroll vertical via un spacer sticky. Transition fluide par translate3d.

FEAT

Transitions organiques SVG animées

js/GlobalIndex.js

Deux chemins SVG (ink-path, ink-path-2) animés avec mouvement sinusoïdal par points de contrôle. Fallback statique si prefers-reduced-motion activé.

FEAT

Loader animé — logo P.M.L + barre de progression

components/loader.astro js/loader.js

Préchargeur avec animation séquentielle du logo (lettres P, M, L), barre de progression avec spark, horloge Europe/Paris en temps réel, et phases d'ease-out.

FEAT

Header adaptatif glass / blanc (IntersectionObserver)

components/Header.astro js/menu.js

Header fixe détectant automatiquement la section visible pour basculer entre mode glass (fond sombre) et mode blanc (fond clair). Menu mobile fullscreen avec stagger CSS et gestion du focus (inert, aria-expanded).

FEAT

Carousel compétences — auto-scroll, drag et flèches

js/skills.js

Carousel infini auto-scroll avec pause hover, navigation par flèches, drag pointer et wheel vertical → horizontal. Delta-time pour vitesse constante.

FEAT

Wave effect lettre par lettre

js/TDscript.js styles/TDstyles.css

Effet de vague par lettre au survol des titres .wave-auto. Animation CSS waveLetter avec délai staggeré par span.

FEAT

Typed.js — hero animé

pages/index.astro

Rotation animée des rôles dans le hero (créateur web, UI/UX designer, full-stack, jeux vidéo) via Typed.js avec smartBackspace.

FEAT

Filtre + autocomplete compétences

js/filtre.js

Filtrage client par catégorie et niveau. Autocomplete avec highlight sur les noms. Pré-calcul des données à l'init. Lecture des paramètres URL (?search=, ?tech=). Toggle Voir plus / moins par mot.

FEAT

Formulaire de contact — API route Astro + Nodemailer

pages/api/contact.ts components/formulaire_contacte.astro

Formulaire avec validation front, envoi via API route Astro et Nodemailer. Feedback visuel sur l'état d'envoi.

FEAT

SEO complet — Open Graph, Twitter Cards, canonical

layouts/Layout.astro

Balises title, description, canonical, og:*, twitter:* dans le layout global. noIndex configurable par page. Sitemap automatique via @astrojs/sitemap.

FEAT

Pages légales — Mentions légales & Confidentialité

pages/mentionlega.astro pages/confidentialite.astro

Pages /mentionlega et /confidentialite conformes RGPD : responsable du traitement, données collectées, droits, hébergement.

Assistant Portfolio

Posez vos questions sur Pierre

P
Bonjour ! 👋 Je suis l'assistant de Pierre. Posez-moi vos questions sur son parcours, ses compétences ou ses projets !