# Easebook — Instructions Claude Code

## Environnement DDEV

Toutes les commandes doivent être exécutées via DDEV (projet `easebook`, PHP 8.3, MariaDB 10.11). Ne jamais utiliser les commandes hôte directement.

| Action | Commande |
|---|---|
| Composer (projet) | `ddev composer <cmd>` |
| WP-CLI | `ddev wp <cmd>` |
| Composer (thème) | `ddev exec composer --working-dir=web/app/themes/ebook-viewer <cmd>` |
| npm (thème) | `ddev exec npm --prefix web/app/themes/ebook-viewer <cmd>` |
| Pint (dirty) | `ddev exec vendor/bin/pint --dirty` |
| Pint (test) | `ddev exec vendor/bin/pint --test` |
| Pint (fichier) | `ddev exec vendor/bin/pint <fichier>` |
| MySQL | `ddev mysql` |
| Restart | `ddev restart` |

## Architecture Bedrock

```
config/              → Configuration WordPress (application.php, environments/)
packages/            → Plugins premium copiés au déploiement (cf. système Composer ci-dessous)
  advanced-custom-fields-pro/
  real3d-flipbook/
  real3d-flipbook-page-editor/
web/
  app/
    mu-plugins/      → bedrock-autoloader, bedrock-disallow-indexing + configs SecuPress
    plugins/         → Plugins WordPress (géré par Composer — gitignored)
    themes/ebook-viewer/  → Thème Sage 11 (voir section suivante)
    uploads/         → Médias (shared dir en deploy)
    languages/       → Fichiers de traduction
  wp/                → WordPress core (géré par Composer, ne pas modifier)
vendor/              → Dépendances Composer projet
composer.json        → Dépendances projet ACTIVES (= copie de composer-prod.json)
composer-full.json   → Dépendances complètes (local dev, inclut les 3 premium)
composer-prod.json   → Dépendances pour la prod/CI (sans les 3 premium)
deploy.php           → Configuration Deployer v7
pint.json            → Configuration Laravel Pint (preset PER)
```

## Système Composer dual (spécifique easebook)

Easebook maintient **deux composer files** parce que 3 plugins premium ne peuvent pas être installés via Composer en CI/prod (limitations Envato + ACF Pro auth) :

- **`composer-full.json`** — usage local : inclut `wpengine/advanced-custom-fields-pro`, `envato/real3d-flipbook`, `envato/real3d-flipbook-page-editor` + le plugin `szepeviktor/composer-envato`
- **`composer-prod.json`** — usage CI/prod : sans ces 4 entrées
- **`composer.json`** — fichier ACTIF, doit toujours être en mode prod pour le commit/CI

Les 3 plugins premium sont versionnés dans `packages/` et copiés sur le serveur par Deployer (`deploy.php` tâche `deploy:plugins:manual` lignes 80-85).

**Toute mise à jour Composer passe par `/update-premium`** qui orchestre le swap full ↔ packages/ ↔ prod automatiquement. Voir `.claude/skills/update-premium/SKILL.md`.

## Structure du thème Sage

Le thème se trouve dans `web/app/themes/ebook-viewer/`. C'est un thème **Sage 11** sur **Roots/Acorn v5** (framework Laravel-like pour WordPress).

```
app/                          → Code applicatif (namespace App\)
  setup.php                   → Support thème, tailles images, menus, Vite assets
  filters.php                 → Filtres WP (archives, images, srcset, reCAPTCHA, SMTP)
  admin.php                   → Pages options ACF, colonnes admin, filtres champs ACF
  ajax.php                    → Handlers AJAX (action save_contact, préfixe kh_ajax_*)
  mailing.php                 → Envoi emails via Symfony Mailer (templates MJML/HTML/TXT)
  helpers.php                 → Fonctions utilitaires (slugify, validation email, formats tel)
  cpt.php                     → Custom Post Types et taxonomies (PostTypes lib)
  Providers/
    ThemeServiceProvider.php  → étend SageServiceProvider
  View/
    Composers/                → View Composers : App, Header, Footer, Post, Ebook
    Components/               → Blade Components (à étoffer au fil du dev)

resources/
  css/
    app.css                   → Tailwind v4 (`@import "tailwindcss" theme(static)`)
    editor.css                → Styles éditeur de blocs
  js/
    app.js                    → Point d'entrée frontend (studiometa/js-toolkit)
    editor.js                 → Scripts éditeur
  views/                      → Templates Blade
    layouts/app.blade.php
    partials/                 → content, content-page, content-single, page-header
    sections/                 → header, footer (Blade)
    index.blade.php, single.blade.php, page.blade.php, page-ebook.blade.php, 404.blade.php

public/build/                 → Output Vite (assets compilés + theme.json généré)
theme.json                    → Source theme.json (compilée par wordpressThemeJson plugin Vite)
vite.config.js                → Vite v6 + @tailwindcss/vite + laravel-vite-plugin + @roots/vite-plugin
```

