docs: refonte du README (pastilles + captures d écran à jour)
3 changed files +81 −75
modified
README.md
+81 −75
@@ -1,113 +1,119 @@ | ||
| 1 | −<!-- | |
| 2 | − Author: Simon-Pierre Boucher <contact@spboucher.ai> | |
| 3 | − File: README.md | |
| 4 | − Desc: Resto·Ka — agrégateur des restaurants du Québec (menus & prix). | |
| 5 | −--> | |
| 1 | +<!-- Auteur : Simon-Pierre Boucher — contact@spboucher.ai --> | |
| 6 | 2 | |
| 7 | 3 | # Resto·Ka |
| 8 | 4 | |
| 9 | −**Tous les restaurants du Québec — menus complets et prix réels, dans les 17 régions.** | |
| 5 | +**Tous les restaurants du Québec — menus complets et prix réels, comparables et cherchables dans les 17 régions.** | |
| 10 | 6 | |
| 11 | − | |
| 7 | +[](https://www.resto-ka.com) | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 12 | 11 | |
| 13 | − | |
| 14 | − | |
| 15 | − | |
| 16 | − | |
| 17 | − | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 18 | 17 | |
| 19 | −## Description | |
| 18 | +**Resto·Ka** ([www.resto-ka.com](https://www.resto-ka.com)) est l'**agrégateur exhaustif des restaurants du Québec** : chaque resto, chaque plat, chaque prix — dans les 17 régions administratives, au même endroit, comparable et cherchable **par resto ou par plat**. Les prix sont des **prix takeout réels, non majorés**, captés sur la plateforme de commande des restos eux-mêmes (pas sur les apps de livraison, majorées de 25-30 %). | |
| 20 | 19 | |
| 21 | −**Resto·Ka** ([**www.resto-ka.com**](https://www.resto-ka.com)) est l'**agrégateur exhaustif des restaurants du Québec** : chaque resto, chaque plat, chaque prix — dans les **17 régions administratives**, au même endroit, comparable et cherchable **par resto ou par plat**. | |
| 20 | +**En chiffres** (base de production) : **14 091 restaurants** référencés (découverte OpenStreetMap, 17/17 régions), **79 159 plats avec prix**, **738 restos avec menu complet**, **24 chaînes suivies**, 98 % des items avec photo, 99 % géolocalisés. Pour qui ? Quiconque veut répondre à « qu'est-ce que je mange, où, et combien ça coûte ? » sans ouvrir quinze applis — là où les apps de livraison majorent et où les annuaires (Google, Yelp) n'ont ni menus structurés ni prix comparables. | |
| 22 | 21 | |
| 23 | −- **14 091 restaurants** référencés (découverte **OpenStreetMap**, 17/17 régions) | |
| 24 | −- **79 159 plats avec prix** — des **prix takeout réels, non majorés**, captés sur la plateforme de commande des restos eux-mêmes (pas sur les apps de livraison, +25-30 %) | |
| 25 | −- **738 restos avec menu complet**, **24 chaînes suivies** | |
| 26 | −- **98 %** des items avec photo, **69 %** avec options, **99 %** géolocalisés | |
| 22 | +## Captures d'écran | |
| 27 | 23 | |
| 28 | −Plateforme de la famille **·Ka** (Lou·Ka, Immo·Ka, Auto·Ka, Food·Ka, Fabri·Ka, Sorti·Ka…). Architecture des connecteurs **calquée sur Lou·Ka**, identité visuelle **« éditorial sharp » du Groupe KA** (Space Grotesk / Inter / JetBrains Mono, papier-encre-lime, bordures encre + ombres décalées). **`CLAUDE.md` est la source de vérité du projet.** | |
| 24 | +<p align="center"> | |
| 25 | + <img src="docs/screenshots/resto-ka-desktop.png" width="640" alt="Accueil — desktop"> | |
| 26 | + <img src="docs/screenshots/resto-ka-mobile.png" width="200" alt="Accueil — mobile"> | |
| 27 | +</p> | |
| 29 | 28 | |
| 30 | 29 | ## Fonctionnalités |
| 31 | 30 | |
| 32 | −- **Prix réels et contextualisés** : un prix n'est **JAMAIS** présenté sans son contexte (**`dine-in` / `takeout` / `delivery`**) — un menu sans `price_context`/`price_source` est **rejeté à l'ingestion**, et un menu salle n'est jamais écrasé par un menu livraison. | |
| 33 | −- **Recherche par plat** dans les **79 159 items**, **groupée par marque** (pour ne pas répéter 76 fois la même poutine de chaîne). | |
| 34 | −- **Options & formats capturés** avec leurs suppléments (« Mini **+3,70 $** ») — ils changent le prix réel. | |
| 31 | +- **Prix réels et contextualisés** — un prix n'est jamais présenté sans son contexte (`dine-in` / `takeout` / `delivery`) ; un menu sans `price_context`/`price_source` est rejeté à l'ingestion, et un menu salle n'est jamais écrasé par un menu livraison. | |
| 32 | +- **Recherche par plat** dans les 79 159 items, groupée par marque (pour ne pas répéter 76 fois la même poutine de chaîne). | |
| 33 | +- **Options & formats capturés** avec leurs suppléments (« Mini +3,70 $ ») — ils changent le prix réel. | |
| 35 | 34 | - **Historique des prix par item** (`item_price_log`) à chaque changement. |
| 36 | −- **Alerte de dérive** : chute anormale du volume d'une source ou du nombre d'items d'un menu → retraits suspendus / ancien menu conservé. | |
| 35 | +- **Alerte de dérive** — chute anormale du volume d'une source ou du nombre d'items d'un menu → retraits suspendus / ancien menu conservé. | |
| 37 | 36 | - **Déduplication inter-sources** (les succursales ne sont jamais fusionnées) et **géocodage à 99 %** (Nominatim + Adresses Québec, cache persistant). |
| 38 | −- **Connexion KA ID** (SSO Groupe Ka), favoris, tableau de bord **Stats** + rapport **PDF**, widget **KA Agent** (chat IA). | |
| 37 | +- **Découverte OpenStreetMap** (API Overpass) : 13 500+ établissements nommés — restos, fast-foods, cafés, bars, crèmeries, boulangeries — dans les 17 régions ; **connecteur UEAT templatisé** (API GraphQL) pour les menus takeout réels de 29 intégrations de chaînes (Sushi Shop, Valentine, Normandin, Thaïzone, Chez Ashton…). | |
| 38 | +- **Connexion KA ID** (SSO Groupe KA), favoris unifiés « Mon univers Ka », tableau de bord `/stats` + rapports PDF (catalogue + ReportBuilder), widget **KA Agent** (chat IA). | |
| 39 | +- **Registre des sources** — `data/sources.json`, à consulter avant tout ajout (statut et raison des sources non connectables). | |
| 39 | 40 | |
| 40 | −| Accueil — recherche de restos | Recherche par plat | | |
| 41 | −|---|---| | |
| 42 | −|  |  | | |
| 41 | +## Architecture | |
| 43 | 42 | |
| 44 | −| Fiche resto — menu, photos, options & prix | Couverture en direct | | |
| 45 | −|---|---| | |
| 46 | −|  |  | | |
| 43 | +Pipeline (patron Lou·Ka) : **connecteurs → normalisation → déduplication → SQLite → API/frontend**. | |
| 47 | 44 | |
| 48 | −## Stack technique | |
| 45 | +- **Backend Python 3.14 / FastAPI / Uvicorn** (`restoka/web.py`) : API + service du build Vite. | |
| 46 | +- **SQLite** (`restoka/db.py`) : restos, **menus par contexte de prix**, historique de prix. | |
| 47 | +- **Connecteurs auto-enregistrés** (`restoka/connectors/`) : requests direct / Firecrawl / Scrapfly + cache détail (`base.py`), UEAT templatisé (`ueat.py`), découverte Overpass/OSM. | |
| 48 | +- **Ingestion** (`restoka/ingest.py`) : sync → geocode → dedup, délai de grâce et alertes de dérive ; enrichissements inspections/permis/heures. | |
| 49 | +- **Frontend React 18 + Vite + TypeScript** (`frontend/`), design « éditorial sharp » Groupe KA. | |
| 50 | +- **45 tests pytest** avec fixtures réelles hors ligne. | |
| 49 | 51 | |
| 50 | −- **Backend** : **Python 3.14** · **FastAPI** · **Uvicorn** · **SQLite** (menus par contexte + historique de prix) | |
| 51 | −- **Frontend** : **React 18** · **Vite** · **TypeScript** — design éditorial sharp Groupe KA | |
| 52 | −- **Scraping/ingestion** : requests direct / **Firecrawl** / **Scrapfly**, API **Overpass** (OSM), API **GraphQL UEAT** | |
| 53 | −- **Tests** : **45 tests pytest** (fixtures réelles hors ligne) | |
| 52 | +Processus PM2 sur le nœud : | |
| 54 | 53 | |
| 55 | −## Structure (patron Lou·Ka) | |
| 54 | +| Processus | Rôle | | |
| 55 | +|---|---| | |
| 56 | +| `resto-ka` | serveur FastAPI (API + frontend) sur le port **8115** | | |
| 57 | +| `resto-ka-sync` | boucle de synchronisation hebdomadaire (`run.py watch`) | | |
| 58 | +| `resto-ka-ngrok` | tunnel ngrok vers **www.resto-ka.com** | | |
| 59 | + | |
| 60 | +## Structure du repo | |
| 56 | 61 | |
| 57 | 62 | ``` |
| 58 | −restoka/ | |
| 59 | −├── connectors/ # un module par source/plateforme, auto-enregistrés | |
| 60 | −│ ├── base.py # requests direct / Firecrawl / Scrapfly + cache détail | |
| 61 | −│ └── ueat.py # UEAT (templatisé) — API GraphQL, prix TAKEOUT réels | |
| 62 | −├── schema.py # Restaurant + menu imbriqué (sections→items→options) + finalize() | |
| 63 | −├── normalize.py # prix, cuisines, type d'établissement, diètes, $-$$$$ | |
| 64 | −├── regions.py # ville → 17 régions (+ repli postal, + repli lat/lng) | |
| 65 | −├── db.py # SQLite : restos, menus PAR CONTEXTE, historique de prix | |
| 66 | −├── ingest.py # pipeline sync → geocode → dedup (délai de grâce, alertes) | |
| 67 | −├── dedup.py # identité resto inter-sources (succursales jamais fusionnées) | |
| 68 | −├── geocode.py # Nominatim + Adresses Québec, cache persistant | |
| 69 | −├── auth.py # connexion KA ID (SSO Groupe Ka) | |
| 70 | −└── web.py # FastAPI + frontend React (frontend/dist) | |
| 71 | −frontend/ # Vite + React 18 + TS — design éditorial sharp Groupe KA | |
| 63 | +resto-ka/ | |
| 64 | +├── run.py # point d'entrée CLI (sync / watch / serve) | |
| 65 | +├── restoka/ # cœur Python : web, db, ingest, dedup, geocode, regions, schema, normalize, auth, stats… + connectors/ | |
| 66 | +├── frontend/ # React 18 + Vite + TypeScript — design éditorial sharp Groupe KA | |
| 67 | +├── data/ # sources.json (registre) + base SQLite de prod (gitignorée) | |
| 68 | +├── scripts/ # scripts d'appoint (captures, déploiement) | |
| 69 | +├── tests/ # 45 tests pytest (fixtures réelles hors ligne) | |
| 70 | +└── docs/ # captures d'écran + docs connecteurs | |
| 72 | 71 | ``` |
| 73 | 72 | |
| 74 | −## Sources connectées | |
| 75 | − | |
| 76 | −Registre : **`data/sources.json`** (à consulter **AVANT** d'ajouter quoi que ce soit). | |
| 73 | +## Développement (remote-first) | |
| 77 | 74 | |
| 78 | −| Source | Palier | Contexte de prix | Couverture | | |
| 79 | −|--------|--------|------------------|------------| | |
| 80 | −| **OpenStreetMap** (découverte, API Overpass) | 4 | — (fiches sans menu) | **13 500+ établissements** : tous les restos, fast-foods, cafés, bars, crèmeries et boulangeries nommés du Québec — **17/17 régions**. Données © contributeurs OSM (ODbL). | | |
| 81 | −| **UEAT** (commande en ligne, API GraphQL anonyme) | 1 | **`takeout` (prix réels)** | **29 intégrations** : Sushi Shop (141), Poulet Rouge (82), Valentine (76), Normandin (44), Chocolats Favoris (41), Allô mon Coco (34), Thaïzone (26), Scores (25), Chez Ashton (23), Pacini (20), Boustan (65), Ben & Florentine (54), Pizzéria NO.900 (32), Sushi Taxi (30), Tutti Frutti, Mandy's, Cochon Dingue, Panda Boba-T, Salvatoré, Ryu Sushi, Impérial, La Belle Province, Madisons, Pizza Mia, Station W, Freddy, Le Super Qualité, Château Frontenac | | |
| 82 | −| St-Hubert | 6 | `takeout` (visé) | à faire — anti-bot Akamai, voir `data/sources.json` | | |
| 75 | +**La source de vérité est le repo git sur le nœud M3U96b** (`~/apps/resto-ka`) — on n'édite jamais les copies laptop. Toute modification se fait sur le nœud via SSH : édition, build, `pm2 restart`, puis commit/push depuis le nœud. | |
| 83 | 76 | |
| 84 | −## Démarrage local | |
| 77 | +- Remote `origin` = **spbgit** (git perso [git.spboucher.ai](https://git.spboucher.ai), bare repos sur M3U96a). **Pas GitHub.** | |
| 78 | +- L'agent forwarding SSH est actif : le `git push origin main` fonctionne pendant une session SSH depuis le laptop. | |
| 79 | +- `CLAUDE.md` est la source de vérité du projet (règles d'ingestion, en-têtes d'auteur obligatoires). | |
| 85 | 80 | |
| 86 | 81 | ```bash |
| 87 | 82 | python3 -m venv .venv && .venv/bin/pip install -r requirements.txt |
| 88 | 83 | cd frontend && npm install && npm run build && cd .. |
| 89 | 84 | |
| 90 | 85 | .venv/bin/python run.py sync # synchronise (+ géocode + dédup) |
| 91 | −.venv/bin/python run.py serve 8115 # API + frontend sur :8115 | |
| 92 | −.venv/bin/python run.py watch 168 # boucle hebdomadaire | |
| 93 | −.venv/bin/python -m pytest tests/ # 45 tests (fixtures réelles hors ligne) | |
| 86 | +.venv/bin/python run.py serve 8115 # API + frontend | |
| 87 | +.venv/bin/python run.py watch 168 # boucle hebdomadaire (heures) | |
| 88 | +.venv/bin/python -m pytest tests/ # 45 tests | |
| 89 | + | |
| 90 | +pm2 restart resto-ka # après un changement en production | |
| 94 | 91 | ``` |
| 95 | 92 | |
| 96 | 93 | ## Déploiement |
| 97 | 94 | |
| 98 | −- **Nœud** : **M3U96b** (cluster MacLustr), répertoire **`~/apps/resto-ka`** | |
| 99 | −- **Port** : **8115** | |
| 100 | −- **Domaine** : **[www.resto-ka.com](https://www.resto-ka.com)** (tunnel **ngrok**) | |
| 101 | −- **PM2** (3 process) : **`resto-ka`** (serveur :8115) + **`resto-ka-sync`** (synchro hebdomadaire) + **`resto-ka-ngrok`** (tunnel → www.resto-ka.com) | |
| 102 | −- Registre cross-session : `~/Desktop/cluster-skill/cluster-deployments.json` | |
| 103 | − | |
| 104 | −## Développement remote-first | |
| 105 | − | |
| 106 | −**La source de vérité est le repo git sur le nœud M3U96b** (`~/apps/resto-ka`), **PAS** les copies laptop. Toute modification se fait **sur le nœud via SSH** : édition, build, `pm2 restart resto-ka`, puis `git add/commit/push origin main` **sur le nœud** (agent forwarding actif). | |
| 107 | − | |
| 108 | −- Remote **`origin`** = **spbgit** (git perso **git.spboucher.ai** — bare repo `~/srv/git/resto-ka.git` sur M3U96a, alias SSH `gitsrv`). **PAS GitHub.** | |
| 109 | −- Référence complète : `~/Desktop/cluster-skill/KA-REMOTE-DEV.md`. | |
| 95 | +- **Nœud** : M3U96b (Mac Studio, cluster MacLustr) — répertoire `~/apps/resto-ka` | |
| 96 | +- **Port** : **8115** (local, exposé uniquement via le tunnel) | |
| 97 | +- **Processus PM2** : `resto-ka` (serveur) + `resto-ka-sync` (synchro) + `resto-ka-ngrok` (tunnel) | |
| 98 | +- **Domaine** : **https://www.resto-ka.com** (tunnel ngrok) | |
| 99 | + | |
| 100 | +## Écosystème Groupe KA | |
| 101 | + | |
| 102 | +- [groupe-ka.com](https://www.groupe-ka.com) — portail du groupe et compte unique KA ID | |
| 103 | +- [lou-ka.com](https://www.lou-ka.com) — logements à louer | |
| 104 | +- [immo-ka.com](https://www.immo-ka.com) — propriétés à vendre | |
| 105 | +- [vrai-prix.com](https://www.vrai-prix.com) — estimation immobilière | |
| 106 | +- [auto-ka.com](https://www.auto-ka.com) — véhicules | |
| 107 | +- [fabri-ka.com](https://www.fabri-ka.com) — produits québécois | |
| 108 | +- [food-ka.com](https://www.food-ka.com) — épicerie et alimentation | |
| 109 | +- [resto-ka.com](https://www.resto-ka.com) — restaurants *(ce repo)* | |
| 110 | +- [sorti-ka.com](https://www.sorti-ka.com) — sorties et événements | |
| 111 | +- [job-ka.com](https://www.job-ka.com) — emplois | |
| 112 | +- [crea-ka.com](https://www.crea-ka.com) — créateurs de contenu | |
| 113 | +- [trouve-ka.com](https://www.trouve-ka.com) — petites annonces | |
| 114 | +- [api-ka.com](https://www.api-ka.com) — API de données | |
| 110 | 115 | |
| 111 | 116 | --- |
| 112 | 117 | |
| 113 | −Un service **[Groupe Ka](https://www.groupe-ka.com)** — Auteur : Simon-Pierre Boucher \<contact@spboucher.ai\>. | |
| 118 | +© Groupe KA — Simon-Pierre Boucher · contact@spboucher.ai | |
| 119 | +Ce repo vit sur **spbgit** ([git.spboucher.ai](https://git.spboucher.ai)). | |
added
docs/screenshots/resto-ka-desktop.png
+0 −0
Binary file not shown.
added
docs/screenshots/resto-ka-mobile.png
+0 −0
Binary file not shown.