Files
suivi_produit/CLAUDE.md
gilles 9a6448facc docs: add frontend Phase 2 implementation plan
- Add detailed 6-step development plan for frontend
- Define architecture with React Router for multi-store evolution
- Document API endpoints needed (existing + to create)
- Update TODO.md and kanban.md with current status

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 19:21:19 +01:00

15 KiB
Raw Permalink Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Commandes Essentielles

Backend (Poetry)

poetry install                    # Installation des dépendances
poetry run pytest                 # Tests unitaires
poetry run ruff check backend/    # Linting
poetry run mypy backend/          # Vérification de types
poetry run coverage run -m pytest && poetry run coverage report -m  # Couverture

Scraper CLI (test manuel)

SCRAPE_TEST_MAX=0 poetry run python backend/app/scraper/run_scrape_tests.py
# Avec navigateur visible si blocage Amazon:
SCRAPE_TEST_HEADFUL_ON_BLOCK=1 SCRAPE_TEST_MAX=0 poetry run python backend/app/scraper/run_scrape_tests.py

Serveur de développement

poetry run uvicorn backend.app.main:app --reload  # Backend (port 8008)
cd frontend && npm run dev                         # Frontend (port 5173)

Frontend (npm)

cd frontend && npm install && npm run dev   # Dev
cd frontend && npm run build                # Build production

Architecture

Stack technique

  • Backend: FastAPI + SQLAlchemy (SQLite) + APScheduler + Loguru
  • Scraper: Playwright (Chromium) + BeautifulSoup4, contexte fr-FR
  • Frontend: React 18 + Vite + Zustand + SCSS Gruvbox dark

Structure clé

├── agent.md
├── backend
│   ├── app
│   │   ├── api
│   │   │   ├── deps.py
│   │   │   ├── __init__.py
│   │   │   ├── routes_config.py
│   │   │   ├── routes_products.py
│   │   │   └── routes_scrape.py
│   │   ├── core
│   │   │   ├── config.py
│   │   │   ├── logging.py
│   │   │   ├── __pycache__
│   │   │   └── scheduler.py
│   │   ├── db
│   │   │   ├── crud.py
│   │   │   ├── database.py
│   │   │   ├── models.py
│   │   │   └── schemas.py
│   │   ├── __init__.py
│   │   ├── main.py
│   │   ├── __pycache__
│   │   │   └── __init__.cpython-313.pyc
│   │   ├── samples
│   │   │   ├── amazon_product.html
│   │   │   ├── debug
│   │   │   ├── scrape_fields.json
│   │   │   ├── scrape_test.json
│   │   │   ├── scrap_result.json
│   │   │   └── storage_state.json
│   │   ├── scraper
│   │   │   ├── amazon
│   │   │   ├── browser.py
│   │   │   ├── normalize.py
│   │   │   ├── __pycache__
│   │   │   ├── runner.py
│   │   │   └── run_scrape_tests.py
│   │   ├── services
│   │   │   ├── __init__.py
│   │   │   ├── pricing.py
│   │   │   └── __pycache__
│   │   └── tests
│   │       ├── __init__.py
│   │       ├── __pycache__
│   │       ├── test_normalize.py
│   │       ├── test_parser_samples.py
│   │       └── test_pricing.py
│   ├── config_backend.json
│   ├── data
│   │   ├── raw
│   │   └── screenshots
│   ├── __init__.py
│   ├── logs
│   └── __pycache__
│       └── __init__.cpython-313.pyc
├── CHANGELOG.md
├── CLAUDE.md
├── consigne codex.md
├── docker
├── docs
│   ├── ARCHITECTURE.md
│   ├── db_structure.md
│   ├── frontend_structure.md
│   ├── scrap.md
│   └── tools.md
├── frontend
│   ├── config_frontend.json
│   ├── package.json
│   ├── public
│   │   └── index.html
│   ├── src
│   │   ├── api
│   │   │   └── client.js
│   │   ├── app
│   │   ├── App.jsx
│   │   ├── components
│   │   │   └── ProductCard.jsx
│   │   ├── main.jsx
│   │   └── styles
│   │       └── global.scss
│   └── vite.config.js
├── kanban.md
├── pyproject.toml
├── README.md
└── TODO.md

Flux de scraping

  1. Playwright charge la page avec délais aléatoires (1-3s)
  2. Détection blocage (captcha/robot) → artéfacts debug (screenshot + HTML)
  3. Extraction via CSS selectors → normalisation (prix, stock, ratings)
  4. Sauvegarde: snapshot DB + raw JSON dans backend/data/raw/