### Stack frontend
- **Sage 11** + **Acorn v5** (Service Providers, View Composers, Blade Components)
- **Blade** pour les templates
- **Tailwind CSS v4** en config CSS-first (`resources/css/app.css`) — pas de SCSS
- **Vite v6** pour le build et HMR (port DDEV 8173)
- **@studiometa/js-toolkit v3** pour les composants JS — pas de jQuery
- **theme.json** est généré dynamiquement depuis Tailwind via `wordpressThemeJson()` plugin

## Plugins installés

Standards (gérés par Composer, présents dans les deux composer files) :
- `acf-extended`, `better-search-replace`, `classic-editor`, `compressx`, `disable-comments`, `secupress`, `svg-support`, `wp-health`

Premium (copiés depuis `packages/` au déploiement, présents uniquement dans `composer-full.json` localement) :
- `advanced-custom-fields-pro` (ACF Pro)
- `real3d-flipbook` (Real3D Flipbook — cœur métier ebook viewer)
- `real3d-flipbook-page-editor`

Mu-plugins (`web/app/mu-plugins/`) : `bedrock-autoloader.php`, `bedrock-disallow-indexing/`, configs SecuPress (générées). Pas de mu-plugin custom projet.

## Custom Post Types

| CPT / Taxonomy | Statut | Usage |
|---|---|---|
| `contact_request` | défini dans `app/cpt.php:13-57`, **registration commentée** | Soumissions formulaire contact (champs ACF : lastname, firstname, email, phone, zipcode, city, subject, message) |
| `hidden_attachment_taxonomy` | enregistré (`app/cpt.php:60-75`) | Taxonomy interne pour cacher des attachments du média admin |

Enregistrements via la lib `PostTypes\PostType` / `PostTypes\Taxonomy` (`jjgrainger/posttypes`).

## Conventions WordPress

