Retour aux projets
PubliéPersonnel

Portfolio

Un portfolio personnel pensé comme un produit, pas comme une vitrine.

Publié mars 20267 min de lecture

🎯 Le Contexte & L'Objectif

J'avais un ancien portfolio. Il faisait le travail, mais il ne me ressemblait plus. Ni dans la forme, ni dans le fond, ni dans le niveau technique qu'il reflétait. En parallèle, un cours à l'ESIGELEC m'avait amené à construire le backend d'un portfolio avec trois bases de données — PostgreSQL, MongoDB et Neo4j. Le résultat était techniquement intéressant mais largement surdimensionné pour un site vitrine. J'ai préféré repartir de zéro avec une approche différente : un frontend moderne, performant, et surtout personnel.

L'objectif n'était pas seulement de lister des compétences et des projets. Je voulais un site qui donne envie d'être exploré, qui raconte quelque chose de moi au-delà du code. C'est pour cette raison que le portfolio intègre une section voyages avec un globe interactif — parce que je suis convaincu qu'un recruteur ou un collaborateur potentiel a autant besoin de savoir qui je suis que ce que je sais faire. Le portfolio devait aussi être l'occasion de découvrir des technologies que je n'avais jamais touchées : Next.js, Framer Motion, MDX, le rendu 3D dans le navigateur.


🛠️ Ma Contribution & Mon Rôle

Projet entièrement solo — du premier composant au déploiement Vercel, en passant par chaque ligne de code et chaque choix de design.

  • Architecture technique : mise en place d'un projet Next.js 16 avec App Router, TypeScript strict, et un système de contenu basé sur des fichiers MDX parsés via gray-matter et rendus avec next-mdx-remote. Validation de toutes les données (projets, compétences, expériences, voyages) par des schémas Zod pour garantir la cohérence à la compilation.
  • Internationalisation : support bilingue français/anglais via next-intl, avec des fichiers de contenu séparés par langue (.fr.mdx / .en.mdx) fusionnés automatiquement par le content loader. Chaque texte de l'interface est traduit via des fichiers de messages JSON.
  • Visualisations 3D : intégration de react-globe.gl pour le globe interactif de la section voyages (marqueurs animés, panneau latéral avec boarding pass) et de react-force-graph-3d pour le graphe de compétences (nœuds colorés par catégorie, interactions au survol, fond étoilé).
  • Animations & UI : animations d'entrée et de scroll orchestrées avec Framer Motion, composants de révélation réutilisables (ScrollReveal, AnimatedText), transitions de page fluides.
  • Contenu éditorial : rédaction de chaque page projet en MDX, avec un soin particulier apporté à la structure narrative — contexte, contribution, stack, défis techniques, résultats, apprentissages.

💻 Stack Technique

  • Framework : Next.js 16 avec App Router et React 19 — le combo permet le rendu statique (SSG) pour les pages de contenu, le routing dynamique par locale, et la génération de métadonnées SEO automatique par page.
  • Langage : TypeScript en mode strict — chaque structure de données est typée et validée par Zod, ce qui élimine une catégorie entière de bugs liés aux données mal formatées.
  • Styling : Tailwind CSS 4 avec un système de design tokens personnalisé (couleurs, typographies Fraunces, Inter et Space Mono). Pas de bibliothèque de composants externe — chaque composant est construit sur mesure.
  • Contenu : fichiers MDX avec frontmatter YAML, parsés par gray-matter et rendus par next-mdx-remote avec coloration syntaxique via rehype-pretty-code et Shiki.
  • 3D & Visualisations : react-globe.gl (basé sur Three.js / globe.gl) pour le globe terrestre, react-force-graph-3d pour le graphe de compétences en réseau.
  • Animations : Framer Motion pour les animations déclaratives — entrées au scroll, transitions entre pages, effets de survol.
  • Internationalisation : next-intl avec routing par préfixe de locale (/fr/, /en/), messages JSON et contenu MDX séparé par langue.
  • Déploiement : Vercel — déploiement automatique à chaque push, prévisualisation par branche, CDN global.

⚙️ Architecture & Défis Techniques

Un pipeline de contenu typé de bout en bout

