rebours/CLAUDE.md
ordinarthur 6583a7295a
All checks were successful
Build & Deploy to K3s / build-and-deploy (push) Successful in 34s
chore: remove legacy Astro + Sanity + Fastify stack
The site has fully migrated to Next.js 15 + Payload CMS 3 + Postgres
(under ./nextjs). Delete the old root-level Astro app, Sanity Studio,
Fastify server and their Docker/nginx plumbing. CI already builds
nextjs/Dockerfile and deploys a single rebours-web pod; drop the
legacy-pod teardown step now that the old workloads are long gone.

Removed:
- src/, public/, sanity/ (Astro pages/layouts/lib, Sanity studio)
- server.mjs, astro.config.mjs (Fastify API, Astro config)
- Dockerfile.ssr, Dockerfile.api, nginx.conf (old 3-pod topology)
- package.json, pnpm-lock.yaml (root, replaced by nextjs/)
- seed-sanity*.mjs, migrate-images.mjs, clean-duplicates.mjs
- .env.example, .dockerignore (root, superseded by nextjs/)
- .astro/ build artifacts

Updated:
- CLAUDE.md rewritten for the Next.js/Payload/Postgres stack
- .gitignore trimmed (no more Astro/Sanity entries)
- .gitea/workflows/deploy.yml: drop "Tear down legacy workloads"

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 18:26:48 +02:00

181 lines
6.2 KiB
Markdown

