SPB Git forge

spb/food-ka

Public

Food-Ka — agrégateur de produits d'épicerie du Québec — www.food-ka.com

55commits 1branches 0releases
10.2 MBsize
maindefault branch
9 days agolast push
Python 53.9% TypeScript 24% CSS 14.9% JavaScript 5.8% HTML 1.4%

docs: README à jour avec screenshot

Simon-Pierre Boucher committed 1 mo ago (Aug 18, 2026) parent e6e3459

2 changed files +83 −14

modified README.md +83 −14
@@ -6,6 +6,8 @@
6 6
7 7 **[www.food-ka.com](https://www.food-ka.com)**
8 8
9 +![Aperçu de Food-Ka](docs/screenshot.png)
10 +
9 11 ![Python](https://img.shields.io/badge/Python-3.14-141814?style=for-the-badge&logo=python&logoColor=d9f26b)
10 12 ![FastAPI](https://img.shields.io/badge/FastAPI-API-141814?style=for-the-badge&logo=fastapi&logoColor=d9f26b)
11 13 ![React](https://img.shields.io/badge/React_18-Vite_+_TS-141814?style=for-the-badge&logo=react&logoColor=d9f26b)
@@ -17,9 +19,9 @@
17 19 ![Produits](https://img.shields.io/badge/produits_agr%C3%A9g%C3%A9s-22%20000%2B-1c5c41?style=flat-square)
18 20 ![Couverture](https://img.shields.io/badge/couverture-tout_le_Qu%C3%A9bec-1c5c41?style=flat-square)
19 21
20 −*Agrégateur indépendant de produits d'épicerie — chaque produit avec son prix courant,
21 −son prix régulier, son prix unitaire comparable ($/100 g) et un lien direct vers la
22 −fiche originale de la bannière. Toujours à jour, automatiquement.*
22 +*Agrégateur indépendant de produits d'épicerie — chaque produit avec son **prix courant**,
23 +son **prix régulier**, son **prix unitaire comparable ($/100 g)** et un lien direct vers la
24 +fiche originale de la bannière. **Toujours à jour, automatiquement.***
23 25
24 26 </div>
25 27
@@ -29,14 +31,27 @@ fiche originale de la bannière. Toujours à jour, automatiquement.*
29 31
30 32 Comparer les prix d'épicerie au Québec, c'est ouvrir Metro, IGA, Maxi, Super C,
31 33 Provigo, Walmart… chacun avec sa propre navigation, son propre panier, son propre
32 −format. **Food-Ka retourne le problème** : un connecteur dédié par bannière visite
33 −chaque site, normalise chaque produit vers un schéma unique, et détecte les
34 −changements de prix en continu.
34 +format. **Food-Ka retourne le problème** : un **connecteur dédié par bannière** visite
35 +chaque site, **normalise chaque produit** vers un schéma unique, et **détecte les
36 +changements de prix en continu**.
35 37
36 38 > Les épiceries n'offrent pas de webhooks. Food-Ka reproduit l'équivalent :
37 39 > **synchronisation périodique + hash de contenu** → nouveaux produits, changements
38 40 > de prix et retraits détectés automatiquement. Chaque variation de prix est
39 −> historisée (`price_log`) — les soldes deviennent traçables.
41 +> **historisée** (`price_log`) — les soldes deviennent traçables.
42 +
43 +## Fonctionnalités
44 +
45 +- **Agrégation multi-bannières** — **24 connecteurs actifs** (sur **30 bannières recensées**), **22 000+ produits** couvrant **tout le Québec**.
46 +- **Prix unitaire comparable** — chaque produit ramené en **$/100 g** pour comparer l'incomparable.
47 +- **Détection des soldes** — prix courant vs **prix régulier**, tri par **rabais**, historique complet des variations.
48 +- **Comparaison inter-bannières** — chaque fiche produit montre les **équivalents chez les autres bannières**.
49 +- **Connexion KA ID** — **SSO du Groupe Ka** (courriel + Google) : un seul compte (`ka_id`) valable sur **toutes les plateformes ·Ka** (`foodka/auth.py`, profil via `hubprofile.py`).
50 +- **Favoris** — cœur sur chaque produit, **favoris synchronisés au compte KA ID** via le hub central (`foodka/hubfav.py`, page **Profil** dans le frontend).
51 +- **Recherche et filtres** — catégorie, bannière, marque, fourchette de prix, soldes, texte libre ; tris prix / prix unitaire / rabais / récents.
52 +- **Stats Groupe KA** — tableau de bord analytique commun avec **export PDF** (`statsdash.py`, `kapdf.py`).
53 +- **PWA installable** — design « éditorial sharp » (Space Grotesk, accent lime, ticker temps réel), **mobile-first**, cibles tactiles ≥ 44 px.
54 +- **Design system ka-ui** — tokens, footer, badge et écosystème **Groupe Ka** partagés (13 sites), page `/contact`, widget **KA Agent** (bulle de chat IA).
40 55
41 56 ## L'architecture en 30 secondes
42 57
@@ -56,7 +71,41 @@ flowchart LR
56 71 F --> U["🛒 Consommateur"]
57 72 ```
58 73
59 −| Couche | Rôle | Fichiers |
74 +## Stack technique
75 +
76 +| Couche | Techno | Rôle |
77 +|---|---|---|
78 +| **Backend** | **Python 3.14 + FastAPI** | API REST, sync, auth KA ID, favoris |
79 +| **Frontend** | **React 18 + Vite + TypeScript** | PWA, react-router, design ka-ui |
80 +| **Stockage** | **SQLite** (`data/foodka.db`) | produits, hash, `price_log`, `sync_log` |
81 +| **Scraping** | requests + **Scrapfly** / **Firecrawl** | HTML, APIs JSON, `__NEXT_DATA__`, anti-bot |
82 +| **Process** | **PM2** + **ngrok** | résilience (auto-restart) + tunnel |
83 +
84 +## Structure du projet
85 +
86 +```
87 +food-ka/
88 +├── run.py # CLI : sync · serve · watch
89 +├── requirements.txt
90 +├── foodka/ # backend Python
91 +│ ├── web.py # API FastAPI (produits, facettes, stats, sync)
92 +│ ├── auth.py # connexion KA ID (SSO Groupe Ka)
93 +│ ├── hubfav.py # favoris synchronisés au hub KA ID
94 +│ ├── hubprofile.py # profil utilisateur KA ID
95 +│ ├── schema.py # Product normalisé + prix unitaire $/100 g
96 +│ ├── db.py # diff engine (hash, upsert, price_log)
97 +│ ├── ingest.py # orchestration des synchronisations
98 +│ ├── normalize.py # catégories canoniques, parsing des prix
99 +│ ├── statsdash.py # tableau de bord Stats Groupe KA
100 +│ ├── kapdf.py / pdfgen.py# export PDF
101 +│ └── connectors/ # 1 module auto-découvert par bannière
102 +├── frontend/ # React 18 + Vite + TS (PWA, ka-ui vendorisé)
103 +├── data/ # foodka.db + sources.json (registre des bannières)
104 +├── docs/ # screenshot.png
105 +└── tests/
106 +```
107 +
108 +| Couche | Détail | Fichiers |
60 109 |---|---|---|
61 110 | **Connecteurs** | 1 module Python par bannière : HTML rendu serveur, API JSON ouvertes (Shopify `products.json`, WooCommerce Store API), `__NEXT_DATA__` (Loblaw), ou **Scrapfly** (anti-bot ASP + rendu JS) / **Firecrawl** pour les sites protégés | `foodka/connectors/*.py` |
62 111 | **Schéma** | `Product` standardisé : nom, marque, format, prix, prix régulier, **prix unitaire $/100 g**, catégorie canonique, images | `foodka/schema.py` |
@@ -64,10 +113,10 @@ flowchart LR
64 113 | **API** | Filtres catégorie / bannière / marque / prix / soldes / recherche, tris (prix, prix unitaire, rabais), facettes, stats | `foodka/web.py` |
65 114 | **Frontend** | Design « éditorial sharp » : Space Grotesk, ombres décalées, accent lime, ticker temps réel, fiches produit avec comparaison inter-bannières, PWA installable | `frontend/` |
66 115
67 −## Démarrage rapide
116 +## Démarrage local
68 117
69 118 ```bash
70 −git clone https://github.com/spboucher-ai/food-ka.git && cd food-ka
119 +git clone gitsrv:srv/git/food-ka.git && cd food-ka
71 120
72 121 # Backend
73 122 python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
@@ -128,6 +177,10 @@ correspondante dans `data/sources.json` pour la page **Sources**.
128 177 | `GET /api/stats` | Totaux, soldes actifs, meilleures aubaines, journal de synchronisation |
129 178 | `POST /api/sync` | Déclenche une synchronisation en arrière-plan |
130 179
180 +L'authentification **KA ID** et les **favoris** exposent leurs propres routes
181 +(`foodka/auth.py`, `foodka/hubfav.py`) adossées au **hub SSO central du Groupe Ka**
182 +(groupe-ka.com).
183 +
131 184 ## Couverture
132 185
133 186 **Grandes bannières** — Metro, Super C, IGA (Voilà), Maxi, Provigo, Walmart Canada,
@@ -142,19 +195,33 @@ Chaque bannière non-connectable est **documentée avec sa raison** dans
142 195 `data/sources.json` (ex. : prix liés à une session Instacart/DoorDash, catalogue
143 196 sans prix, anti-bot strict).
144 197
145 −## Production
198 +## Déploiement (production)
146 199
147 −Déployé sous **PM2** (3 processus) derrière **ngrok** :
200 +- **Nœud** : **M4M64b** (Mac Studio, 16 cœurs / 64 Go) — répertoire `~/apps/food-ka`
201 +- **Port** : **8097**
202 +- **Domaine** : **[www.food-ka.com](https://www.food-ka.com)** (tunnel **ngrok**)
203 +- **Process manager** : **PM2** (3 processus, auto-restart) :
148 204
149 205 ```
150 −food-ka-web .venv/bin/python run.py serve 8096 # API + frontend
206 +food-ka-web .venv/bin/python run.py serve 8097 # API + frontend
151 207 food-ka-sync .venv/bin/python run.py watch 360 # resync aux 6 h
152 −food-ka-ngrok ngrok http --url=www.food-ka.com 8096 # tunnel
208 +food-ka-ngrok ngrok http --url=www.food-ka.com 8097 # tunnel
153 209 ```
154 210
155 211 Philosophie d'exploitation : **on ne pousse que le code — le serveur maintient ses
156 212 données lui-même.**
157 213
214 +## Développement remote-first (IMPORTANT)
215 +
216 +La **source de vérité est le repo git SUR le nœud M4M64b** (`~/apps/food-ka`), **pas
217 +une copie locale**. Toute modification se fait **via SSH sur le nœud** : édition,
218 +`npm run build` du frontend, `pm2 restart food-ka-web`, puis commit/push **depuis le
219 +nœud** (agent forwarding actif).
220 +
221 +- **Remote `origin` = spbgit** (git perso, **git.spboucher.ai**) via l'**alias SSH `gitsrv`** :
222 + `gitsrv:srv/git/food-ka.git` (bare repo hébergé sur M3U96a). **Pas GitHub.**
223 +- Ne **jamais** éditer d'éventuelles copies laptop — elles ne sont pas synchronisées.
224 +
158 225 ## Principes
159 226
160 227 1. **Politesse** — délai ≥ 0,5 s entre requêtes, périmètre de crawl borné,
@@ -183,4 +250,6 @@ données lui-même.**
183 250
184 251 © 2026 Simon-Pierre Boucher — tous droits réservés.
185 252
253 +**Un service [Groupe Ka](https://www.groupe-ka.com)**
254 +
186 255 </div>
added docs/screenshot.png +0 −0

Binary file not shown.