Le contenu du site — projets, compétences, expériences, formations, certifications, voyages — est entièrement stocké dans des fichiers JSON et MDX dans le dossier /content/. Plutôt que de faire confiance au format des données à l'exécution, chaque fichier est parsé et validé par un schéma Zod dédié au moment du build. Si un champ manque, si une date est mal formatée ou si une compétence référencée n'existe pas, le build échoue avec un message explicite. Ce choix ralentit légèrement l'itération en développement, mais il a évité des dizaines de bugs silencieux — un texte manquant en anglais, une image de couverture inexistante, un slug dupliqué.

Le système de contenu gère aussi la fusion automatique des fichiers bilingues : projet.fr.mdx et projet.en.mdx sont parsés indépendamment puis fusionnés en un objet unique avec des champs bilingues ({ fr: "...", en: "..." }), ce qui simplifie considérablement le rendu côté composant.

Le globe interactif : Three.js dans un contexte SSR

Intégrer une visualisation 3D basée sur Three.js dans une application Next.js en App Router n'est pas trivial. Le principal obstacle est que Three.js nécessite un accès au DOM et à WebGL, ce qui est incompatible avec le rendu côté serveur. La solution passe par un import dynamique avec ssr: false et un composant wrapper client ("use client"). Le globe affiche des marqueurs animés pour chaque voyage, avec un panneau latéral qui s'ouvre au clic sous forme de boarding pass — un choix de design qui renforce l'identité personnelle du site.

Le graphe de compétences en réseau 3D

La page Skills présente les compétences sous forme d'un graphe 3D en force-directed, où chaque nœud représente une compétence et les liens traduisent les relations entre technologies. Les nœuds sont colorés par catégorie (frontend, backend, data, DevOps, etc.) et s'illuminent au survol avec un effet de glow. Le graphe propose trois niveaux de tri — par catégorie, par compétence, ou en affichant l'ensemble — ce qui permet de naviguer dans un réseau dense sans se perdre. La topologie du graphe (nœuds et liens) est générée par un script TypeScript dédié qui produit un fichier skills-graph.json, découplé des données métier de skills.json. Ce découplage permet de modifier les relations entre compétences sans toucher aux données affichées ailleurs sur le site.

Animations et performance perceptive

Le site utilise abondamment Framer Motion pour les animations d'entrée et de scroll, mais chaque animation a été pensée pour améliorer la perception de fluidité sans pénaliser les performances. Les composants ScrollReveal utilisent l'Intersection Observer pour ne déclencher les animations que lorsque l'élément entre dans le viewport, et les animations sont désactivées pour les utilisateurs ayant activé prefers-reduced-motion. Les transitions entre pages sont gérées par un PageWrapper qui orchestre les animations d'entrée et de sortie via AnimatePresence.


🚀 Résultats & Impact

  • Un site qui me ressemble : au-delà de la vitrine technique, le portfolio raconte une histoire — mes projets, mes voyages, mon parcours. La section voyages avec le globe 3D est systématiquement le premier élément que les gens remarquent et commentent.
  • Découverte technologique : première expérience avec Next.js, Framer Motion, MDX et le rendu 3D dans le navigateur. Chacune de ces technologies est passée du statut d'inconnue à celui d'outil maîtrisé en un mois.
  • Bilingue et maintenable : l'architecture de contenu permet d'ajouter un nouveau projet en quelques minutes — créer un fichier MDX, remplir le frontmatter, et le site se met à jour automatiquement. Le support bilingue est natif, pas greffé après coup.
  • Performance : rendu statique pour les pages de contenu, chargement dynamique des composants 3D lourds, optimisation des images via le composant next/image, et CDN Vercel pour la distribution globale.

💡 Ce que j'ai appris

Ce projet a été un condensé d'apprentissages en un mois. Next.js et son App Router m'ont fait comprendre la puissance du rendu hybride — pouvoir mélanger pages statiques et composants client interactifs dans une même application, avec un routing par locale intégré. Framer Motion m'a appris qu'une animation bien dosée transforme l'expérience utilisateur : ce n'est pas du superflu, c'est ce qui fait la différence entre un site qui "fonctionne" et un site qui donne envie de rester.

La partie la plus formatrice a été la gestion du contenu. Construire un pipeline MDX avec validation Zod, fusion bilingue et rendu personnalisé m'a donné une compréhension fine de la frontière entre données et présentation — et de l'importance de typer ses données le plus tôt possible dans la chaîne.