# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## ⚠️ Direction du projet — Migration vers Laravel

Le projet est en cours de **réécriture complète depuis Next.js vers Laravel**. L'application Next.js actuelle (documentée ci-dessous) sert de **référence fonctionnelle/visuelle** ; la nouvelle base sera construite en Laravel.

**Stack cible (décisions arrêtées) :**
- **Framework** : **Laravel 12** (PHP 8.2+).
- **Base de données** : **MySQL 8** (MariaDB 10.6+ compatible).
- **Backend + Frontend** : Laravel en **Blade full-stack** + **Livewire 3** + **Alpine.js** (pas de SPA séparée).
- **CSS** : **Tailwind CSS** (via Vite) — voir tokens dans [DESIGN.md](DESIGN.md).
- **Backoffice / Admin** : **Filament v3** (CRUD, gestion média, settings, dashboards).
- **Stockage des CV** : **Cloudflare R2** (S3-compatible) via le driver `s3` natif de Laravel — bucket **privé**, accès par **URLs signées temporaires** uniquement. Basculable (B2/AWS) via `.env` seul.
- **E-mails** : SMTP configuré dans `.env`. **En développement local, l'envoi passe par [Mailpit](http://localhost:8025)** (SMTP `127.0.0.1:1025`, `MAIL_MAILER=smtp`) qui **capture** tous les mails sans les envoyer réellement — les consulter sur http://localhost:8025. En production : vrai serveur SMTP. Les **destinataires** (contact, CV, newsletter) sont paramétrables dans le backoffice (table `settings`).
- **Anti-spam / anti-robot** : **Cloudflare Turnstile** (gratuit, RGPD-friendly) + **honeypot** sur les formulaires contact et dépôt de CV.

**Nouvelles fonctionnalités demandées (au-delà du site actuel) :**
1. **Témoignages** gérés depuis le backoffice (CRUD Filament) — remplace les données GraphQL/statiques.
2. **Carrousel de logos clients** sur la page d'accueil : logos uploadés depuis le backoffice ; l'upload **recadre/normalise automatiquement** chaque logo à une **dimension uniforme** (via Spatie Media Library conversions ou Intervention Image) ; défilement type marquee.
3. **Newsletter** : enregistre les inscriptions/messages en base **et** envoie une notification par e-mail aux destinataires paramétrés dans le backoffice.
4. **Dépôt de CV** : les fichiers (pdf, word…) sont stockés sur **R2 privé** (jamais en local Laravel, jamais exposés publiquement) + notification e-mail.
5. **Actualités (News)** : publication depuis le backoffice via un **éditeur WYSIWYG riche** (Filament RichEditor/TipTap : médias, tableaux, liens…), brouillon/publié, SEO ; rendu HTML purifié côté public.
6. **Cookies / RGPD** : bandeau de consentement front (Accepter/Refuser/Personnaliser), catégories (nécessaires/analytics/marketing), choix journalisé ; le tracking analytics dépend du consentement.
7. **Statistiques visiteurs** (backoffice) : middleware de tracking (IP, **pays/ville via GeoIP**, date/heure, pages, referrer, device, **parcours de session**), tableau de bord Filament (graphes, top pages/pays, visites récentes, export), conditionné au consentement cookies.
8. **Protection anti-robot** : **Cloudflare Turnstile** + **honeypot** + rate-limiting sur les formulaires **Contact** et **Dépôt de CV** (et idéalement newsletter) — validation côté serveur du token avant traitement.
9. **Certificats de formation** (Phase 11) : sessions de formation (titre, dates début/fin, formateurs, e-mail) + participants (entreprise, fonction, téléphone) gérés en backoffice ; choix d'un **modèle de certificat** ; génération **PDF paysage A4 haute résolution** par participant (dompdf) avec **QR code** pointant vers la page publique de **vérification d'authenticité** `/certificats/verifier/{code}` (code unique non devinable, révocable).
10. **Rapport de formation & intermédiaire de session** (Phase 12) : l'**e-mail du participant devient obligatoire** ; la session porte les coordonnées de l'**intermédiaire** (nom, prénom, fonction, téléphone, e-mail) avec option « participe à la formation » qui l'ajoute **automatiquement** aux participants (sans doublon) ; après la formation, envoi à l'intermédiaire d'un **rapport de formation** — e-mail **HTML soigné** (charte navy/vert/gold) + **PDF complet en pièce jointe** (dompdf, portrait A4 : synthèse, objectifs, programme dispensé, assiduité, évaluations à chaud et des acquis, certificats délivrés, recommandations, annexe participants), rédigé/pré-rempli en backoffice et envoyé via une action Filament (uniquement session terminée + e-mail intermédiaire renseigné).

> Le contenu réel vs. placeholder des données actuelles est analysé dans [STRUCTURE.md](STRUCTURE.md) §8 ; les menus/sous-menus ajustés en §9.

