Files
librodrome/CLAUDE.md
T
Yvv 8408fd6466
ci/woodpecker/push/woodpecker Pipeline was successful
feat: SEO complet + analytics Umami + og:image § logo
SEO :
- composable useSeoPage() : og:*, Twitter Cards, canonical sur toutes les pages (15 pages)
- app.vue : JSON-LD Organization + Book, og:image global og-default.png
- og-default.png 1200×630 : logo § calligraphique + texte (Pillow)
- nuxt.config.ts : @nuxtjs/sitemap avec 26 URLs statiques

Analytics Umami :
- useTracking() : helpers typés audio/pdf/player/scroll/cta
- useScrollTracking() : scroll depth 25/50/75/100% + liens externes auto
- useAudioPlayer : trackAudioPlay/Progress/Complete
- BookPdfReader : trackPdfOpen/Close avec durée
- BookPlayer : trackPlayerOpen/Chapter/Mode
- docker-compose : variables NUXT_PUBLIC_UMAMI_* passées au container

Images :
- Couv-Economie-du-don.jpg ajoutée dans public/images/
- bookplayer.config.yml + home.yml : références mises à jour

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 00:25:28 +02:00

132 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Librodrome
Site vitrine du projet Le Librodrome — livre + chansons sur l'économie du don.
## Protocole de début de session
1. `git pull --rebase origin main` (récupère les commits admin git sync YAML prod)
2. Vérifier que `data/messages.yml` existe — si absent, signaler avant toute opération
3. Si l'objectif de la session n'est pas précisé, le demander
## Stack
- Nuxt 4 (Vue 3, TypeScript, Nitro) + Nuxt Content, Pinia, UnoCSS, VueUse, Nuxt Image
- Icônes : Lucide + Phosphor (via @iconify-json) ; Package manager : pnpm
- Déploiement : Docker + Traefik, CI via Woodpecker
## Structure
```
app/
pages/
numerique/ # index + [slug]
economique/ # index, monnaie-libre, commande, productions-collectives
modele-eco/ # sommaire + chapitres [slug]
citoyenne/ # index + [slug]
en-musique/ # player audio
admin/ # back-office (pages/, book/, songs, messages, media)
components/
book/Actions.vue # boutons partagés (player, PDF, chapitres, commande)
home/ # BookSection, AxisBlock, AxisGrid, HeroSection, HomeMessages
admin/, player/, song/, ui/
composables/ # useAudioPlayer, useBookData, useGrateWizard, usePageContent
stores/palette.ts # 4 palettes saisonnières (été par défaut, persisté localStorage)
assets/css/main.css # UnoCSS + overrides light mode
site/
pages/ # Contenu YAML administrable par section (sous-dossiers)
site.yml # Config globale (nav, footer, GrateWizard)
bookplayer.config.yml # Config player/chapitres
data/
messages.yml # Runtime — volume Docker ../data:/src/data — JAMAIS dans git
server/
api/content/ # GET pages YAML (chemins imbriqués)
api/admin/content/ # PUT pages YAML + liste
api/messages/ # GET (publiés) + POST (nouveau message)
api/admin/messages/ # GET tous + PUT (type, reply, published) + DELETE
utils/content.ts # readDataYaml/writeDataYaml (data/) + readYaml/writeYaml (site/)
middleware/redirects.ts # 301 : /gestation, /modele-eco, /decision, /lire
docker/
Dockerfile, docker-compose.yml, docker-compose.dev.yml
```
## Données runtime (CRITIQUE)
- `data/messages.yml` : volume Docker monté `../data:/src/data` (relatif à `docker/`)
- Persisté entre les rebuilds — **jamais écrasé par les commits ni par le déploiement**
- Structure message : `{ id, author, email, text, type, published, createdAt, reply: { text, publishedAt } | null }`
- Types : `reaction` (ancien, affiché "Réaction", plus proposé dans les formulaires) | `question` | `suggestion` | `retour`
- En dev local : `<racine>/data/messages.yml`
- **Avant toute migration de chemin ou écriture sur data/ : demander confirmation**
## Intégration GrateWizard
- URL dev : `app/app.config.ts``localhost:3001`
- URL prod : `https://gratewizard.axiom-team.fr`
## Contenu administrable
- YAML dans `site/pages/` par section ; API supporte les chemins imbriqués
- Admin : `/admin/pages` liste, `/admin/pages/{path}` édite en YAML
- Git sync auto en prod (`ADMIN_GIT_SYNC=true`) → d'où le `git pull --rebase` obligatoire en début de session
## Commandes
```bash
pnpm dev # Dev server :3000
pnpm build # Build production
PORT=3099 node .output/server/index.mjs # Test build prod (toujours avant commit)
```
## Conventions
- CSS via UnoCSS + variables CSS palettes ; composants Vue SFC `<script setup lang="ts">`
- Shadoks SVG inline thématiques sur chaque page (hidden mobile, opacity 0.180.28)
- Hexagramme 益 (#42 Yi, Augmentation) dans `layouts/default.vue`
- Signature § (logo calligraphique SVG gradient) dans `TheHeader.vue` — ne pas modifier sans demander
## SEO & Recherche IA — Checklist permanente
### À chaque nouvelle page Vue
1. **Appeler `useSeoPage()`** — jamais `useHead({ title })` seul
```ts
useSeoPage({
title: 'Titre page — Le Librodrome', // 5060 chars
description: 'Description...', // 120155 chars
image: '/images/og-specifique.jpg', // optionnel, sinon og-default.png (logo §)
type: 'website' | 'article' | 'book', // défaut: website
})
```
2. **og:image** : utiliser la couverture `/images/Couv-Economie-du-don.jpg` pour les pages livre/musique ; `og-default.png` (logo §) pour les pages site générales
3. **type: 'article'** pour les chapitres du modele-eco ; **type: 'book'** pour les index livre
### À chaque nouveau fichier YAML dans `site/pages/`
Ajouter le bloc `seo:` en tête :
```yaml
seo:
title: "Titre SEO — 50-60 chars max"
description: "Description 120-155 chars, avec mots-clés naturels"
# image: /images/og-specifique.jpg # optionnel
# keywords: [monnaie libre, TRM, économie du don]
```
### Règles description SEO
- Commence par un verbe d'action ou une affirmation forte
- Contient les mots-clés : économie du don, monnaie libre, TRM, June, bassin de vie, autonomie
- 120155 caractères (ni trop court, ni tronqué)
- Différente du titre et du H1
### JSON-LD automatique
- JSON-LD `Organization` + `Book` : injecté globalement dans `app.vue` — ne pas redupliquer
- Chapitres → og:type `article` via `useSeoPage({ type: 'article' })`
- Sitemap : géré par `@nuxtjs/sitemap` — ajouter manuellement les nouvelles routes statiques dans `nuxt.config.ts > sitemap.urls`
### Analytics — Nouveaux composants
- Tout bouton CTA externe : `trackCta(label, url)` depuis `useTracking()`
- Tout `<a target="_blank">` : capturé automatiquement par `useScrollTracking()` dans `default.vue`
- Tout nouveau lecteur média : appeler `trackAudioPlay` / `trackPdfOpen` depuis `useTracking()`