Files
portfolio/CLAUDE.md
Johan LEROY 859683b624 prod setup
2026-05-04 12:05:08 +02:00

5.5 KiB

CLAUDE.md — Portfolio johanleroy.fr

Site vitrine personnel en Astro 6 hybrid (SSG public + SSR admin), identité Cyberpunk Dark / Free Party tekno.

Contexte rapide

  • Utilisateur : Johan Leroy — dev fullstack + DJ tekno
  • Objectif : remplacer l'ancien portfolio Angular 19 (~/WebstormProjects/Portfolio_angular/) par une version moderne, animée, maintenable sans recompilation
  • Déploiement : Plesk Node.js sur johanleroy.fr (upload FTP manuel, pas de CI)
  • Commande /context johanleroy charge tout le contexte projet

Stack

  • Astro 6 hybrid (output: 'static' + @astrojs/node standalone)
  • React 19 (îlots interactifs uniquement)
  • Tailwind CSS 4 + design system custom
  • Framer Motion + Lenis (animations)
  • Zod (schémas de contenu)
  • jose + bcryptjs (auth admin)
  • @iconify-icon/react (icônes simple-icons + lucide)

Points critiques à connaître

Content

Tout le contenu du site est dans data/content/*.json (7 fichiers, gitignored). Chaque fichier est validé par un schéma Zod dans src/content/schemas/. Édition possible via /admin ou directement en éditant le JSON. Au premier run, les JSON sont copiés depuis public/content/*.json (seeds versionnés en repo) si data/content/ est vide — voir src/lib/content.ts.

Persistance prod (Plesk)

Le déploiement (FTP manuel) réécrit dist/ et public/ à chaque upload. C'est pour ça que tout le contenu dynamique est dans data/ (gitignored, jamais touché par l'upload, conservé entre déploiements) :

  • data/content/*.json — JSON édités via /admin
  • data/uploads/img/{folder}/* — images uploadées
  • data/uploads/assets/{folder}/* — PDF (CV)

Les fichiers de data/uploads/ sont servis via la route /api/files/[...path] (Astro SSR) — donc les chemins en JSON sont du type /api/files/img/pp/foo.png ou /api/files/assets/cv.pdf.

Init prod (premier déploiement post-refonte) :

  1. Sur le serveur Plesk, créer data/{content,uploads/img,uploads/assets} avec les bons droits (utilisateur Node).
  2. Copier les seeds : cp public/content/*.json data/content/ et cp -r public/img/* data/uploads/img/ et cp public/assets/cv.pdf data/uploads/assets/.
  3. Lors des uploads FTP suivants, ne jamais sélectionner data/ — uploader uniquement dist/, public/, package.json, package-lock.json.
  4. Tester un upload via /admin → vérifier que le fichier arrive bien dans data/uploads/... et que /api/files/... le sert.

Sécurité : /api/files/[...path].ts protège contre le path traversal (résolu via resolve() + check préfixe). Les uploads passent par /api/upload qui est JWT-gated dans src/middleware.ts.

Admin

Protégé par mot de passe bcrypt + JWT cookie httpOnly 7j. Middleware dans src/middleware.ts. Routes /admin/* et /api/* ont export const prerender = false.

Env vars (.env)

ADMIN_PASSWORD_HASH=$2b$12$...
ADMIN_JWT_SECRET=...
PORT=3100

Générer : npm run hash:password -- 'monMotDePasse' (⚠️ guillemets simples toujours — les ! et $ sont interprétés par bash sinon).

Important : src/lib/auth.ts lit à la fois import.meta.env (dev Vite) ET process.env (prod Node standalone). Ne pas casser ce merge.

Design

  • Palette : --color-bg #0A0A0F, --color-cyan #00F0FF, --color-acid #C6FF00, --color-magenta #FF2A6D, --color-red #FF0040
  • Typos : Inter (body), Space Grotesk (display), JetBrains Mono (code), Bebas Neue (stencil signature)
  • Dark only — pas de light mode
  • Ligne éditoriale : pro avant tout (nav FR, URLs grand public), free party = déco (stickers, BPM, LED, stencil)

Animations

Tous les composants animés doivent respecter prefers-reduced-motion. Les 14 blocs livrés sont listés dans la memory animations-blocks.md.

Feedback important

  • Pas de 3D Hero pour l'instant (supprimé — on y reviendra)
  • Pas de curseur custom (supprimé)
  • Nav FR standards (/projets, /experience, /formations)
  • Sons off par défaut, togglables via header
  • Boot sequence au 1er load uniquement (sessionStorage)
  • Responsive : fallback grid pour le Crate horizontal pinned sur mobile

Commandes utiles

  • npm run dev — port 3100
  • npm run build — check + build prod
  • npm run checkastro check
  • npm run hash:password -- 'mdp' — génère bcrypt + JWT secret

Conventions de code

  • Tous les îlots React dans src/components/islands/
  • Composants Astro pure (sans JS) directement dans src/components/
  • Les schémas Zod sont la source de vérité pour les types — ne pas écrire de type custom à la main pour le contenu
  • astro check doit passer à 0 erreur avant commit
  • Utiliser className en TSX et class en Astro (erreur Astro commune)

Workflow d'édition

  1. Lire docs/README.md puis docs/01-analyse-et-plan.md + docs/02-moodboard-freeparty.md pour la direction artistique
  2. Pour un changement de contenu → éditer data/content/*.json (ou via /admin). Les seeds dans public/content/*.json ne sont utilisés qu'au premier run (bootstrap)
  3. Pour un changement de design → modifier src/styles/global.css + composants
  4. Pour un changement structurel → modifier schéma Zod d'abord, puis composant, puis JSON

Ne PAS faire sans demander

  • Ne pas changer la stack (Astro + React + Tailwind 4 est verrouillé)
  • Ne pas réintroduire de 3D hero sans validation
  • Ne pas retirer le respect prefers-reduced-motion
  • Ne pas commiter .env (vérifier .gitignore)
  • Ne pas toucher à dist/ (généré par build)