# Fabri·Ka
### Tous les produits québécois. Un seul endroit.
**[www.fabri-ka.com](https://www.fabri-ka.com)**











*Agrégateur de découverte des produits vendus en ligne par les entreprises du Québec —
chaque produit renvoie vers la boutique d'origine. Aucune vente sur Fabri-Ka :
les prix, photos et stocks appartiennent aux marchands sources.*
---
## Aperçu
| Accueil | Catalogue | Boutiques |
|---|---|---|
|  |  |  |
| Page boutique (landing) | Statistiques |
|---|---|
|  |  |

Mobile-first : barre d'onglets, filtres en bottom sheet, galeries swipe, pages boutiques avec logo/couverture, page statistiques.
## Pourquoi Fabri-Ka ?
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, 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).
> 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.
## L'architecture en 30 secondes
```mermaid
flowchart LR
subgraph Discovery["Pipeline de découverte (scripts/)"]
A["30+ annuaires sources
certifications · associations ·
marques régionales · balayages"] --> B["harvest → aggregate →
verify → classify A–E"]
B --> R[("stores.json
3 131 boutiques QC")]
end
subgraph FabriKa["Plateforme (fabrika/)"]
R --> C["Connecteurs plateforme
Shopify · WooCommerce · Wix ·
Squarespace · Scrapfly/Firecrawl"]
C --> D[("SQLite + FTS5
hash + diff")]
D --> E["API FastAPI
/api/products · /api/facets"]
E --> F["React 18 + Vite
recherche · filtres · fiches"]
end
W["⏱ Watcher 6 h (PM2)"] -.-> C
F --> U["🍁 Acheteur local"]
```
| Couche | Rôle | Fichiers |
|---|---|---|
| **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` |
| **Vérification** | Plateforme ecommerce + test réel de l'endpoint catalogue + signaux de localisation QC (codes postaux, indicatifs, TLD, wording) | `scripts/verify.py` |
| **Classification** | Origine A–E avec évidence conservée (certifications → a priori ; wording du site → ajustement) | `scripts/build_registry.py` |
| **Connecteurs** | Shopify `products.json` (transport curl anti-429 TLS), WooCommerce Store API, Wix Stores GraphQL (jeton public), Squarespace `?format=json`, Firecrawl en secours | `fabrika/connectors/` |
| **Diff engine** | Upsert par hash de contenu, retraits avec délai de grâce (2 syncs) | `fabrika/db.py` |
| **API** | Recherche FTS5 accent-insensible, facettes, filtres catégorie/région/origine/prix, stats, sync | `fabrika/web.py` |
| **Frontend** | « Chaleur artisanale, précision éditoriale » — Fraunces + Outfit, crème/terracotta/pin, PWA-lite, fr-CA | `frontend/` |
## Chiffres (2026-08-12)
| Mesure | Valeur |
|---|---|
| Domaines candidats découverts et dédupliqués | 3 481 |
| Boutiques québécoises actives vérifiées | **3 131** |
| — avec ecommerce détecté | 1 970 |
| — connectables par un connecteur plateforme | 1 369 |
| Produits agrégés (catalogues complets) | **281 000+** |
| Boutiques avec produits en ligne | 1 204 |
| Régions administratives couvertes | **17 / 17** |
| Classes d'origine | A : 3 062 · C : 19 · E : 50 |
Détails, méthodologie, taux de découverte marginal et angles morts :
[`deliverables/research_report.md`](deliverables/research_report.md) ·
stratégie de découverte continue : [`deliverables/discovery_strategy.md`](deliverables/discovery_strategy.md).
## Démarrage rapide
```bash
git clone https://git.spboucher.ai/fabri-ka.git && cd fabri-ka
# Backend
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
# Frontend
cd frontend && npm install && npm run build && cd ..
# (optionnel) répertoires JS / sites anti-bot
echo "FIRECRAWL_API_KEY=fc-votre-cle" > .env
# Ingestion puis service
.venv/bin/python run.py sync # toutes les boutiques connectables
.venv/bin/python run.py serve 8090 # → http://localhost:8090
.venv/bin/python run.py watch 360 # resynchronisation en boucle (minutes)
```
## API
| Endpoint | Description |
|---|---|
| `GET /api/products?q=&category=®ion=&origin=&price_min=&price_max=&sort=&page=` | Recherche plein-texte + filtres, triée |
| `GET /api/products/{uid}` | Fiche produit (galerie, boutique, produits liés) |
| `GET /api/stores?region=&q=&with_products=` | Répertoire des boutiques (logo, région, plateforme) |
| `GET /api/stores/{id}` | Fiche boutique enrichie : logo, couverture, stats de prix, catégories, boutiques similaires |
| `GET /api/facets` | Catégories/régions/origines avec compteurs |
| `GET /api/stats` | Totaux, ventilation régionale, journal de sync |
| `GET /api/stats/extended` | Statistiques riches : prix (médian/moyen/histogramme), catégories, régions, plateformes, croissance, top boutiques |
| `GET /api/report.pdf` | Rapport de marché PDF (couverture de marque, KPIs, graphiques, tableaux) — généré à la volée |
| `POST /api/sync` | Déclenche une synchronisation en arrière-plan |
## Classification d'origine
| Classe | Signification |
|---|---|
| **A** | Fabriqué / cultivé / transformé au Québec |
| **B** | Conçu au Québec, fabriqué ailleurs |
| **C** | Détaillant québécois (revente) |
| **D** | Mixte |
| **E** | Incertain — à vérifier |
Chaque classe est justifiée par une **évidence conservée** (certification Aliments
du Québec / Les Produits du Québec, adhésion à une association de producteurs,
wording du site) — jamais déduite du seul fait qu'une entreprise « semble » québécoise.
## Production
Déployé sous **PM2** (3 processus) derrière **ngrok** sur le nœud M4M64a :
```
fabri-ka-web .venv/bin/python run.py serve 8097 # API + frontend
fabri-ka-sync .venv/bin/python run.py watch 360 # resync aux 6 h
fabri-ka-ngrok ngrok http --url=www.fabri-ka.com 8097 # tunnel
```
## Principes
1. **Politesse** — throttle global par plateforme (Shopify : 0,7 s/req toutes
boutiques confondues), délais entre requêtes, User-Agent identifié.
2. **Fidélité** — aucun prix inventé ; entités HTML décodées ; si la source ne
publie pas une donnée, elle est `null`.
3. **Traçabilité** — chaque produit renvoie vers la boutique d'origine ; chaque
boutique conserve sa provenance de découverte et son évidence d'origine.
4. **Robustesse** — une boutique qui casse n'affecte jamais les autres ;
journal `sync_log` avec raison d'échec par boutique.
---
## Auteur
**Simon-Pierre Boucher**
[](mailto:contact@spboucher.ai)
[](https://git.spboucher.ai)
*Conçu, construit et déployé en une journée — du recensement provincial
(3 131 boutiques vérifiées, 35+ sources) au moteur de recherche en production.*
© 2026 Simon-Pierre Boucher — tous droits réservés.