create-wp-reactor
v0.12.0
Published
Scaffolder de repo client mince WP Reactor : émet apps/webapp (depuis le starter) + thème enfant + CI réutilisable + docker. Usage : npm create wp-reactor <nom>.
Readme
create-wp-reactor
Scaffolder de repo client WP Reactor — un framework headless WordPress (kernel TanStack Start + modules commerce/auth/editorial + générateur de blocs).
npm create wp-reactor@latest mon-client
# ou : pnpm create wp-reactor mon-client
# ou : npx create-wp-reactor mon-clientGénère un monorepo client « 2 mondes » :
apps/webapp/ coque TanStack Start (deps @wp-reactor/* publiées)
apps/wordpress/theme-<nom>/ thème ENFANT (branding + blocs propres)
docker-compose.dev.yml stack dev local (WordPress + DB + Redis)
.github/workflows/deploy.yml CI réutilisable du framework (GHCR → Coolify)
docs/ deploy.md, environment.md, traefik-labels.mdOptions
create-wp-reactor <nom> [--dir <path>] [--namespace <ns>]
create-wp-reactor update [--dir <path>]
create-wp-reactor --provision [<config>] # défaut : .env.provision--dir: dossier cible (défaut :<nom>dans le cwd).--namespace: namespace des blocs Gutenberg (défaut :<nom>sans tirets).
--provision
Scaffolde puis monte l'infra complète, là où il fallait jusqu'ici enchaîner une dizaine d'étapes manuelles dans l'UI Coolify, l'UI GitHub et Cloudflare.
Une commande, un fichier :
npx create-wp-reactor@latest --provisionAu premier appel, le fichier de configuration n'existe pas : la commande le
génère (.env.provision, en chmod 600), liste ce qu'il reste à remplir,
et attend.
✓ .env.provision créé (chmod 600).
Remplis-le — il contient des jetons, ne le committe pas.
Manquant : WPR_PROJECT_NAME, WPR_DOMAIN, WPR_GH_OWNER, WPR_COOLIFY_SERVER,
GITHUB_TOKEN, COOLIFY_URL, COOLIFY_TOKEN, NODE_AUTH_TOKEN
Remplis .env.provision, puis Entrée pour revérifier — q pour quitter.Tu ouvres le fichier dans un autre terminal, tu le remplis, tu appuies sur Entrée : il est relu et revalidé. Une fois complet, un récapitulatif s'affiche et la confirmation est demandée avant le moindre appel — le provisioning crée de l'infra facturée par des appels non idempotents, sans rollback.
Projet Acme Deco (slug acme-deco)
Front https://acme.example.com
WordPress https://wp.acme.example.com
Repo acme-org/acme-deco (privé)
Serveur prod-1
DNS Cloudflare, zone abc123
Jetons GITHUB_TOKEN ✓ COOLIFY_TOKEN ✓ NODE_AUTH_TOKEN ✓ CF_API_TOKEN ✓
Crée de l'infra réelle, sans rollback automatique. Continuer ? [y/N]Aucune valeur de jeton n'est jamais affichée — seulement présent/absent.
| Étape | Ce qui est créé |
|---|---|
| 1 | Repo client généré, .env de dev local écrit avec un vrai SESSION_SECRET |
| 2 | Repo GitHub, variables VITE_* et secrets Actions |
| 3 | Enregistrements DNS Cloudflare (front proxifié, WordPress DNS-only) |
| 4 | Projet Coolify, MariaDB et Redis managés |
| 5 | Ressource Docker Compose WordPress + son environnement |
| 6 | Application webapp (labels Traefik, health check, purge post-deploy) |
| 7 | Secrets COOLIFY_*_UUID, puis premier push — qui déclenche la CI |
L'ordre dénoue un cycle : Coolify a besoin d'images sur GHCR, ces images viennent
de la CI, et la CI a besoin des UUID Coolify. Les ressources sont donc créées
sans être déployées, et c'est le push final qui lance la CI, laquelle construit
les images puis appelle elle-même /api/v1/deploy. Pas de polling, pas de
seconde commande.
Tous les secrets sont générés (SESSION_SECRET, mots de passe DB/Redis/admin
WordPress) et ne sont écrits que dans l'environnement Coolify — jamais dans le
repo. Le mot de passe admin est affiché une fois, en fin de commande.
Le fichier de configuration
Format .env. Il porte tout — paramètres et jetons — et le template généré
documente chaque clé.
| Clé | Rôle |
|---|---|
| WPR_PROJECT_NAME | nom lisible du client (slugifié pour les identifiants) |
| WPR_DOMAIN | domaine du front, sans schéma |
| WPR_GH_OWNER | propriétaire GitHub (compte perso ou organisation) |
| WPR_COOLIFY_SERVER | nom affiché ou UUID du serveur Coolify |
| WPR_REPO_NAME, WPR_WP_HOST, WPR_NAMESPACE, WPR_DIR | optionnels |
| GITHUB_TOKEN | repo + write:packages |
| COOLIFY_URL / COOLIFY_TOKEN | instance et jeton write + deploy |
| NODE_AUTH_TOKEN | PAT read:packages, utilisé par la CI pour les @wp-reactor/* |
| CF_API_TOKEN / CF_ZONE_ID | optionnels par paire, Zone:DNS:Edit — DNS et purge du cache |
Les jetons gardent leur nom conventionnel, sans préfixe : un
export GITHUB_TOKEN=… déjà présent dans ton shell fonctionne tel quel. Les
paramètres sont préfixés WPR_ pour ne pas entrer en collision avec des noms
génériques — DOMAIN traîne dans beaucoup d'environnements.
Précédence : flag CLI > variable du shell > fichier. Ça permet de surcharger une valeur ponctuellement sans éditer le fichier.
Le fichier ne concerne que le provisioning — rien à voir avec l'environnement runtime des applications, qui vit dans Coolify.
Autres options
--dry-run imprime le plan d'appels sans en émettre aucun — pas même les
GET. C'est la porte de revue avant un run réel, puisque ces appels créent de
l'infra et ne sont pas idempotents. En contrepartie, un dry-run ne valide aucun
jeton : il ne contacte aucun serveur. Il saute aussi la confirmation, n'ayant
rien à créer.
--yes saute la confirmation, pour la CI. Sur une configuration incomplète,
la commande échoue en listant les clés manquantes au lieu d'attendre.
Hors terminal interactif (stdin redirigé, CI), la commande ne bloque jamais : elle échoue en expliquant quoi faire.
Forme à flags, toujours supportée — utile pour scripter sans fichier :
GITHUB_TOKEN=… COOLIFY_URL=… COOLIFY_TOKEN=… NODE_AUTH_TOKEN=… \
npx create-wp-reactor@latest "Acme" --provision --yes \
--domain acme.example.com --gh-owner acme-org --coolify-server prod-1Options associées : --repo-name (défaut : le slug), --wp-host (défaut :
wp.<domaine>), --dir, --namespace.
Reste manuel : docker login ghcr.io en root sur l'hôte Coolify (l'API
n'expose pas les credentials de registry) et la Cache Rule Cloudflare. La
commande le rappelle en fin de course.
update
Rafraîchit un repo client déjà généré sur deux axes, sans toucher la coque
src/ ni le branding :
cd mon-client
npx create-wp-reactor@latest update # `@latest` : cf. « quelles versions ? »
pnpm install # le lockfile a bougé
git diff # relire avant de committer- Infra & skills — re-pousse depuis le template embarqué :
docker-compose.dev.yml,docs/, Dockerfiles,.github/workflows/(dossier entier, reusable vendorisébuild-and-deploy-image.ymlcompris), et.claude/skills/(le skill agentgen-blocksuit les versions du CLI qu'il documente). Un skill ou un workflow propre au client posé à côté n'est jamais touché :updateécrit, il ne purge pas. - Deps
@wp-reactor/*— réécrit chaque range en^<version>dans tous lespackage.jsondu repo (racine,apps/webapp, thème enfant, packages ajoutés par le client). Le remplacement est chirurgical — seule la chaîne de version bouge, l'indentation et l'ordre des clés sont préservés, donc le diff ne montre que les bumps.
L'identité du projet (nom, namespace) est relue depuis package.json +
wp-reactor.config.json, donc les tokens du template sont re-rendus avec ton
branding. Hors d'un repo client, la commande échoue au lieu d'écrire.
Quelles versions ? Celles embarquées dans le CLI exécuté (manifeste
versions.generated.ts, figé au build) — aucun appel réseau. D'où
create-wp-reactor@latest : un npx qui recycle une version cachée bumpera vers
les versions de cette version-là.
Ce que update ne touche pas :
| Hors périmètre | Pourquoi |
|---|---|
| apps/webapp/src/, thème enfant | c'est ton code — la coque est un point de départ, pas un fichier managé |
| deps hors @wp-reactor/* (react, vite, turbo…) | les bumper pourrait casser ton app ; à faire à ton rythme |
| package.json (scripts, nom), wp-reactor.config.json, .env.example, .gitignore, .npmrc | personnalisés par le client |
| ranges workspace: / link: / file: / portal: | liens locaux (dogfood monorepo) — les réécrire casserait le lien |
Une dep @wp-reactor/* inconnue du manifeste (package renommé ou retiré) est
laissée telle quelle et signalée en ⚠ — jamais bumpée dans le vide.
Après génération
Les packages runtime @wp-reactor/* sont sur GitHub Packages (privé) →
authentifie-toi avant pnpm install :
echo "//npm.pkg.github.com/:_authToken=<PAT read:packages>" >> ~/.npmrc
cd mon-client && pnpm install && pnpm devVoir le README.md et docs/ du repo généré pour le dev Docker et le déploiement.
