# portfolio-maker (stack) Dépôt d'**orchestration** de l'environnement du générateur de portfolios PDF de Figures Libres. Il ne contient pas de code applicatif : il câble ensemble, via Docker Compose, l'app et le CMS Grav d'exemple qui lui sert de source de contenu. ## Trois dépôts, un environnement Ce dépôt attend deux autres checkouts **posés côte à côte** (chacun a son propre dépôt git et n'est pas versionné ici) : ``` portfolio-maker/ # CE dépôt (stack) ├── docker/grav/Dockerfile # Image PHP+Apache servant grav-reference/ ├── docker-compose.yml # Services grav-reference (8089) + generator (8091) ├── docker-compose.prod.yml # Surcouche déploiement (build Nitro + rsync prod) ├── generator/ ←──────── dépôt À PART : l'app Nuxt (Dockerfile inclus) = le livrable └── grav-reference/ ←──────── dépôt À PART : le vrai site Grav (~4,8 Go), monté :ro ``` - **`generator/`** — le générateur (Nuxt). Détails d'architecture : voir son propre `README.md` / `CLAUDE.md`. Poussé sur le gitea figureslibres.io. - **`grav-reference/`** — CMS Grav d'exemple, en **lecture seule** (monté `:ro`). C'est la source de contenu, **pas** l'app à développer. > ⚠️ Tout tourne dans Docker : Node, build Nuxt, Playwright/Chromium, Ghostscript, > ffmpeg, rsync — rien n'est installé sur l'hôte. > 📦 **Non versionné dans ce dépôt** : `generator/` et `grav-reference/` (dépôts > séparés, à cloner côte à côte), ainsi que `docs/` (PDF de référence + spec déjà > réalisée). Le `Dockerfile` de l'image Grav, lui, reste versionné dans `docker/grav/`. ## Lancer en dev ```bash docker compose up -d # grav-reference + generator ``` - Grav de référence : http://localhost:8089 - Générateur de portfolios : http://localhost:8091 — mot de passe partagé : `figureslibres` (variable `PORTFOLIO_PASSWORD`) Le générateur lit directement `grav-reference/user/pages/02.projets/` (mode DEV de `ContentSource`). Le bouton « Rafraîchir » relit le contenu local. Commandes utiles (toujours via le conteneur) : ```bash docker compose run --rm --no-deps generator npm install # dépendances docker compose exec generator npm run build # build de prod docker logs -f figureslibres-portfolio-generator # logs du dev server ``` ## Parcours utilisateur 1. Se connecter (mot de passe partagé) — on arrive sur la liste des **portfolios**. 2. Créer un **portfolio** : ajouter des projets via la modale « Ajouter un projet » (recherche plein texte, filtres catégorie/tag — seuls les projets publiés sont proposés). Chaque projet = **deux pages ou plus**, fidèles au gabarit `book_v3` (PDF de référence dans `docs/`, non versionné) : - une page **couverture** : bandeau 55 mm couleur de la catégorie (titre en fonte d'« utilité » — Playfair/Manifont/Avara —, pastille, présentation Syne 12/16 pt) + image de couverture (celle de la grille du CMS) ; - des pages **grille** : filet 5 mm, marges 8 mm, gouttières 3,8 mm, images **entières** (jamais tronquées) calées sur la grille — 8 dispositions au choix, présentées par icônes. Les vidéos ne sont pas sélectionnables. Couleur de bandeau et texte noir/blanc réglables (palette du gabarit + couleurs du site). Pages spéciales : couverture, sommaire, page libre. Aperçu WYSIWYG A3 paysage, sauvegarde automatique. 3. **Générer le PDF** (nom de fichier personnalisable) : rendu Playwright/Chromium au format **A3 paysage** (1190,55 × 841,89 pt, comme le gabarit), images redimensionnées à 2× leur taille d'affichage (sharp), post-traitement Ghostscript, métadonnées. Le contenu utilisé est **figé** (`data/frozen//`) : régénérer redonne le même PDF ; « Réactualiser depuis Grav » resynchronise volontairement. ## Déploiement (mode PROD) Le contenu est tiré de la prod par **rsync/SSH en lecture seule** vers `generator/data/content-cache/`, déclenché par le bouton « Rafraîchir ». ```bash # .env (non versionné) PORTFOLIO_PASSWORD=… SESSION_SECRET=… INTERNAL_TOKEN=… SYNC_REMOTE=user@prod:/chemin/vers/user/pages/02.projets/ SYNC_SSH_KEY_FILE=/chemin/local/vers/cle_privee docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d generator ``` ## Données Tout est sur disque dans `generator/data/` (sauvegarde = copie du dossier) : `portfolios/*.json` (compositions), `exports/*.pdf`, `frozen//` (snapshots), `cache/` (miniatures, posters vidéo — régénérable), `content-cache/` (rsync prod).