# Covalba — Site headless (Next.js + WordPress)

Site de production de **Covalba** (peinture réflective Cool Roof). Architecture **headless** :
un back-office **WordPress** (contenu via ACF + WPGraphQL) alimente un front **Next.js**
statique-first déployé sur Vercel. Les formulaires de génération de leads sont connectés à
**HubSpot**. Multilingue **FR / EN / ES** via Polylang.

```
┌────────────────────┐      GraphQL       ┌─────────────────────┐
│  WordPress (Docker) │ ─────────────────▶ │   Next.js (Vercel)  │
│  ACF + WPGraphQL    │                    │   App Router, ISR   │
│  Polylang FR/EN/ES  │ ◀──── revalidate ──│   /api/revalidate   │
│  /srv/covalba-wp    │   (webhook par tag)│                     │
└────────────────────┘                    └──────────┬──────────┘
     VPS srv1255941 · 72.61.87.116                    │ Forms Submission API
                                                      ▼
                                              ┌───────────────┐
                                              │    HubSpot    │
                                              └───────────────┘
```

---

## Stack

| Tier | Techno |
|------|--------|
| **Front** | Next.js 16 (App Router, Turbopack), React 19, TypeScript, Tailwind + shadcn/ui, GSAP |
| **Back** | WordPress 6.8 (PHP 8.3), ACF PRO + ACF Extended, WPGraphQL + WPGraphQL for ACF, Polylang |
| **Données** | MariaDB 11, Redis 7 (object cache) |
| **Leads** | HubSpot Forms Submission API + Google Tag Manager |
| **Infra** | Front : Vercel · Back : Docker Compose sur VPS |

---

## Prérequis

- **Node.js 20+** et npm
- **Docker** + Docker Compose (pour WordPress en local ou sur le VPS)
- Une licence **ACF PRO** (variable `ACF_PRO_LICENSE`)
- Un compte **HubSpot** (Private App token) pour les formulaires

---

## 1. Front Next.js

```bash
npm install
cp .env.example .env.local      # puis renseigner WORDPRESS_GRAPHQL_URL au minimum
npm run dev                     # http://localhost:3000
```

Sans `WORDPRESS_GRAPHQL_URL`, le front retombe sur ses fallbacks statiques
(`isWpConfigured`, `src/lib/wp/client.ts`) — pratique pour bosser l'UI sans WordPress.

| Script | Rôle |
|--------|------|
| `npm run dev` | Dev server (`next dev`, host/port lus depuis `.env.local`) |
| `npm run build` | Build de production |
| `npm start` | Serveur de production |
| `npm run lint` | ESLint |
| `npm test` | Tests unitaires (Vitest) |

### Variables d'environnement (front)

| Variable | Requis | Description |
|----------|--------|-------------|
| `WORDPRESS_GRAPHQL_URL` | ✅ | Endpoint WPGraphQL (ex. `https://covalba-admin.paf-studio.dev/graphql`) |
| `REVALIDATE_SECRET` | ✅ | Secret partagé avec WP pour l'ISR on-demand (`openssl rand -hex 32`) |
| `WP_I18N_ENABLED` | – | `true` pour activer i18n Polylang (FR/EN/ES). Défaut `false` |
| `WP_FETCH_CONCURRENCY` | – | Plafond de requêtes GraphQL parallèles au build. Défaut `8` |
| `NEXT_PUBLIC_WP_MEDIA_URL` | – | Origine de remplacement des médias WP (CDN/proxy) |
| `WP_SECTIONS_TYPE_PREFIX` | – | Préfixe des types GraphQL des layouts ACF. Défaut `SectionsSections` |
| `NEXT_PUBLIC_GTM_ID` | – | Conteneur Google Tag Manager |
| `HUBSPOT_PRIVATE_APP_TOKEN` | – | Token Private App — **serveur uniquement** (scripts de setup) |
| `NEXT_PUBLIC_HUBSPOT_PORTAL_ID` | ✅* | Portal HubSpot (*pour les formulaires) |
| `NEXT_PUBLIC_HUBSPOT_FORM_GUID_*` | ✅* | GUIDs des 5 formulaires (diagnostic, contact, applicateur, livreblanc, estimation) |

---

## 2. Back WordPress (headless)