Base de données (SQLite)

  • products: URL, ASIN, titre, catégorie, statut actif
  • product_snapshots: prix, stock, ratings, badges, status scrape, lien vers raw JSON
  • scrape_runs: métadonnées de chaque exécution (success/fail counts)

Configuration

  • backend/config_backend.json: intervalle scrape, timeout, browser settings
  • frontend/config_frontend.json: thème, layout grille, champs visibles
  • .env: variables d'environnement (copier .env.example)

Règles de développement

Libertés accordées

  • Créer/modifier fichiers backend, frontend, docs
  • Refactorer pour lisibilité/robustesse
  • Lancer tests et scripts de validation

Actions nécessitant approbation

  • Refonte architecture (stack, framework)
  • Suppression/reset données utilisateur (tables, raw JSON, logs)
  • Migrations DB irréversibles

Qualité code

  • Chaque scrape produit un log clair dans backend/logs/scrap.log (rotation 10MB, 7j)
  • Erreurs scraping = résilience (log + artéfacts) sans crash global
  • Logique métier critique accompagnée de tests

Commits

  • Messages courts explicites: feat: add scraper runner
  • Un commit = une unité cohérente
  • Pas de commits fourre-tout

Notes importantes

  • Le scraping est volontairement lent (15-20 produits/jour) pour éviter blocage Amazon
  • Raw JSON conservé 30 jours dans backend/data/raw/
  • Pre-commit hooks configurés (Ruff + MyPy): pre-commit install

Schéma ASCII (UI globale)

Objectif : reproduire lesprit de la capture (vignette + section prix + graphe), en améliorant la lisibilité.

┌──────────────────────────────────────────────────────────────────────────┐
│  suivi_produits   [Add Product] [Refresh] [Settings]  FE vX  BE vY       │
│  (header fixed)     [debug]                                      (⋯)     │
├──────────────────────────────────────────────────────────────────────────┤
│  Grid (cols = config_frontend.json)                                      │
│                                                                          │
│  ┌──────────────────────────── Card Produit ──────────────────────────┐  │
│  │  Boutique + Titre (2 lignes)                                       │  │
│  │  Amazon                                                            │  │
│  │  Samsung SSD Interne 9100 Pro…                                     │  │
│  │                                                                    │  │
│  │  ┌───────────────┐   ┌──────────────────────────────────────────┐  │  │
│  │  │   Image       │   │  ACTUEL         249€99                   │  │  │
│  │  │  (non rognée) │   │  PRIX CONSEILLÉ  329€99 (si présent)     │  │  │
│  │  │               │   │  RÉDUCTION       -24%  (si présent)      │  │  │
│  │  └───────────────┘   │  STOCK          Disponible               │  │  │
│  │                      │  NOTE           4,7 (967)                │  │  │
│  │                      │  CHOIX AMAZON   Oui/Non                  │  │  │
│  │                      │  PRIME          Oui/Non                  │  │  │
│  │                      │  DEAL           Oui/Non                  │  │  │
│  │                      │  Ref: ASIN      [Lien produit]           │  │  │
│  │                      └──────────────────────────────────────────┘  │  │
│  │                                                                    │  │
│  │  ┌────────────────────── Graph 30j (clair) ─────────────────────┐  │  │
│  │  │  ligne + points, axes lisibles, tooltip                      │  │  │
│  │  └──────────────────────────────────────────────────────────────┘  │  │
│  │                                                                    │  │
│  │  Min 249€99   Max 249€99   Tendance → stable +0.0%   Dernier: now  │  │
│  │  Catégorie: SSD   Type: NVMe                                       │  │
│  │                                                                    │  │
│  │  [Scrap] [Edit] [Delete] [Détail]                                  │  │
│  └────────────────────────────────────────────────────────────────────┘  │
│                                                                          │
└──────────────────────────────────────────────────────────────────────────┘

page de debug et log qui affiche le contenue des differentes tables sqlite dans des section distincte, une section log qui affiche les log json de scrap

