Jules Bulant · Voir en ligne
Portfolio Artistique — Nuxt 3 + Sanity CMS
Portfolio artistique moderne avec galerie interactive, modal viewer plein écran, navigation tactile mobile, et CMS headless pour gérer les œuvres.
Nuxt 3Sanity CMSTypeScriptCSSReact 19
- Année
- 2026
- Stack
- Nuxt 3 · Sanity CMS · TypeScript · CSS · React 19
- Type
- Réalisation
- Rôle
- Dev front + UX
Aperçu

Conception & réalisation
Problèmes rencontrés, décisions UX et livrables.
Problèmes identifiés
5 points- 1.Créer une expérience galerie immersive avec navigation fluide entre les œuvres
- 2.Gérer une architecture monorepo (site public + studio CMS privé)
- 3.Permettre une gestion simple des œuvres et expositions sans compétences techniques
- 4.Assurer une navigation tactile optimale sur mobile (swipe entre œuvres)
- 5.Optimiser le chargement d'images haute résolution (œuvres d'art)
Actions réalisées
5 livrables- 1.Modal viewer plein écran avec navigation clavier/swipe et préchargement
- 2.Monorepo organisé : site/ (Nuxt SSR) + studio/ (Sanity CMS)
- 3.Schémas Sanity typés : Paintings, Exhibitions, Profile avec images multiples
- 4.Swipe mobile natif avec détection de gestes et animations fluides
- 5.SSR Nuxt + lazy loading + images optimisées Sanity (hotspot, crop)
Code
typescriptModal viewer avec navigation et swipe mobile
1// Composables/useModal.ts - Gestion du modal avec navigation2 const currentIndex = ref(0);3 const paintings = ref<Painting[]>([]);45 function openModal(index: number) {6 currentIndex.value = index;7 document.body.style.overflow = 'hidden';89 // Précharger images adjacentes10 preloadAdjacentImages(index);11 }1213 function navigate(direction: 'prev' | 'next') {14 if (direction === 'prev' && currentIndex.value > 0) {15 currentIndex.value--;16 } else if (direction === 'next' && currentIndex.value < paintings.value.length - 1) {17 currentIndex.value++;18 }19 preloadAdjacentImages(currentIndex.value);20 }2122 // Support navigation clavier23 onMounted(() => {24 window.addEventListener('keydown', (e) => {25 if (e.key === 'ArrowLeft') navigate('prev');26 if (e.key === 'ArrowRight') navigate('next');27 if (e.key === 'Escape') closeModal();28 });29 });
Suite du parcours
Accéder aux autres projets ou me contacter.