Tout est dans `wordpress/`. Le code métier vit dans les **mu-plugins** `covalba-core`
et `covalba-chatbot` (chargés automatiquement, pas d'activation requise).

### Démarrage (Docker)

```bash
cd wordpress
cp .env.example .env            # renseigner DB_PASSWORD, COVALBA_REVALIDATE_SECRET, ACF_PRO_LICENSE…
docker compose up -d            # db (MariaDB) + wordpress + redis
# WP-CLI à la demande (profil "tools") :
docker compose run --rm wpcli wp core version
```

WordPress écoute sur `127.0.0.1:8080` (à exposer en HTTPS via un reverse-proxy).

### Plugins requis (non vendorisés)

ACF PRO · ACF Extended · WPGraphQL · WPGraphQL for ACF (v2) · Polylang · Redis Object Cache · Safe SVG.

### Modèle de contenu

**`wordpress/SCHEMA.md` est la source de vérité** (CPT, taxonomies, field groups, layouts).
Le mu-plugin déclare 5 CPT (`produit`, `toiture`, `industrie`, `reference`, `lieu`), 2 taxonomies
(`secteur`, `type_support`), un flexible content `sections` (~21 layouts) et l'exposition GraphQL
camelCase. L'i18n (`language` / `translations`) est exposé par `inc/graphql-i18n.php`.

### Seed du contenu

```bash
# idempotent — 3 passes (posts → champs → traductions)
docker compose run --rm wpcli wp eval-file wp-content/seed/run.php
```

Le contenu localisé est dans `wordpress/seed/content/*.json` (+ `*.en.json`, `*.es.json`).

### Variables (`wordpress/.env`)

| Variable | Description |
|----------|-------------|
| `DB_PASSWORD`, `DB_ROOT_PASSWORD` | MariaDB |
| `COVALBA_REVALIDATE_SECRET` | = `REVALIDATE_SECRET` du front (revalidation ISR) |
| `COVALBA_FRONT_URLS` | URLs front autorisées (CORS + revalidation), séparées par virgules |
| `COVALBA_CHATBOT_APP_URL` | Origine publique du service chatbot (ex. `https://covalba-chatbot.vercel.app`) |
| `COVALBA_CHATBOT_ADMIN_TOKEN` | Secret partagé avec le service chatbot pour l'admin WP, les réglages, le dashboard et le récap IA |
| `ACF_PRO_LICENSE` | Licence ACF PRO |

---

## 3. HubSpot

Les 5 formulaires (diagnostic, contact, applicateur, livre blanc, estimation) postent côté
client vers l'**API Forms Submission** (`api.hsforms.com/.../{PORTAL_ID}/{FORM_GUID}`), avec
mapping des valeurs internes HubSpot. À chaque succès, un event est poussé dans `dataLayer`
(GTM) — voir `src/lib/hubspot.ts`, `src/lib/dataLayer.ts` et les schémas `src/lib/*Form.ts`.

Création/mise à jour idempotente des formulaires + propriétés (nécessite `HUBSPOT_PRIVATE_APP_TOKEN`) :

```bash
npm run hubspot:setup            # diagnostic
npm run hubspot:setup-contact
npm run hubspot:setup-applicateur
npm run hubspot:setup-lead-forms # livre blanc + estimation
```

Les scripts affichent les `PORTAL_ID` / `FORM_GUID` à reporter dans `.env.local`.

---

## 4. Déploiement

### Front → Vercel
Projet Vercel connecté à ce repo, branche de production `main`. Renseigner les variables
d'environnement (Production) côté Vercel, notamment `WORDPRESS_GRAPHQL_URL`, `REVALIDATE_SECRET`,
`WP_I18N_ENABLED`, et les `NEXT_PUBLIC_HUBSPOT_*`. Chaque merge sur `main` déclenche un déploiement.

### Revalidation ISR
WordPress notifie le front à chaque sauvegarde via `POST {front}/api/revalidate`
(header `x-revalidate-secret`), qui revalide les tags de cache concernés.

### Back → VPS (Docker)
Le `docker compose` de `wordpress/` tourne sur le VPS. Le **mu-plugin** est déployé en continu
par CI : à chaque merge sur `main` touchant `wordpress/mu-plugins/**`,
`.github/workflows/deploy-wp-muplugin.yml` synchronise le mu-plugin sur le VPS, vide le cache,
puis **vérifie le schéma GraphQL** (`scripts/wp/check-graphql-schema.sh` — échoue si un champ
attendu manque). Déploiement manuel garde-fou : `scripts/wp/deploy-mu-plugins.sh` (refuse de
déployer autre chose que `origin/main`).

> **Secrets GitHub Actions requis** : `COVALBA_WP_SSH_KEY`, `COVALBA_WP_HOST`, `COVALBA_WP_USER`.

**Accès VPS WordPress** : `covalba-admin.paf-studio.dev` → **`72.61.87.116`** (VPS Hostinger `srv1255941`, id `1255941`).
Stack Docker dans `/srv/covalba-wp` (`covalba-wp-wordpress-1` + `covalba-wp-db-1` MariaDB + `covalba-wp-redis-1`).

```bash
ssh root@72.61.87.116                       # clé dédiée : ~/.ssh/covalba_wp_ed25519
# WP-CLI (aucun wp-cli sur l'hôte → image jetable sur le réseau du projet) :
docker run --rm --network covalba-wp_default --volumes-from covalba-wp-wordpress-1 \
  -u 33:33 wordpress:cli wp <commande>
```

---

## Structure

```
app/                  Routes Next.js (App Router) — FR + /en + /es, API (revalidate, geo)
src/
  components/         Composants UI + blocks (rendu du contenu WP)
  views/              Vues de page
  lib/wp/             Client GraphQL, requêtes, i18n, fragments
  lib/                HubSpot, dataLayer, formulaires, SEO
  config/, data/      Routes i18n, données statiques
wordpress/
  mu-plugins/covalba-core/   CPT, taxonomies, ACF, GraphQL, Polylang, revalidation
  mu-plugins/covalba-chatbot/ Réglages Assistant IA, knowledge, emails rapport, dashboard, GraphQL widget
  seed/                      Moteur de seed + contenu JSON (FR/EN/ES)
  docker-compose.yml         MariaDB + WordPress + Redis + WP-CLI
  SCHEMA.md                  Contrat du modèle de contenu (source de vérité)
scripts/
  hubspot/            Setup idempotent des formulaires HubSpot
  wp/                 Déploiement mu-plugin + check schéma GraphQL
  wp-seed/            Génération des pages SEO locales (lieux)
.github/workflows/    CI (déploiement mu-plugin + check schéma)
```
