All checks were successful
Build & Deploy to K3s / build-and-deploy (push) Successful in 34s
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>
181 lines
6.2 KiB
Markdown
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/`
|