# REBOURS — Documentation technique
## Architecture du projet
```
rebours/
├── nextjs/ # App live (Next.js 15 + Payload CMS 3 + Postgres)
│ ├── src/
│ │ ├── app/
│ │ │ ├── (frontend)/ # Site public (/, /collection/[slug], /success)
│ │ │ └── (payload)/admin/ # Back-office Payload (/admin)
│ │ ├── collections/ # Schémas Payload (Products, Media, Users)
│ │ ├── components/admin/ # Custom admin UI (visual product editor)
│ │ ├── lib/payload.ts # Helpers Payload (mediaUrl, mediaAlt)
│ │ ├── scripts/main.js # JS client (cursor CAD, grid, panel, carousel)
│ │ ├── payload.config.ts # Config Payload (collections, plugins, drafts)
│ │ └── migrations/ # Migrations Postgres (auto-générées)
│ ├── public/
│ │ ├── style.css # CSS global du site public
│ │ └── assets/ # Favicons, son ambiant, fallback images
│ ├── Dockerfile # Image Docker unique (build + runtime)
│ ├── next.config.mjs
│ └── package.json
├── k8s/ # Manifests K3s (namespace, configmap, service, deployment, postgres)
├── .gitea/workflows/deploy.yml # CI/CD : build Docker + déploiement K3s
└── CLAUDE.md
```
## Stack
| Couche | Techno |
|--------|--------|
| Front + Back | Next.js 15 (App Router, SSR) |
| CMS | Payload 3 (self-hosted, monté sur `/admin`) |
| Base de données | PostgreSQL (StatefulSet K3s) |
| Paiement | Stripe Checkout (`price_data` inline) + plugin-stripe |
| Images | Payload Media → stockage local + `sharp` |
| Hébergement | K3s sur Proxmox (Traefik en front) |
| Fonts | Space Mono (Google Fonts) |
---
## Développement local
### Prérequis
- Node.js >= 20
- pnpm
- Docker (pour Postgres local) ou une instance Postgres accessible
- Un fichier `nextjs/.env` (voir `nextjs/.env.example`)
### Variables d'environnement (`nextjs/.env`)
```env
DATABASE_URI=postgres://rebours:rebours@localhost:5432/rebours
PAYLOAD_SECRET=your_32_char_secret
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
NEXT_PUBLIC_SERVER_URL=http://localhost:3000
```
### Lancer le projet
```bash
cd nextjs
pnpm install
pnpm dev
```
- Site public : http://localhost:3000
- Admin Payload : http://localhost:3000/admin
### Build
```bash
cd nextjs && pnpm build
```
---
## CMS — Payload
### Accès
- Admin : https://rebours.studio/admin (prod) / http://localhost:3000/admin (dev)
- Premier démarrage : la page `/admin/create-first-user` demande la création du premier user.
### Collection `products`
Éditeur visuel sur-mesure (`src/components/admin/ProductPreviewEditor.tsx`) : la page d'édition reproduit exactement le panneau produit public. Tous les champs éditables au clic (texte inline, carousel d'images, prix). Drawer « Réglages avancés » en bas pour les champs techniques (slug, SEO, Stripe ID).
Champs principaux : `productDisplayName`, `name`, `slug`, `index`, `type`, `materials`, `year`, `status`, `description`, `specs`, `notes`, `images[]` (array d'uploads), `price` (centimes), `currency`, `availability`, `isPublished`, `seoTitle`, `seoDescription`.
Autosave activé (interval 800 ms) via `versions.drafts.autosave`.
### Sync Stripe
Le plugin `@payloadcms/plugin-stripe` synchronise automatiquement les produits et prix avec Stripe dès que `STRIPE_SECRET_KEY` est valide. Un hook `beforeValidate` court-circuite la sync tant que `productDisplayName` est vide (évite l'erreur Stripe sur autosave de doc neuf).
---
## Stripe
### Checkout
1. Le front envoie le slug du produit à `/api/checkout`
2. Le serveur fetch le produit via Payload Local API
3. Création d'une session Stripe avec `price_data` inline
4. Redirect vers Stripe
5. Retour : `/success?session_id=...`
### Endpoints
| Route | Méthode | Description |
|-------|---------|-------------|
| `/api/checkout` | POST | Crée une session Stripe Checkout |
| `/api/session/[id]` | GET | Statut d'une session |
| `/api/stripe/webhook` | POST | Webhook Stripe (plugin-stripe) |
Webhook prod : `https://rebours.studio/api/stripe/webhook`
---
## Production
### Architecture K3s
```
Internet :443 → Traefik (10.10.10.2) → Service rebours-web → Pod rebours-web :3000
↘ Service rebours-postgres :5432
```
### Pods (namespace `rebours`)
| Workload | Port | Rôle |
|----------|------|------|
| `rebours-web` (Deployment) | 3000 | Next.js + Payload (tout-en-un) |
| `rebours-postgres` (StatefulSet) | 5432 | Postgres + PVC |
### Variables d'environnement en prod
- **ConfigMap** (`k8s/configmap.yml`) : `NEXT_PUBLIC_SERVER_URL`, `DATABASE_URI`
- **Secret `rebours-db-secret`** : `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`
- **Secret `rebours-app-secret`** : `PAYLOAD_SECRET`, `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`
- **Secret `gitea-registry-secret`** : pull de l'image depuis le registre Gitea
Les secrets d'app sont créés par la CI depuis les Gitea Actions secrets.
### Déploiement
Push sur `main` → Gitea Actions build l'image Docker puis applique les manifests K3s.
```bash
git push gitea main
```
Repo Gitea : `https://git.arthurbarre.fr/ordinarthur/rebours`
### Debugging prod
```bash
# Pods
ssh arthur@100.78.207.119 "sudo kubectl -n rebours get pods"
# Logs
ssh arthur@100.78.207.119 "sudo kubectl -n rebours logs deployment/rebours-web --tail=50"
# Redémarrer
ssh arthur@100.78.207.119 "sudo kubectl -n rebours rollout restart deployment/rebours-web"
# Shell Postgres
ssh arthur@100.78.207.119 "sudo kubectl -n rebours exec -it rebours-postgres-0 -- psql -U rebours"
```
---
## Routing
| URL | Comportement |
|-----|-------------|
| `/` | Page principale (SSR, Payload Local API) |
| `/collection/[slug]` | Page produit (SSR), auto-open panel via `window.__OPEN_PANEL__` |
| `/success?session_id=...` | Confirmation Stripe |
| `/admin` | Back-office Payload |
| `/api/*` | Routes Payload (REST + GraphQL) + endpoints custom (checkout, webhook) |
---
## Fichiers à ne jamais versionner
- `nextjs/.env`
- `node_modules/`
- `nextjs/.next/`