### Préfixe
Toutes les fonctions globales utilisent le préfixe `kh_` (cohérent avec les autres projets de l'org) :
```php
function kh_ajax_save_contact() { ... }
function kh_send_email_notification_contact_admin($post_id) { ... }
function kh_get_all_sizes_images($id) { ... }
```

Les fichiers PHP sont dans le namespace `App\` (PSR-4 via Composer).

### Hooks AJAX
Pattern observé dans `app/ajax.php` :
```php
add_action('wp_ajax_save_contact', 'kh_ajax_save_contact');
add_action('wp_ajax_nopriv_save_contact', 'kh_ajax_save_contact');
```
Note : l'action WP est `save_contact` (sans préfixe), le handler est `kh_ajax_save_contact`. Toujours vérifier le nonce (`wp_verify_nonce` avec nonce name `save_contact`).

### Validation reCAPTCHA
Filtre custom : `apply_filters('kh_verify_captcha', ...)` (cf. `filters.php:152-157`).

### Emails
Symfony Mailer v7 dans `app/mailing.php`. Templates MJML dans `resources/emails/` (compilés en HTML + fallback TXT).

## Variables d'environnement

`.env` contient (cf. README pour les détails) :
- DB : `DB_HOST`, `DB_NAME`, `DB_USER`, `DB_PASSWORD`, `DB_PREFIX`
- Salts WP : `AUTH_KEY`/`SALT`, `LOGGED_IN_KEY`/`SALT`, `NONCE_KEY`/`SALT`, `SECURE_AUTH_KEY`/`SALT`
- Config : `WP_ENV`, `WP_HOME`, `WP_SITEURL`, `WP_POST_REVISIONS`
- Premium : `ENVATO_TOKEN` (pour `szepeviktor/composer-envato`)

## Workflows

### Mise à jour
Lancer `/update` (qui invoque `/update-premium` à l'étape Composer, puis traductions, composer thème, npm thème, build, Pint).
Pour ne refaire QUE le cycle premium : `/update-premium` directement.
Pour cibler : `/update composer | translations | theme`.

### Avant commit
`/finalize` (Pint + build + check `composer.json` = `composer-prod.json`).

### Commit
`/commit` (commit conventionnel, scopes easebook).

### Revue de code
`/review` (lance l'agent reviewer en subagent isolé).

### Déploiement
`/deploy` pour la checklist (le déploiement réel passe par GitLab CI).

## Déploiement

- **CI/CD** : GitLab CI (`.gitlab-ci.yml`)
- **Outil** : Deployer v7.5.12 (`deploy.php`)
- **Image CI** : `php:8.3-cli` + Node 20 (NVM)
- **Repo** : `git@gitlab.com:keroth-vl/easebook.git`
- **Hébergement** : OVH shared (`ftp.cluster028.hosting.ovh.net`)
- **Staging** : auto sur push `main` — path `/home/easebou/preprod`
- **Production** : manuel (approbation GitLab) — path `/home/easebou/www`
- **User remote** : `easebou`
- **PHP serveur** : `/usr/local/php8.3/bin/php`
- **Releases gardées** : 3
- **Tâches deploy custom** (`deploy.php`) :
  1. `deploy:composer:auth` (lignes 46-65) — décode credentials ACF base64 dans `auth.json`
  2. `deploy:vendors` (lignes 68-77) — `composer install` projet + thème
  3. `deploy:plugins:manual` (lignes 80-85) — copie `packages/{3 premium}/` vers `release/web/app/plugins/`
  4. `deploy:copy_assets` (lignes 88-91) — upload `web/app/themes/ebook-viewer/public/` (build Vite)
  5. `deploy:fix_permissions` (lignes 94-101) — chown `easebou:users` + group write
  6. `cleanup:auth` (lignes 104-107) — supprime `auth.json` post-install
- **Secrets CI** : `SSH_PRIVATE_KEY`, `SSH_KNOWN_HOSTS`, `ACF_USERNAME`, `ACF_PASSWORD` (encodés base64 et passés à `dep deploy`)
- **Build Vite** : fait localement EN CI avant déploiement (`npm install && npm run build` dans la before_script)

## Style de code

- **PHP** : Laravel Pint, preset PER (`pint.json`)
- **CSS** : Tailwind utility-first, pas de SCSS
- **JS** : pattern `Base` de `@studiometa/js-toolkit`, vanilla, pas de jQuery
- **Blade** : escaping `{{ }}` par défaut, raw `{!! !!}` justifié

## Workflow AI

1. **Planifier** — comprendre le contexte, vérifier les fichiers voisins
2. **Implémenter** — respecter les conventions existantes (kh_ prefix, namespace `App\`, Sage patterns)
3. **`/finalize`** — Pint + build frontend + check composer prod
4. **`/commit`** — commit conventionnel avec scope approprié

### Règles
- Toujours vérifier les fichiers voisins avant de créer/modifier un composant
- **Ne JAMAIS éditer `composer.json` à la main** — passer par `/update-premium`
- Ne jamais éditer manuellement les exports `acfe-php/` (gérés par ACF Extended)
- Préfixe `kh_` sur toutes les fonctions globales
- Ne pas modifier `web/wp/` ni les fichiers SecuPress dans `web/app/mu-plugins/`
- Le dossier `packages/` est versionné — un commit qui modifie `packages/` est attendu après `/update-premium`
- Le dossier `web/app/plugins/` est gitignored — son contenu local ne doit jamais apparaître dans les commits
- Build Vite local (`ddev exec npm --prefix web/app/themes/ebook-viewer run build`) requis avant tout commit qui touche `resources/`
