# Portfolio — Johan Leroy

Site vitrine personnel en **Astro 6 hybrid** (SSG public + SSR admin), déployé sur Plesk Node.js.

🎧 Dev le jour, DJ la nuit — stack cyberpunk dark, contenu éditable sans recompilation.

---

## Stack

- **Astro 6** (`output: 'static'` + adapter Node standalone — hybrid via `prerender: false` sur `/admin/*` et `/api/*`)
- **React 19** (îlots interactifs)
- **Tailwind CSS 4** + custom design system cyberpunk
- **Framer Motion** + **GSAP** + **Lenis** (animations)
- **@react-three/fiber** (hero 3D disco ball)
- **Zod** (validation schémas de contenu)
- **jose** + **bcryptjs** (auth admin JWT cookie)

---

## Développement

```bash
npm install
npm run dev
```

→ http://localhost:3100

## Édition du contenu

Tout le contenu éditable est dans `public/content/*.json` :

| Fichier | Rôle |
|---|---|
| `profile.json` | Profil, photo, CTA hero, réseaux sociaux |
| `skills.json` | Compétences techniques (primary + secondary) |
| `experiences.json` | Parcours pro + compétences techniques & transverses |
| `formations.json` | Diplômes et formations |
| `projects.json` | Portfolio de projets |
| `interests.json` | Centres d'intérêt |
| `site.json` | Meta SEO + flags features |

Tu peux éditer :
- **Via `/admin`** (interface web protégée par mot de passe) — recommandé en prod
- **Manuellement** en éditant les JSON et en rechargeant la page

**Aucune recompilation n'est nécessaire** : les fichiers sont servis statiquement côté site public, et relus au runtime côté admin.

---

## Admin

### Configuration initiale

1. Générer un hash de mot de passe :
   ```bash
   npm run hash:password -- monMotDePasse
   ```
2. Copier les deux lignes générées (`ADMIN_PASSWORD_HASH` et `ADMIN_JWT_SECRET`) dans un fichier `.env` (local) ou dans les variables d'environnement Plesk (prod).

### Accès

→ http://localhost:3100/admin (ou https://johanleroy.fr/admin en prod)

Login via mot de passe, cookie httpOnly 7 jours.

---

## Déploiement Plesk Node.js

### Variables d'environnement à définir sur Plesk

| Variable | Valeur |
|---|---|
| `ADMIN_PASSWORD_HASH` | hash bcrypt généré |
| `ADMIN_JWT_SECRET` | secret JWT aléatoire |
| `PORT` | `3100` (ou ce que Plesk impose) |
| `HOST` | `0.0.0.0` |
| `NODE_ENV` | `production` |

### Paramètres Plesk Node.js

- **Node.js version** : 22+ (24.x OK)
- **Application root** : `/httpdocs/johanleroy`
- **Document root Apache** : `/httpdocs/johanleroy/dist/client` (Apache sert les statiques buildés, le reste passe en proxy vers Node)
- **Application startup file** : `dist/server/entry.mjs`
- **Application URL** : https://johanleroy.fr (SSL Let's Encrypt obligatoire pour les cookies admin)

### Déploiement manuel

1. **Build local** : `npm run build` (vérifier que `dist/server/entry.mjs` est généré)
2. **Upload FTP/SFTP** vers le répertoire de l'application Plesk (ex : `/httpdocs/johanleroy/`) :
   - `dist/` (écrase l'existant)
   - `public/` (écrase l'existant)
   - `package.json`
   - `package-lock.json`
3. **Plesk → Node.js → NPM install** (à faire si `package.json` a changé)
4. **Plesk → Node.js → Restart App** pour recharger le nouveau bundle

**Ne JAMAIS écraser** : `data/`, `.env`, `node_modules/` côté serveur.

---

## Structure

```
src/
├── components/
│   ├── Header.astro, Footer.astro, SEO.astro
│   ├── ProjectCard.astro
│   └── islands/         # composants React hydratés
│       ├── Hero3D.tsx
│       ├── RolesMorph.tsx
│       ├── Reveal.tsx
│       ├── SkillCard.tsx
│       ├── SmoothScroll.tsx
│       └── CustomCursor.tsx
├── content/schemas/     # schémas Zod (typages + validation)
├── lib/
│   ├── auth.ts          # JWT cookie admin
│   └── content.ts       # lecture/écriture JSON
├── layouts/BaseLayout.astro
├── middleware.ts        # protection routes /admin et /api
├── pages/
│   ├── index.astro
│   ├── formations.astro
│   ├── experience.astro
│   ├── projets.astro
│   ├── 404.astro
│   ├── admin/
│   │   ├── login.astro
│   │   ├── index.astro
│   │   └── edit/[section].astro
│   └── api/
│       ├── auth/login.ts, logout.ts
│       ├── content/[section].ts
│       └── upload.ts
└── styles/global.css

public/
├── content/*.json       # données éditables
├── img/                 # images (icônes, entreprises, projets, photos)
└── assets/cv.pdf
```

---

## Direction artistique

**Cyberpunk Dark** — noir profond + cyan/magenta néon.

- Palette : `#0A0A0F / #00F0FF / #FF2A6D / #D1F7FF`
- Typographies : Space Grotesk (display), Inter (body), JetBrains Mono (mono)
- Effets : disco ball 3D, smooth scroll Lenis, curseur custom, glow néon, scanlines, glitch

---

## Licence

© 2026 Johan Leroy.
