SPB Git forge

spb/fabri-ka

Public

Agrégateur de produits québécois — www.fabri-ka.com

217commits 1branches 0releases
66.1 MBsize
maindefault branch
5 h agolast push
Python 38.4% HTML 30.3% TypeScript 17.2% CSS 11% JavaScript 3.2%

docs: README à jour avec screenshot

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

2 changed files +91 −150

modified README.md +91 −150
@@ -12,8 +12,8 @@
12 12 ![SQLite](https://img.shields.io/badge/SQLite-FTS5-1E1B16?style=for-the-badge&logo=sqlite&logoColor=C4532E)
13 13 ![Firecrawl](https://img.shields.io/badge/Firecrawl-rendu_JS-1E1B16?style=for-the-badge&logoColor=C4532E)
14 14
15 −![Produits](https://img.shields.io/badge/produits_agr%C3%A9g%C3%A9s-291_000%2B-234438?style=flat-square)
16 −![Boutiques connectées](https://img.shields.io/badge/boutiques_avec_produits-1_266-234438?style=flat-square)
15 +![Produits](https://img.shields.io/badge/produits_agr%C3%A9g%C3%A9s-291_557-234438?style=flat-square)
16 +![Boutiques connectées](https://img.shields.io/badge/boutiques_avec_produits-1_265-234438?style=flat-square)
17 17 ![Registre](https://img.shields.io/badge/boutiques_QC_v%C3%A9rifi%C3%A9es-3_224-234438?style=flat-square)
18 18 ![Connecteurs](https://img.shields.io/badge/connecteurs_plateforme-7-234438?style=flat-square)
19 19 ![Régions](https://img.shields.io/badge/r%C3%A9gions_couvertes-17%2F17-234438?style=flat-square)
@@ -24,15 +24,33 @@
24 24 ![SSO](https://img.shields.io/badge/KA_ID-SSO_Groupe_KA-C4532E?style=flat-square)
25 25 ![Langue](https://img.shields.io/badge/fr--CA-d'abord-C4532E?style=flat-square)
26 26
27 −*Agrégateur de découverte des produits vendus en ligne par les entreprises du Québec —
28 −chaque produit renvoie vers la boutique d'origine. Aucune vente sur Fabri-Ka :
29 −les prix, photos et stocks appartiennent aux marchands sources.*
30 −
31 27 </div>
32 28
29 +![Aperçu de Fabri-Ka](docs/screenshot.png)
30 +
33 31 ---
34 32
35 −## Aperçu
33 +## Description
34 +
35 +**Fabri-Ka** est le **répertoire des produits québécois** : un agrégateur de découverte qui recense **291 557 produits** provenant de **1 265 boutiques en ligne** du Québec, couvrant les **17 régions administratives** de la province. Chaque produit renvoie vers la **boutique d'origine** — **aucune vente sur Fabri-Ka** : les prix, photos et stocks appartiennent aux marchands sources.
36 +
37 +Acheter québécois demande de connaître des centaines de boutiques dispersées — érablières, microbrasseries, savonneries, ébénistes, torréfacteurs, fermes… **Fabri-Ka retourne le problème** : un pipeline de découverte recense les boutiques en ligne du Québec (**3 224 boutiques vérifiées** au registre), des connecteurs par *plateforme* aspirent leurs catalogues publics complets, et un **moteur de recherche unique** les rend trouvables — filtrés par **catégorie**, **région** et **origine de fabrication** (classes **A–E**).
38 +
39 +> Contrairement à un agrégateur classique (1 connecteur / site), Fabri-Ka utilise **1 connecteur / plateforme ecommerce** : le même code **Shopify** sert des centaines de boutiques, piloté par le registre `data/stores.json` produit par la recherche.
40 +
41 +## Fonctionnalités
42 +
43 +- **Recherche de produits** — plein-texte **FTS5 accent-insensible** sur **291 557 produits**, filtres **catégorie / région / origine / prix**, tri, pagination, fiches riches (galerie, boutique, produits liés).
44 +- **Répertoire de boutiques** — **1 265 boutiques** avec produits (sur **3 224 vérifiées**), fiches enrichies : logo, région, plateforme, **stats de prix**, catégories, boutiques similaires.
45 +- **Statistiques** — tableau de bord analytique `/stats` (module commun **ka-stats**) : totaux, médianes, histogrammes, ventilation régionale, croissance — et **rapport de marché PDF** généré à la volée (`/api/report.pdf`, moteur **kapdf**).
46 +- **Catégories** — taxonomie de **20 catégories** (mode 38 k · bijoux 34 k · épicerie fine 29 k · …) avec **~350 pages programmatiques SEO** (`/categorie/erable`, `/region/monteregie`, combinaisons non vides).
47 +- **Classification d'origine A–E** — chaque boutique justifiée par une **évidence conservée** (certifications *Aliments du Québec* / *Les Produits du Québec*, associations, wording du site).
48 +- **SEO / SSR** — **292 000+ pages indexables** : HTML complet dès la 1ʳᵉ requête, **JSON-LD** schema.org, **sitemaps** exhaustifs, 301/404/410 propres (détails plus bas).
49 +- **KA ID (SSO)** + favoris **« Mon univers Ka »** synchronisés au hub **groupe-ka.com**.
50 +- **Widget KA Agent** — bulle de chat Groupe KA (`ka-agent.js`).
51 +- **Mobile-first** — barre d'onglets, filtres en bottom sheet, galeries swipe, CTA collant, PWA-lite, **fr-CA** d'abord.
52 +
53 +### Galerie
36 54
37 55 | Accueil | Fiche produit |
38 56 |---|---|
@@ -51,22 +69,20 @@ les prix, photos et stocks appartiennent aux marchands sources.*
51 69 &nbsp;&nbsp;
52 70 <img src="docs/screenshots/mobile-produit.png" width="240" alt="Fiche produit mobile"/>
53 71 </p>
54 −<p align="center"><i>Mobile-first : barre d'onglets, filtres en bottom sheet, galeries swipe, CTA collant, favoris ♥ synchronisés au hub Groupe KA.</i></p>
55 72
56 −## Pourquoi Fabri-Ka ?
73 +## Stack technique
57 74
58 −Acheter québécois demande de connaître des centaines de boutiques dispersées —
59 −érablières, microbrasseries, savonneries, ébénistes, torréfacteurs, fermes…
60 −**Fabri-Ka retourne le problème** : un pipeline de découverte recense les boutiques
61 −en ligne du Québec, des connecteurs par *plateforme* aspirent leurs catalogues
62 −publics complets, et un moteur de recherche unique les rend trouvables — filtrés
63 −par catégorie, région et origine de fabrication (classes A–E).
64 −
65 −> Contrairement à un agrégateur classique (1 connecteur / site), Fabri-Ka utilise
66 −> **1 connecteur / plateforme ecommerce** : le même code Shopify sert des centaines
67 −> de boutiques, piloté par le registre `data/stores.json` produit par la recherche.
75 +| Couche | Technologies |
76 +|---|---|
77 +| **Backend** | **Python 3.14** · **FastAPI** (API + SSR SEO + service du frontend) |
78 +| **Base de données** | **SQLite + FTS5** — upsert par **hash de contenu**, retraits avec délai de grâce (2 syncs) |
79 +| **Frontend** | **React 18 + Vite + TypeScript** — 9 pages, identité famille KA « éditorial sharp » (Space Grotesk + Inter + JetBrains Mono, palette crème/terracotta/pin/miel), tokens **ka-ui** |
80 +| **Connecteurs** | **Shopify** `products.json` (transport curl anti-429 TLS) · **WooCommerce** Store API · **Wix Stores** GraphQL · **Squarespace** `?format=json` · **connecteur générique** (sitemap → JSON-LD/microdata/OG : PrestaShop, Lightspeed, Snipcart, Magento, sites custom) · **Scrapfly/Firecrawl** en secours anti-bot |
81 +| **Découverte** | **35+ sources** : sitemaps d'annuaires, API cachées de cartes (wpgmza, FacetWP), pagination htmx, sessions **Firecrawl** pour répertoires JS |
82 +| **Comptes** | **KA ID** SSO (JWT HS256, stdlib pure) · favoris HMAC-SHA256 vers le hub central |
83 +| **Prod** | **PM2** + **ngrok** sur le cluster **MacLustr** |
68 84
69 −## L'architecture en 30 secondes
85 +### Architecture en 30 secondes
70 86
71 87 ```mermaid
72 88 flowchart LR
@@ -87,26 +103,9 @@ flowchart LR
87 103 F --> U["🍁 Acheteur local"]
88 104 ```
89 105
90 −| Couche | Rôle | Fichiers |
91 −|---|---|---|
92 −| **Découverte** | Sitemaps d'annuaires, API cachées de cartes (wpgmza, FacetWP), pagination htmx, résolution de redirections affiliées, sessions Firecrawl pour répertoires JS (CMAQ) | `scripts/harvest.py`, `scripts/cmaq_firecrawl.py` |
93 −| **Vérification** | Plateforme ecommerce + test réel de l'endpoint catalogue + signaux de localisation QC (codes postaux, indicatifs, TLD, wording) | `scripts/verify.py` |
94 −| **Classification** | Origine A–E avec évidence conservée (certifications → a priori ; wording du site → ajustement) | `scripts/build_registry.py` |
95 −| **Connecteurs** | Shopify `products.json` (transport curl anti-429 TLS), WooCommerce Store API, Wix Stores GraphQL (jeton public), Squarespace `?format=json`, **connecteur générique** (sitemap → JSON-LD/microdata/OG sur PrestaShop, Lightspeed, Snipcart, Magento, sites custom), Scrapfly/Firecrawl en secours anti-bot | `fabrika/connectors/` |
96 −| **Diff engine** | Upsert par hash de contenu, retraits avec délai de grâce (2 syncs), FTS5 accent-insensible | `fabrika/db.py` |
97 −| **API** | Recherche FTS5, facettes, filtres catégorie/région/origine/prix, stats, rapport PDF, sync | `fabrika/web.py` |
98 −| **SEO / SSR** | HTML complet dès la 1ʳᵉ requête sur toutes les routes, pages programmatiques, JSON-LD, sitemaps, 301/404/410 | `fabrika/seo.py` |
99 −| **Comptes** | « Se connecter avec KA ID » (SSO du Groupe KA), favoris « Mon univers Ka » poussés au hub central | `fabrika/auth.py`, `fabrika/hubfav.py`, `fabrika/hubprofile.py` |
100 −| **Frontend** | Identité famille KA « éditorial sharp » (cf. Food-Ka/Lou-Ka) — Space Grotesk + Inter + JetBrains Mono, bordures encre, ombres décalées, palette crème/terracotta/pin/miel, PWA-lite, fr-CA | `frontend/` |
101 −
102 −## SEO & rendu serveur — 292 000+ pages indexables
103 −
104 −Le site est une SPA React, mais **aucun moteur de recherche ne voit une page vide** :
105 −le catch-all FastAPI (`fabrika/seo.py`) injecte dans le HTML du build Vite, pour
106 −chaque route, un `<head>` complet **et le contenu essentiel de la page dans `#root`**
107 −— React remplace ce contenu au montage (hydratation), le dynamique reste intact.
106 +## SEO & rendu serveur — **292 000+ pages indexables**
108 107
109 −**Ce que reçoit un robot (et un visiteur sans JavaScript) :**
108 +Le site est une SPA React, mais **aucun moteur de recherche ne voit une page vide** : le catch-all FastAPI (`fabrika/seo.py`) injecte dans le HTML du build Vite, pour chaque route, un `<head>` complet **et le contenu essentiel de la page dans `#root`** — React remplace ce contenu au montage (hydratation).
110 109
111 110 | Élément | Détail |
112 111 |---|---|
@@ -116,87 +115,59 @@ chaque route, un `<head>` complet **et le contenu essentiel de la page dans `#ro
116 115 | **JSON-LD schema.org** | `Product` + `Offer` (prix CAD, dispo, vendeur), `BreadcrumbList`, `OnlineStore`, `CollectionPage` + `ItemList`, `WebSite` + `SearchAction` |
117 116 | **Contenu HTML complet** | H1, stats, description, galerie (lazy + dimensions), grille de produits, maillage interne |
118 117
119 −**Pages programmatiques** — une URL propre par recherche type :
120 −
121 −```
122 −/categorie/erable → Érable & miel du Québec (6 300+ produits, prix moyen/médian)
123 −/region/monteregie → Produits québécois — Montérégie
124 −/categorie/erable/region/estrie → Érable & miel — Estrie
125 −```
126 −
127 −~350 pages (20 catégories × 17 régions + combinaisons non vides), chacune avec H1,
128 −statistiques (nombre de produits, **prix moyen et médian**, fourchette), 24 produits
129 −en HTML, pagination crawlable et liens vers les pages voisines. Les routes React
130 −miroirs gardent l'expérience SPA (filtres verrouillés sur la dimension de l'URL).
131 −
132 −**URLs & statuts propres :**
133 −
134 −```
135 −/produits/sirop-d-erable-edition-limitee-…-b63130ffc8b18c8cc650 ← slug lisible + uid
136 −/produits/b63130ffc8b18c8cc650 → 301 vers l'URL slugée
137 −produit retiré du catalogue → 410 Gone + lien catégorie
138 −uid inconnu → 404 (fini le soft-404)
139 −```
140 −
141 −**Sitemaps & robots :** `/robots.txt` (bloque `/api/`, `/profil`) → `/sitemap.xml`
142 −(index) → `sitemap-pages.xml` + `sitemap-boutiques.xml` + `sitemap-produits-{1..8}.xml`
143 −(40 000 URLs/chunk, `lastmod` réel, régénérés automatiquement, cache 1 h).
118 +**URLs & statuts propres** : slug lisible + uid (`/produits/sirop-d-erable-…-b63130ffc8b18c8cc650`), **301** de l'uid nu vers l'URL slugée, **410 Gone** pour les produits retirés, **404** pour les uid inconnus — fini le soft-404.
144 119
145 −**Performance :** GZip (‑80 % sur le HTML), `Cache-Control: immutable` sur les assets
146 −hashés, images `loading="lazy"` avec dimensions explicites, polices en `swap`.
120 +**Sitemaps & robots** : `/robots.txt` → `/sitemap.xml` (index) → `sitemap-pages.xml` + `sitemap-boutiques.xml` + `sitemap-produits-{1..8}.xml` (**40 000 URLs/chunk**, `lastmod` réel, régénérés automatiquement, cache 1 h).
147 121
148 −<details>
149 −<summary><b>Vérifier soi-même (curl)</b></summary>
122 +**Performance** : **GZip** (‑80 % sur le HTML), `Cache-Control: immutable` sur les assets hashés, images `loading="lazy"` avec dimensions explicites, polices en `swap`.
150 123
151 −```bash
152 −curl -s https://www.fabri-ka.com/categorie/erable | grep -o '<h1>[^<]*</h1>'
153 −# <h1>Érable &amp; miel du Québec</h1>
154 −
155 −curl -s https://www.fabri-ka.com/produits/b63130ffc8b18c8cc650 -o /dev/null -w '%{http_code} %{redirect_url}\n'
156 −# 301 https://www.fabri-ka.com/produits/sirop-d-erable-edition-limitee-…
124 +## API
157 125
158 −curl -s https://www.fabri-ka.com/sitemap.xml | grep -c '<sitemap>'
159 −# 10
160 −```
161 −</details>
126 +| Endpoint | Description |
127 +|---|---|
128 +| `GET /api/products?q=&category=&region=&origin=&price_min=&price_max=&sort=&page=` | Recherche plein-texte + filtres, triée |
129 +| `GET /api/products/{uid}` | Fiche produit (galerie, boutique, produits liés) |
130 +| `GET /api/stores?region=&q=&with_products=` | Répertoire des boutiques (logo, région, plateforme) |
131 +| `GET /api/stores/{id}` | Fiche boutique enrichie : stats de prix, catégories, boutiques similaires |
132 +| `GET /api/facets` | Catégories/régions/origines avec compteurs |
133 +| `GET /api/stats` · `GET /api/stats/extended` | Totaux, ventilation régionale · stats riches (médianes, histogrammes, croissance) |
134 +| `GET /api/report.pdf` | Rapport de marché PDF — généré à la volée |
135 +| `POST /api/sync` | Déclenche une synchronisation en arrière-plan |
136 +| `GET /api/auth/ka/login` → `…/callback` · `GET /api/auth/me` · `POST /api/auth/logout` | SSO **KA ID** |
137 +| `GET /api/favorites` · `POST /api/favorites/toggle` | Favoris « Mon univers Ka » (hub central) |
138 +| `GET /robots.txt` · `GET /sitemap.xml` (+ sous-sitemaps) | Infrastructure SEO |
162 139
163 −## Écosystème Groupe KA
140 +## Classification d'origine
164 141
165 −Fabri-Ka fait partie du **Groupe KA** (immo-ka, ora-ka, …) et partage son
166 −infrastructure de comptes :
142 +| Classe | Signification |
143 +|---|---|
144 +| **A** | Fabriqué / cultivé / transformé au Québec |
145 +| **B** | Conçu au Québec, fabriqué ailleurs |
146 +| **C** | Détaillant québécois (revente) |
147 +| **D** | Mixte |
148 +| **E** | Incertain — à vérifier |
167 149
168 −- **KA ID (SSO)** — « Se connecter avec KA ID » : flot `authorize → callback` avec
169 − JWT HS256 signé d'un secret partagé, vérifié en stdlib pure (hmac/hashlib —
170 − aucune dépendance), session locale en cookie httpOnly signé 30 jours.
171 − Le même `ka_id` identifie le membre sur toutes les plateformes du groupe.
172 −- **Favoris « Mon univers Ka »** — aucun stockage local : chaque ♥ est poussé/lu
173 − au hub central (groupe-ka.com) via requêtes signées HMAC-SHA256, cache 30 s,
174 − invalidation au toggle. Le hub est l'unique source de vérité.
175 −- **Profil** — la page `/profil` affiche le profil Groupe KA (bio, ville, réseaux),
176 − source de vérité : le hub.
150 +Chaque classe est justifiée par une **évidence conservée** — jamais déduite du seul fait qu'une entreprise « semble » québécoise.
177 151
178 −## Chiffres (2026-08-13)
152 +## Chiffres (2026-08-17, site live)
179 153
180 154 | Mesure | Valeur |
181 155 |---|---|
182 −| Domaines candidats découverts et dédupliqués | 3 481 |
156 +| Produits agrégés (catalogues complets) | **291 557** |
157 +| Boutiques avec produits en ligne | **1 265** |
158 +| Régions administratives couvertes | **17 / 17** |
183 159 | Boutiques québécoises actives vérifiées (registre) | **3 224** |
184 160 | — avec ecommerce détecté | 1 970+ |
185 −| Produits agrégés (catalogues complets) | **291 017** |
186 −| — avec prix | 285 316 (médiane 29,95 $ · moyenne 297 $) |
187 −| Boutiques avec produits en ligne | **1 266** |
188 −| Régions administratives couvertes | **17 / 17** |
189 −| Catégories | 20 (mode 38 k · bijoux 34 k · épicerie fine 29 k · …) |
161 +| Domaines candidats découverts et dédupliqués | 3 481 |
162 +| Catégories | **20** (mode 38 k · bijoux 34 k · épicerie fine 29 k · …) |
190 163 | Pages indexables (produits + boutiques + programmatiques) | **292 000+** |
191 164
192 −Détails, méthodologie, taux de découverte marginal et angles morts :
193 −[`deliverables/research_report.md`](deliverables/research_report.md) ·
194 −stratégie de découverte continue : [`deliverables/discovery_strategy.md`](deliverables/discovery_strategy.md).
165 +Détails et méthodologie : [`deliverables/research_report.md`](deliverables/research_report.md) · stratégie de découverte continue : [`deliverables/discovery_strategy.md`](deliverables/discovery_strategy.md).
195 166
196 167 ## Structure du projet
197 168
198 169 ```
199 −qc-store/
170 +fabri-ka/
200 171 ├── fabrika/ # plateforme
201 172 │ ├── web.py # API FastAPI + service du frontend + routes SEO
202 173 │ ├── seo.py # rendu serveur : meta, JSON-LD, sitemaps, 301/404/410
@@ -212,11 +183,11 @@ qc-store/
212 183 ├── scripts/ # pipeline de découverte (harvest → verify → registry)
213 184 ├── data/ # stores.json (registre) · fabrika.db · caches (non versionnés)
214 185 ├── deliverables/ # rapport de recherche, CSV des boutiques, sources
215 −├── docs/screenshots/ # captures de ce README
186 +├── docs/ # captures d'écran de ce README
216 187 └── run.py # CLI : sync · serve · watch
217 188 ```
218 189
219 −## Démarrage rapide
190 +## Démarrage local
220 191
221 192 ```bash
222 193 git clone https://git.spboucher.ai/fabri-ka.git && cd fabri-ka
@@ -241,39 +212,11 @@ EOF
241 212 .venv/bin/python run.py watch 360 # resynchronisation en boucle (minutes)
242 213 ```
243 214
244 −## API
215 +## Déploiement
245 216
246 −| Endpoint | Description |
247 −|---|---|
248 −| `GET /api/products?q=&category=&region=&origin=&price_min=&price_max=&sort=&page=` | Recherche plein-texte + filtres, triée |
249 −| `GET /api/products/{uid}` | Fiche produit (galerie, boutique, produits liés) |
250 −| `GET /api/stores?region=&q=&with_products=` | Répertoire des boutiques (logo, région, plateforme) |
251 −| `GET /api/stores/{id}` | Fiche boutique enrichie : stats de prix, catégories, boutiques similaires |
252 −| `GET /api/facets` | Catégories/régions/origines avec compteurs |
253 −| `GET /api/stats` · `GET /api/stats/extended` | Totaux, ventilation régionale · stats riches (médianes, histogrammes, croissance) |
254 −| `GET /api/report.pdf` | Rapport de marché PDF — généré à la volée |
255 −| `POST /api/sync` | Déclenche une synchronisation en arrière-plan |
256 −| `GET /api/auth/ka/login` → `…/callback` · `GET /api/auth/me` · `POST /api/auth/logout` | SSO KA ID |
257 −| `GET /api/favorites` · `POST /api/favorites/toggle` | Favoris « Mon univers Ka » (hub central) |
258 −| `GET /robots.txt` · `GET /sitemap.xml` (+ sous-sitemaps) | Infrastructure SEO |
217 +En production sur le **nœud M4M64a** du cluster **MacLustr** (répertoire `~/fabri-ka`), servi sur le **port 8097** et exposé via **ngrok** sur **[www.fabri-ka.com](https://www.fabri-ka.com)**.
259 218
260 −## Classification d'origine
261 −
262 −| Classe | Signification |
263 −|---|---|
264 −| **A** | Fabriqué / cultivé / transformé au Québec |
265 −| **B** | Conçu au Québec, fabriqué ailleurs |
266 −| **C** | Détaillant québécois (revente) |
267 −| **D** | Mixte |
268 −| **E** | Incertain — à vérifier |
269 −
270 −Chaque classe est justifiée par une **évidence conservée** (certification Aliments
271 −du Québec / Les Produits du Québec, adhésion à une association de producteurs,
272 −wording du site) — jamais déduite du seul fait qu'une entreprise « semble » québécoise.
273 −
274 −## Production
275 −
276 −Déployé sous **PM2** (3 processus) derrière **ngrok** sur un nœud du cluster MacLustr :
219 +**3 processus PM2 :**
277 220
278 221 ```
279 222 fabri-ka-web .venv/bin/python run.py serve 8097 # API + frontend + SSR SEO
@@ -281,35 +224,33 @@ fabri-ka-sync .venv/bin/python run.py watch 360 # resync aux 6 h
281 224 fabri-ka-ngrok ngrok http --url=www.fabri-ka.com 8097 # tunnel
282 225 ```
283 226
284 −Redéploiement : `rsync` du dépôt (en excluant `data/` — la prod garde sa base,
285 −resynchronisée en continu) puis `pm2 restart fabri-ka-web`.
227 +Redéploiement : build + **`pm2 restart fabri-ka-web`** (la prod garde sa base `data/` — resynchronisée en continu, jamais écrasée).
228 +
229 +## Développement remote-first (IMPORTANT)
230 +
231 +La **source de vérité est le repo git sur le nœud M4M64a** (`~/fabri-ka`) — **pas** une copie locale sur le laptop. Toute modification se fait **sur le nœud via SSH** : édition, build, `pm2 restart`, puis commit/push **depuis le nœud** (agent forwarding actif).
232 +
233 +- Remote `origin` = **spbgit** (git perso **[git.spboucher.ai](https://git.spboucher.ai)**), via l'alias SSH **`gitsrv`** : `gitsrv:srv/git/fabri-ka.git` — bare repo hébergé sur M3U96a.
234 +- **Ne pas éditer de copies laptop** ; référence complète : `~/Desktop/cluster-skill/KA-REMOTE-DEV.md`.
286 235
287 236 ## Principes
288 237
289 −1. **Politesse** — throttle global par plateforme (Shopify : 0,7 s/req toutes
290 − boutiques confondues), délais entre requêtes, User-Agent identifié.
291 −2. **Fidélité** — aucun prix inventé ; entités HTML décodées ; si la source ne
292 − publie pas une donnée, elle est `null`.
293 −3. **Traçabilité** — chaque produit renvoie vers la boutique d'origine ; chaque
294 − boutique conserve sa provenance de découverte et son évidence d'origine.
295 −4. **Robustesse** — une boutique qui casse n'affecte jamais les autres ;
296 − journal `sync_log` avec raison d'échec par boutique.
297 −5. **Trouvabilité** — tout ce qui existe dans la base existe pour Google :
298 − HTML complet, données structurées, sitemaps exhaustifs, jamais de soft-404.
238 +1. **Politesse** — throttle global par plateforme (Shopify : **0,7 s/req** toutes boutiques confondues), délais entre requêtes, User-Agent identifié.
239 +2. **Fidélité** — aucun prix inventé ; entités HTML décodées ; si la source ne publie pas une donnée, elle est `null`.
240 +3. **Traçabilité** — chaque produit renvoie vers la **boutique d'origine** ; chaque boutique conserve sa provenance de découverte et son évidence d'origine.
241 +4. **Robustesse** — une boutique qui casse n'affecte jamais les autres ; journal `sync_log` avec raison d'échec par boutique.
242 +5. **Trouvabilité** — tout ce qui existe dans la base existe pour Google : HTML complet, données structurées, sitemaps exhaustifs, jamais de soft-404.
299 243
300 244 ---
301 245
302 246 <div align="center">
303 247
304 −## Auteur
305 −
306 248 **Simon-Pierre Boucher**
307 249
308 250 [![Email](https://img.shields.io/badge/contact@spboucher.ai-1E1B16?style=for-the-badge&logo=minutemailer&logoColor=C4532E)](mailto:contact@spboucher.ai)
309 251 [![Git](https://img.shields.io/badge/git.spboucher.ai-1E1B16?style=for-the-badge&logo=git&logoColor=C4532E)](https://git.spboucher.ai)
310 252
311 −*Du recensement provincial (3 224 boutiques vérifiées, 35+ sources) au moteur de
312 −recherche indexable en production — conçu, construit et déployé en deux jours.*
253 +Un service **[Groupe Ka](https://www.groupe-ka.com)**
313 254
314 255 © 2026 Simon-Pierre Boucher — tous droits réservés.
315 256
added docs/screenshot.png +0 −0

Binary file not shown.