Vignette produit : exigences UI

  • Image non tronquée : object-fit contain, fond neutre, padding.

  • Section prix alignée au niveau de limage (descendue comme sur la capture).

  • “Boutique + titre” sur 2 lignes, pleine largeur, icône boutique.

  • Badges : Amazon Choice / Prime / Deal / Exclusive (chips).

  • Graph 30j :

    • axes + labels lisibles
    • points visibles
    • min/max/tendance affichés sous le graphe
    • couleurs + flèches :
      • baisse : vert + flèche ↓
      • stable : jaune/orange + →
      • hausse : rouge + ↑
  • Responsive :

    • columns paramétrable (desktop)
    • mobile : 1 colonne + layout empilé

    Contraintes clés :

  • Scraping : Python + Playwright (robuste, peu de produits : 1520/jour).

  • Stockage : JSON (raw scrap) + persistance en SQLite (historique prix + métriques).

  • Config :

    • config_backend.json (paramètres scraping + backend + catégories/types)
    • config_frontend.json (paramètres UI + colonnes + thème + bouton mode text/icon)
  • Logs : fichier de log des scrapes (rotation simple).

  • UI : Gruvbox vintage dark, moderne (ombres, arrondis, typo lisible), responsive. icon fa

  • Déploiement : test en mode .env puis deploiement final dans docker-compose (backend + frontend) + cron/worker pour scrapes périodiques.

  • Repo : sur mon serveur Gitea, nom : suivi_produits : https://gitea.maison43.duckdns.org/gilles/suivi_produit


Objectif produit (fonctionnel)

Application self-hosted pour suivre lévolution de produits Amazon.fr (puis autres stores). Lutilisateur ajoute des URLs de produits, lapp :

  • scrape les données clés (prix, stock, note, badges, image, etc.)
  • stocke un snapshot à chaque scraping
  • affiche des vignettes produit + graphique historique clair (tendance, min/max, %)
  • propose actions : Scrap, Edit, Delete, Détail
  • lance un scraping planifié (cron) sur tous les produits à intervalle défini.

Données à capturer (Amazon.fr)

Champs de base (toujours)

  • url (canonique) + asin
  • title (nom produit)
  • image_main_url (image principale)
  • price_current (valeur numérique + devise)
  • stock_status (texte) + in_stock (bool)
  • rating_value (float) + rating_count (int)

Champs conditionnels (si présents)

  • price_list / prix conseillé / prix barré (si affiché)
  • discount_percent (si affiché ou calculé)
  • lowest_30d_price (si mention “prix le plus bas des 30 derniers jours”)
  • amazon_choice (badge)
  • limited_time_deal (offre à durée limitée)
  • prime_eligible (badge prime / livraison prime)
  • amazon_exclusive (mention exclusivité)

Calculs à faire côté app (pas “inventer”)

Important : ne pas “calculer une réduction” si le champ source nexiste pas. on ne calcule rien sauf demande explicite de ma part ( peut etre tendance dans courbe historique)


Méthode de scraping (sûre/efficace)

Stratégie Playwright

  • Navigateur Chromium.
  • Context :
    • locale fr-FR
    • timezone Europe/Paris
    • viewport réaliste (ex. 1366×768 ou 1920×1080)
    • user-agent récent
  • Rythme : faible (1520 produits/jour) + delays aléatoires 13s entre pages.
  • Détection blocages :
    • si page contient captcha / robot-check → marquer scrap “blocked” + screenshot + html dump pour debug.
  • Résilience :
    • retry 12 fois max avec backoff, sinon échec contrôlé.

Sélecteurs (approche robuste)

  • Priorité : IDs stables (ex : #productTitle, #acrCustomerReviewText, #availability)
  • Prix : gérer variantes (prix fractionné, promo, etc.)
  • Fallback : si sélecteur absent, log “missing field”, ne pas planter.

Artifacts de debug

À chaque scrap :

  • sauvegarder un JSON “raw” normalisé
  • en cas déchec : page.screenshot() + page.content() dans un dossier debug/ horodaté.

Architecture cible

Backend

  • API HTTP (proposé : FastAPI) :
    • CRUD produits
    • déclenchement scrap (produit / tous)
    • lecture historique + agrégats (min/max/tendance)
    • lecture/écriture configs frontend/backend
  • Worker de scraping (Playwright) séparé en module “scraper”
  • Scheduler (cron interne ou cron container) qui appelle scrape_all

Frontend

  • SPA simple (proposé : Vite + React ou Svelte) ou HTML server-side minimal (selon simplicité).
  • Thème Gruvbox vintage dark :
    • fond #282828, cartes #3c3836, texte #ebdbb2
    • accent orange #fe8019, jaune #fabd2f, vert #b8bb26
  • Responsive : nombre de colonnes configurable.
  • utilisation de popup lors de l'ajout de produit ou acces a setting

Stockage

  • le stockage se fais uniquement lors de l'enregistrement du produit
  • SQLite : tables normalisées (produits, snapshots, tags/catégories/types)
  • JSON “raw” : archivage optionnel (dossier data/raw/YYYY-MM/...json)