# __PROJECT_TITLE__

Repo client **WP Reactor** (framework headless WordPress) — monorepo léger « 2 mondes ».

```
apps/webapp/                 coque TanStack Start (deps @wp-reactor/* publiées)
apps/wordpress/theme-__PROJECT_NAME__/   thème ENFANT (branding + blocs propres)
apps/wordpress/Dockerfile    image WP = base framework + thème enfant overlayé
docker-compose.dev.yml       stack dev local (WordPress + DB + Redis)
.github/workflows/deploy.yml appelle les workflows réutilisables du framework
wp-reactor.config.json       config gen-block (namespace, chemins)
pages/master-page.ts         vitrine page-as-code : tous les blocs, toutes les variantes
.claude/skills/gen-block/    skill agent : Figma/capture → schéma → bloc généré
docs/environment.md          où va chaque variable (local / GitHub / Coolify)
docs/traefik-labels.md       labels Traefik à coller dans Coolify
```

## Prérequis

Les packages `@wp-reactor/*` sont sur **GitHub Packages** (privé, org `wp-reactor`).
Authentifie-toi avant `pnpm install` :

```bash
export NODE_AUTH_TOKEN=insert_token_here
```

## Dev rapide (Docker)

WordPress (image base framework) + DB + Redis en conteneurs, webapp sur l'hôte.

```bash
# L'image WordPress base est privée (GHCR) → login une fois :
echo <PAT read:packages> | docker login ghcr.io -u <user> --password-stdin

pnpm install
cp .env.local.example .env      # ajuste si besoin

pnpm docker:up                  # WordPress + DB + Redis
pnpm docker:bootstrap           # install WP + plugins GraphQL + thème enfant
pnpm dev                        # webapp sur http://localhost:3000
```

WordPress (admin / GraphQL) : `http://localhost:8890` (cf `WP_PORT`).
Arrêt : `pnpm docker:down` — remise à zéro (volumes) : `pnpm docker:reset`.

> Détail des variables d'environnement : **[`docs/environment.md`](docs/environment.md)**.

## Mettre à jour depuis le framework

Le repo est généré une fois, puis suit le framework avec une seule commande — sans
toucher ta coque `src/` ni ton branding :

```bash
npx create-wp-reactor@latest update
pnpm install     # le lockfile a bougé
git diff         # relis avant de committer
```

Elle fait deux choses :

- **Infra & skills** re-poussés depuis le template : `docker-compose.dev.yml`, `docs/`,
  Dockerfiles, workflows CI, `.claude/skills/`. Un skill que tu as ajouté toi-même
  n'est jamais touché.
- **Deps `@wp-reactor/*` bumpées** vers les dernières versions publiées, dans tous les
  `package.json` du repo (racine, webapp, thème). Seule la chaîne de version bouge :
  le diff ne montre que les bumps.

> Garde le `@latest` : les versions sont figées dans le CLI au moment de sa
> publication, donc un `create-wp-reactor` plus ancien bumpera vers des versions
> plus anciennes.

Restent hors périmètre — à ton rythme : ta coque `src/`, ton thème, et tes deps hors
`@wp-reactor/*` (react, vite, turbo…). L'**image WordPress** (`wordpress-base`) se met
à jour, elle, au rebuild.

## Générer un bloc

```bash
pnpm gen:block                       # mode interactif (create / update / delete)
pnpm gen:block apps/webapp/src/blocks/schemas/<slug>.json   # écrit thème enfant + renderer webapp + registre
```

Le schéma généré est renommé `<slug>.generated.json` — c'est l'état du bloc, et
c'est ce qui sépare les listes « create » et « update » du mode interactif.

Chaque renderer est déclaré en `React.lazy` (un chunk JS par bloc, chargé à la
demande). Pour un bloc au-dessus de la ligne de flottaison (héros → LCP),
génère-le avec `--eager` : import statique, jamais derrière un `Suspense`.

Depuis un agent (Claude Code), le skill **`gen-block`** livré dans
`.claude/skills/` fait le chemin complet : lien Figma ou capture → schéma inféré
→ génération → renderer à implémenter → variantes ajoutées à la master page. Il est
re-poussé par `npx create-wp-reactor@latest update` avec le reste de l'infra.

## La master page

`pages/master-page.ts` décrit une page **en TypeScript** (une suite de `block(...)`)
et la pousse vers WordPress. Elle sert de vitrine : **un bloc par variante utile** —
chaque valeur de `Select`, `Toggle` dans les deux sens, avec et sans les repeaters
optionnels. C'est le seul endroit qui rend toute la bibliothèque pour de vrai, donc
le seul endroit où on voit qu'un bloc casse.

```bash
pnpm push:page pages/master-page.ts --dry-run   # aperçu du markup, 100 % local
pnpm push:page pages/master-page.ts --create    # crée la page si le slug est absent
pnpm push:page pages/master-page.ts             # met à jour la page existante
```

> ⚠️ Le push **écrase** le `post_content` de la page cible : les éditions faites
> dans Gutenberg sur cette page sont perdues. Le `--dry-run` ne touche à rien (ni
> réseau ni credentials) — c'est celui à lancer par défaut.

Le push a besoin de `WP_USER` + `WP_APP_PASSWORD` dans le `.env` (Application
Password WordPress) ; l'URL retombe sur `VITE_WORDPRESS_URL`. Comme la page est en
`status: "publish"` avec un slug explicite, pense à la masquer avant la mise en
production.

## Déploiement

Push sur `main` → `.github/workflows/deploy.yml` build+push les images webapp & WordPress
sur GHCR via les workflows réutilisables du framework, puis déclenche Coolify.

- **Procédure ordonnée + Cloudflare** : **[`docs/deploy.md`](docs/deploy.md)**
- **Variables / secrets** (GitHub Actions + Coolify) : **[`docs/environment.md`](docs/environment.md)**
- **Labels Traefik** à coller dans l'UI Coolify : **[`docs/traefik-labels.md`](docs/traefik-labels.md)**
