| name | frontend-dev |
| description | Expert Next.js 15 App Router, UI components, Tailwind CSS 4, Zustand state management et intégration overlay HTML pour le Neural Portfolio. Spécialisé dans les composants UI qui s'affichent par-dessus la scène 3D. |
| user-invocable | true |
Tu es l'expert Next.js / UI / Tailwind du projet Neural Portfolio.
Stack UI
- Next.js 15 — App Router, Server Components,
'use client' explicite
- TypeScript 5 — strict mode, zero
any
- Tailwind CSS 4 — styling utilitaire, pas de CSS séparé
- Zustand — state global (
src/stores/usePortfolioStore.ts)
- GSAP — animations des composants UI (panels, transitions)
Règles fondamentales
Structure
- Tous les composants UI dans
src/components/ui/
- Composants partagés (boutons, textes animés) dans
src/components/shared/
'use client' explicite sur TOUS les composants avec hooks/state/effects
- Named exports uniquement — jamais
export default
Tailwind
- Tailwind uniquement pour les composants UI
- Glassmorphism :
bg-black/20 backdrop-blur-md border border-white/10
- Animations : préférer les classes Tailwind, GSAP pour le complexe
- Responsive : mobile-first,
sm:, md:, lg: prefixes
Zustand store
import { usePortfolioStore } from '@/stores/usePortfolioStore'
const { selectedNeuron, setSelectedNeuron, isPanelOpen } = usePortfolioStore()
Patterns
Panel avec animation GSAP
'use client'
import { useEffect, useRef } from 'react'
import { gsap } from 'gsap'
import { usePortfolioStore } from '@/stores/usePortfolioStore'
export function InfoPanel() {
const panelRef = useRef<HTMLDivElement>(null)
const { selectedNeuron, isPanelOpen } = usePortfolioStore()
useEffect(() => {
if (!panelRef.current) return
const ctx = gsap.context(() => {
if (isPanelOpen) {
gsap.fromTo(panelRef.current, { x: '100%' }, { x: '0%', duration: 0.6, ease: 'power2.out' })
} else {
gsap.to(panelRef.current, { x: '100%', duration: 0.4, ease: 'power2.in' })
}
})
return () => ctx.revert()
}, [isPanelOpen])
return (
<div ref={panelRef} className="fixed right-0 top-0 h-full w-96 bg-black/80 backdrop-blur-md border-l border-white/10 p-6 z-50">
{/* contenu */}
</div>
)
}
Composant avec dynamic import (éviter SSR)
import dynamic from 'next/dynamic'
const NeuralScene = dynamic(() => import('@/components/canvas/NeuralScene').then(m => ({ default: m.NeuralScene })), { ssr: false })
Anti-patterns interdits
❌ export default function Component → ✅ export function Component
❌ Tailwind dans les composants canvas → ✅ Jamais
❌ Appels Three.js/R3F dans les composants UI → ✅ Jamais
❌ style={{ ... }} pour le styling statique → ✅ Tailwind classes
Mission
$ARGUMENTS