📄 Voir [STRUCTURE.md](STRUCTURE.md) pour l'arborescence/menus du site actuel, [PLAN.md](PLAN.md) pour le plan d'exécution de la migration, et [DESIGN.md](DESIGN.md) pour la direction artistique (palette navy/vert/gold, typographie, composants, refonte page d'accueil).

---

## Commands

> ⚠️ L'application Next.js de référence a été **déplacée dans [old/](old/)** (avec `package.json`, `server.js`, `jsconfig.json`, `.env.example`, `.prettierrc`). Les commandes ci-dessous se lancent **depuis `old/`** (`cd old`). La racine est désormais réservée à la nouvelle base **Laravel** (voir [PLAN.md](PLAN.md)).

```bash
npm run dev      # Start dev server via custom server.js on http://localhost:3000
npm run build    # next build
npm run start    # Production: NODE_ENV=production node server.js
```

There is **no lint or test script** and no test framework configured. Formatting is enforced by Prettier (`.prettierrc`: single quotes, semicolons, 2-space, 80 print width, no trailing commas) — run `npx prettier` manually if needed.

On Windows, `npm run start` will fail as written because it uses the bash-style `NODE_ENV=production` prefix; use `npx cross-env` or set the env var separately in PowerShell.

## Architecture

This is a **Next.js 12 Pages Router** site (a French-language HR consulting template, "HR CONSULTING & CO"). It does **not** use the App Router. A custom `server.js` wraps Next's request handler; both dev and prod run through it.

### Two distinct data sources

1. **Headless WordPress via GraphQL** — Apollo Client (`old/src/services/appolo-config.js`) points at `http://api.hrconsultingco.ci/graphql`. Dynamic content (news posts, formations) is fetched in `getServerSideProps` using GraphQL queries defined in `old/src/services/*.service.js`. WordPress post nodes are normalized through the `mapResultsSsr` / `mapResults` / `mapResultSsr` helpers, which flatten `featuredImage.node.sourceUrl`, strip HTML to plain text via `innertext`, and parse dates. **When adding a page that reads CMS content, follow this pattern: define a `gql` query in a service file, call `appoloClient.query` in `getServerSideProps`, and map the result before passing as props.**

2. **Static local data** — Marketing content (services, instructors, testimonials, statistics, home/welcome services) lives as plain JS arrays in `old/src/data/*.js` and is imported directly into components/pages. No fetching.

### API routes (`old/src/pages/api/`)

Form submissions are handled server-side and dispatched as **email via Nodemailer SMTP** (`nodemailer.config.js` builds the transporter from `SMTP_*` env vars). Each form route (`contact`, `send-resume`, `order-formation`, `custom-formation`) follows the same shape:
- Validate required fields with the shared `checkEntries(body, keys)` helper (returns first missing key name).
- Build an HTML body from a template in `old/src/pages/api/views/*.template.js`.
- Call `transporter.sendMail(...)`.

`send-resume` additionally attaches an uploaded file (`body.file`, base64) and raises the body-parser `sizeLimit` to `8mb` via the exported route `config`.

The newsletter route (`subscribe.js`) is the exception — it POSTs to an external WordPress newsletter REST API via `axios` using `NEWSLETTER_*` env vars, not email.

### Client-side form flow

Frontend forms call API routes and wrap the request in `old/src/utils/handleHttpRequest.js`, which drives `react-toastify` toast states (pending/success/error) and extracts the server error message. `react-toastify` is mounted once globally in `_app.js`.

### Global shell

`old/src/pages/_app.js` wraps every page in `ApolloProvider` → `ChakraProvider` (theme from `old/src/styles/theme.js`) and renders the persistent `Head`, `Navbar`, `Footer`, `Loading`, and `ToastContainer`. `react-reveal` is configured globally with `ssrFadeout: true` for scroll animations used throughout the components.

### UI

Chakra UI **v1.8.8** (note: not v2 — APIs differ) with Emotion. Components live in `old/src/components/<Name>/index.jsx`, one folder per component.

## Conventions

- **Path aliases** (from `jsconfig.json`) — always prefer these over relative imports: `@components/*`, `@assets/*`, `@data/*`, `@utils/*`, `@public/*`, `@styles/*`, `@services/*`, `@views/*` (→ `old/src/pages/api/views/*`).
- User-facing copy is **French**; keep new UI text in French to match.
- Secrets come from `.env` (see `.env.example` for `SMTP_*` and `NEWSLETTER_*` keys); API route files call `require('dotenv').config()`.
- **Commenter toutes les fonctions** : chaque fonction/méthode (JS comme PHP/Laravel) doit être précédée d'un commentaire décrivant son rôle, ses paramètres et sa valeur de retour (docblock PHPDoc/JSDoc). Côté Laravel, documenter aussi les méthodes des contrôleurs, services, jobs et composants Livewire.
- **Commits** : ne **pas** apparaître en co-auteur sur GitHub — ne jamais ajouter de ligne `Co-Authored-By:` (ni mention d'assistant IA) dans les messages de commit.
