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>
6.2 KiB
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(voirnextjs/.env.example)
Variables d'environnement (nextjs/.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
cd nextjs
pnpm install
pnpm dev
- Site public : http://localhost:3000
- Admin Payload : http://localhost:3000/admin
Build
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-userdemande 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
- Le front envoie le slug du produit à
/api/checkout - Le serveur fetch le produit via Payload Local API
- Création d'une session Stripe avec
price_datainline - Redirect vers Stripe
- 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.
git push gitea main
Repo Gitea : https://git.arthurbarre.fr/ordinarthur/rebours
Debugging prod
# 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/.envnode_modules/nextjs/.next/