docs: README v3 — chiffres live vérifiés, pastilles dynamiques, sections complètes
1 changed file +149 −66
modified
README.md
+149 −66
@@ -6,25 +6,48 @@ | ||
| 6 | 6 | <h1 align="center">Resto·Ka</h1> |
| 7 | 7 | <p align="center"><b>Chaque resto, chaque plat, chaque prix</b></p> |
| 8 | 8 | |
| 9 | −<p align="center"> | |
| 10 | − <a href="https://www.resto-ka.com"><img src="https://img.shields.io/website?url=https%3A%2F%2Fwww.resto-ka.com&style=flat-square&label=www.resto-ka.com&up_color=f08c00&up_message=en%20ligne" alt="Site"></a> | |
| 11 | − <a href="https://www.resto-ka.com/doc/"><img src="https://img.shields.io/badge/📖_documentation-%2Fdoc-f08c00?style=flat-square" alt="Documentation"></a> | |
| 12 | − <a href="https://www.resto-ka.com/doc/resto-ka-documentation.pdf"><img src="https://img.shields.io/badge/guide-PDF-f08c00?style=flat-square" alt="PDF"></a> | |
| 13 | − <img src="https://img.shields.io/badge/n%C5%93ud-M3U96b-1f6feb?style=flat-square" alt="Nœud"> | |
| 14 | − <img src="https://img.shields.io/badge/port-8115-141814?style=flat-square" alt="Port"> | |
| 15 | − <img src="https://img.shields.io/badge/process-PM2-2b037a?style=flat-square" alt="PM2"> | |
| 16 | −</p> | |
| 17 | −<p align="center"> | |
| 18 | − <img src="https://img.shields.io/badge/Python-3.14-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python"> | |
| 19 | − <img src="https://img.shields.io/badge/FastAPI-API-009688?style=flat-square&logo=fastapi&logoColor=white" alt="FastAPI"> | |
| 20 | − <img src="https://img.shields.io/badge/React_18-Vite_+_TS-087EA4?style=flat-square&logo=react&logoColor=white" alt="React"> | |
| 21 | − <img src="https://img.shields.io/badge/SQLite-menus_+_prix-003B57?style=flat-square&logo=sqlite&logoColor=white" alt="SQLite"> | |
| 22 | − <img src="https://img.shields.io/badge/Groupe-KA-f08c00?style=flat-square" alt="Groupe KA"> | |
| 23 | −</p> | |
| 9 | +<div align="center"> | |
| 10 | + | |
| 11 | +<a href="https://www.resto-ka.com"><img src="https://img.shields.io/website?url=https%3A%2F%2Fwww.resto-ka.com&style=flat-square&label=www.resto-ka.com&up_color=f08c00&up_message=en%20ligne" alt="Site"></a> | |
| 12 | +<a href="https://www.resto-ka.com/healthz"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.resto-ka.com%2Fhealthz&query=%24.status&label=sant%C3%A9%20API&color=f08c00&style=flat-square" alt="Santé API (live)"></a> | |
| 13 | +<a href="https://www.resto-ka.com/doc/"><img src="https://img.shields.io/badge/📖_documentation-%2Fdoc-f08c00?style=flat-square" alt="Documentation"></a> | |
| 14 | +<a href="https://www.resto-ka.com/doc/resto-ka-documentation.pdf"><img src="https://img.shields.io/badge/guide-PDF-f08c00?style=flat-square" alt="PDF"></a> | |
| 15 | +<img src="https://img.shields.io/badge/n%C5%93ud-M3U96b-1f6feb?style=flat-square" alt="Nœud"> | |
| 16 | +<img src="https://img.shields.io/badge/port-8115-141814?style=flat-square" alt="Port"> | |
| 17 | +<img src="https://img.shields.io/badge/process-PM2-2b037a?style=flat-square" alt="PM2"> | |
| 18 | + | |
| 19 | +</div> | |
| 20 | + | |
| 21 | +<div align="center"> | |
| 22 | + | |
| 23 | +<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.resto-ka.com%2Fapi%2Fstats&query=%24.restaurants&label=restaurants&color=f08c00&style=flat-square" alt="Restaurants (live)"> | |
| 24 | +<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.resto-ka.com%2Fapi%2Fstats&query=%24.items&label=plats%20avec%20prix&color=f08c00&style=flat-square" alt="Plats avec prix (live)"> | |
| 25 | +<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.resto-ka.com%2Fapi%2Fstats&query=%24.with_menu&label=menus%20captur%C3%A9s&color=f08c00&style=flat-square" alt="Menus capturés (live)"> | |
| 26 | +<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.resto-ka.com%2Fapi%2Fstats&query=%24.chains&label=cha%C3%AEnes&color=f08c00&style=flat-square" alt="Chaînes (live)"> | |
| 27 | +<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.resto-ka.com%2Fapi%2Fstats&query=%24.regions&label=r%C3%A9gions&color=f08c00&style=flat-square" alt="Régions (live)"> | |
| 28 | +<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.resto-ka.com%2Fapi%2Fstats&query=%24.inspections&label=inspections%20MAPAQ&color=f08c00&style=flat-square" alt="Inspections MAPAQ (live)"> | |
| 29 | +<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.resto-ka.com%2Fapi%2Fstats&query=%24.with_alcohol_permit&label=permis%20alcool&color=f08c00&style=flat-square" alt="Permis d'alcool (live)"> | |
| 30 | +<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.resto-ka.com%2Fapi%2Fstats&query=%24.sources_registry&label=sources%20au%20registre&color=f08c00&style=flat-square" alt="Sources au registre (live)"> | |
| 31 | + | |
| 32 | +</div> | |
| 33 | + | |
| 34 | +<div align="center"> | |
| 35 | + | |
| 36 | +<img src="https://img.shields.io/badge/Python-3.14-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python"> | |
| 37 | +<img src="https://img.shields.io/badge/FastAPI-API-009688?style=flat-square&logo=fastapi&logoColor=white" alt="FastAPI"> | |
| 38 | +<img src="https://img.shields.io/badge/React_18-TypeScript-087EA4?style=flat-square&logo=react&logoColor=white" alt="React"> | |
| 39 | +<img src="https://img.shields.io/badge/Vite-5-646CFF?style=flat-square&logo=vite&logoColor=white" alt="Vite"> | |
| 40 | +<img src="https://img.shields.io/badge/SQLite-menus_+_prix-003B57?style=flat-square&logo=sqlite&logoColor=white" alt="SQLite"> | |
| 41 | +<img src="https://img.shields.io/badge/PM2-3_processus-2B037A?style=flat-square&logo=pm2&logoColor=white" alt="PM2"> | |
| 42 | +<img src="https://img.shields.io/badge/ngrok-tunnel-1F1E37?style=flat-square&logo=ngrok&logoColor=white" alt="ngrok"> | |
| 43 | +<img src="https://img.shields.io/badge/Groupe-KA-f08c00?style=flat-square" alt="Groupe KA"> | |
| 44 | +<img src="https://img.shields.io/badge/remote--first-spbgit-141814?style=flat-square" alt="remote-first spbgit"> | |
| 45 | + | |
| 46 | +</div> | |
| 24 | 47 | |
| 25 | 48 | **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 %). |
| 26 | 49 | |
| 27 | −**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. | |
| 50 | +**En chiffres** (live `/api/stats`, au 2026-08-24) : **14 716 restaurants actifs** (hors doublons, découverte OpenStreetMap, 17/17 régions), **149 569 plats avec prix**, **1 682 menus capturés** (1 268 takeout · 386 salle · 31 livraison), **180 chaînes identifiées** dont **116 intégrations UEAT découvertes**, 2 994 inspections MAPAQ importées, 1 859 restos avec permis d'alcool (RACJ), 155 312 entrées d'historique de prix, 80 % des items avec photo, 100 % des restos 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. | |
| 28 | 51 | |
| 29 | 52 | ## Visite guidée |
| 30 | 53 | |
@@ -46,7 +69,7 @@ | ||
| 46 | 69 | <td align="center"><img src="docs/screenshots/fiche.png" width="420"><br><sub><b>Fiche restaurant — menu structuré et prix contextualisés</b></sub></td> |
| 47 | 70 | </tr> |
| 48 | 71 | <tr> |
| 49 | − <td align="center"><img src="docs/screenshots/plats.png" width="420"><br><sub><b>Recherche par plat — 79 159 items, groupés par marque</b></sub></td> | |
| 72 | + <td align="center"><img src="docs/screenshots/plats.png" width="420"><br><sub><b>Recherche par plat — 149 569 items, groupés par marque</b></sub></td> | |
| 50 | 73 | <td align="center"><img src="docs/screenshots/stats.png" width="420"><br><sub><b>Tableau de bord /stats — le marché resto en chiffres</b></sub></td> |
| 51 | 74 | </tr> |
| 52 | 75 | </table> |
@@ -54,77 +77,134 @@ | ||
| 54 | 77 | ## Fonctionnalités |
| 55 | 78 | |
| 56 | 79 | - **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. |
| 57 | −- **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). | |
| 80 | +- **Recherche par plat** dans les 149 569 items (au 2026-08-24), groupée par marque (pour ne pas répéter la même poutine de chaîne des dizaines de fois). | |
| 58 | 81 | - **Options & formats capturés** avec leurs suppléments (« Mini +3,70 $ ») — ils changent le prix réel. |
| 59 | −- **Historique des prix par item** (`item_price_log`) à chaque changement. | |
| 82 | +- **Historique des prix par item** (`item_price_log`, 155 312 entrées au 2026-08-24) à chaque changement. | |
| 60 | 83 | - **Alerte de dérive** — chute anormale du volume d'une source ou du nombre d'items d'un menu → retraits suspendus / ancien menu conservé. |
| 61 | −- **Déduplication inter-sources** (les succursales ne sont jamais fusionnées) et **géocodage à 99 %** (Nominatim + Adresses Québec, cache persistant). | |
| 62 | −- **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…). | |
| 84 | +- **Déduplication inter-sources** (les succursales ne sont jamais fusionnées) et **géocodage à 100 %** (Nominatim + Adresses Québec, cache persistant). | |
| 85 | +- **Découverte OpenStreetMap** (API Overpass) : 13 427 établissements nommés au dernier passage — 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 **116 intégrations de chaînes découvertes** (Sushi Shop, Valentine, Normandin, Thaïzone, Chez Ashton…). | |
| 86 | +- **Découverte des sites web** des restos OSM (connecteur `site-finder`, Serper /maps) et **extraction des photos** depuis les sites des restos (`site-resto`). | |
| 87 | +- **Enrichissements officiels** : inspections MAPAQ (2 994 importées, 288 appariées à 204 restos) et permis d'alcool RACJ (1 859 restos). | |
| 88 | +- **Avis & notes** : Yelp par scraping quotidien (177 restos notés) et croisement Uber Eats (36 restos, prix marqués `delivery`). | |
| 63 | 89 | - **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). |
| 64 | −- **Registre des sources** — `data/sources.json`, à consulter avant tout ajout (statut et raison des sources non connectables). | |
| 90 | +- **Registre des sources** — `data/sources.json` (10 sources), à consulter avant tout ajout (statut et raison des sources non connectables). | |
| 91 | + | |
| 92 | +## Démarrage rapide | |
| 93 | + | |
| 94 | +```bash | |
| 95 | +# Backend | |
| 96 | +python3 -m venv .venv && .venv/bin/pip install -r requirements.txt | |
| 97 | + | |
| 98 | +# Frontend (build servi par FastAPI) | |
| 99 | +cd frontend && npm install && npm run build && cd .. | |
| 100 | +# ou en dev : cd frontend && npm run dev | |
| 101 | + | |
| 102 | +# Lancer | |
| 103 | +.venv/bin/python run.py sync # synchronise (+ géocode + dédup) | |
| 104 | +.venv/bin/python run.py serve 8115 # API + frontend sur :8115 | |
| 105 | +.venv/bin/python run.py watch 168 # boucle hebdomadaire (heures) | |
| 65 | 106 | |
| 66 | −## API (endpoints principaux) | |
| 107 | +# Tests (80 tests pytest, fixtures réelles hors ligne) | |
| 108 | +.venv/bin/python -m pytest tests/ | |
| 109 | +``` | |
| 110 | + | |
| 111 | +## API (endpoints) | |
| 67 | 112 | |
| 68 | 113 | Servis par `restoka/web.py` (FastAPI) sur le port 8115. |
| 69 | 114 | |
| 70 | −| Endpoint | Rôle | | |
| 71 | −|---|---| | |
| 72 | −| `GET /api/restaurants` | recherche de restos (ville, région, cuisine, texte libre, pagination) | | |
| 73 | −| `GET /api/restaurants/{uid}` | fiche complète : menu structuré par contexte de prix, photos, coordonnées | | |
| 74 | −| `GET /api/restaurants/{uid}/prices` | historique des prix des items du resto | | |
| 75 | −| `GET /api/restaurants/{uid}/inspections` | inspections/permis (enrichissements MAPAQ) | | |
| 76 | −| `GET /api/dishes` | recherche par plat dans les 79 159 items, groupée par marque | | |
| 77 | −| `GET /api/facets` · `GET /api/sources` | facettes de filtres, registre des sources | | |
| 78 | −| `GET /api/stats` · `/api/stats/dashboard` · `/report` · `/catalog` · `POST /api/stats/report/custom` | tableau de bord + rapports PDF (catalogue et personnalisés) | | |
| 79 | −| `GET /api/favorites` · `POST /api/favorites/toggle` | favoris « Mon univers Ka » (session KA ID) | | |
| 80 | −| `POST /api/sync` | déclenchement d'une synchronisation | | |
| 81 | −| `GET /healthz` | santé du service | | |
| 82 | −| `GET /doc/` | guide d'utilisation en ligne | | |
| 115 | +| Méthode | Endpoint | Description | | |
| 116 | +|---|---|---| | |
| 117 | +| `GET` | `/api/restaurants` | recherche de restos (ville, région, cuisine, texte libre, `uids=`, pagination) | | |
| 118 | +| `GET` | `/api/restaurants/{uid}` | fiche complète : menu structuré par contexte de prix, photos, coordonnées, horaires | | |
| 119 | +| `GET` | `/api/restaurants/{uid}/prices` | historique des prix des items du resto (`item_price_log`) | | |
| 120 | +| `GET` | `/api/restaurants/{uid}/inspections` | inspections/permis (enrichissements MAPAQ + RACJ) | | |
| 121 | +| `GET` | `/api/dishes` | recherche par plat dans les 149 569 items, groupée par marque | | |
| 122 | +| `GET` | `/api/facets` | facettes de filtres (régions, villes, cuisines, types) | | |
| 123 | +| `GET` | `/api/sources` | registre des sources (statuts, cadences) | | |
| 124 | +| `GET` | `/api/stats` | statistiques publiques JSON (alimente les pastilles ci-dessus) | | |
| 125 | +| `GET` | `/api/stats/dashboard` | données du tableau de bord `/stats` | | |
| 126 | +| `GET` | `/api/stats/report` | rapport PDF principal | | |
| 127 | +| `GET` | `/api/stats/catalog` | catalogue des rapports disponibles | | |
| 128 | +| `POST` | `/api/stats/report/custom` | rapport PDF personnalisé (ReportBuilder) | | |
| 129 | +| `GET` | `/api/favorites` | favoris « Mon univers Ka » (session KA ID) | | |
| 130 | +| `POST` | `/api/favorites/toggle` | ajout/retrait d'un favori | | |
| 131 | +| `POST` | `/api/sync` | déclenchement d'une synchronisation | | |
| 132 | +| `GET` | `/healthz` | santé du service (`{"status":"ok"}`) | | |
| 133 | +| `GET` | `/doc/` | guide d'utilisation en ligne | | |
| 134 | +| `GET` | `/{full_path}` | SPA + pages SSR légères (accueil, fiches JSON-LD, /villes) | | |
| 83 | 135 | |
| 84 | 136 | ## Connecteurs |
| 85 | 137 | |
| 86 | −Auto-enregistrés dans `restoka/connectors/` (requests direct / Firecrawl / Scrapfly + cache détail dans `base.py`, résilience `_resilient.py`) : | |
| 138 | +Auto-enregistrés dans `restoka/connectors/` (requests direct / Firecrawl / Scrapfly + cache détail dans `base.py`, résilience `_resilient.py`, chaîne anti-bot Oxylabs → Scrapfly → Bright Data) : | |
| 87 | 139 | |
| 88 | −| Connecteur | Rôle | | |
| 89 | −|---|---| | |
| 90 | −| `osm` | découverte OpenStreetMap (Overpass) — 13 500+ établissements nommés, 17/17 régions | | |
| 91 | −| `ueat` | connecteur templatisé UEAT (API GraphQL) — menus takeout réels de 29 intégrations de chaînes | | |
| 92 | −| `siteresto` | menus publiés sur le site des restos indépendants | | |
| 93 | −| `sitefinder` | découverte du site web / de la plateforme de commande d'un resto | | |
| 94 | −| `ubereats` | complément livraison (prix marqués `delivery`, jamais prioritaires sur un menu salle) | | |
| 95 | −| `yelp` · `yelp_scrape` | enrichissement annuaire via yelp.ca (notes, nombre d'avis, gamme de prix, catégories, fermetures) | | |
| 140 | +| Connecteur | Famille | Rôle | Cadence | | |
| 141 | +|---|---|---|---| | |
| 142 | +| `osm` | découverte | OpenStreetMap (Overpass, miroirs fiabilisés) — 13 427 établissements nommés, 17/17 régions | mensuelle | | |
| 143 | +| `ueat` | menus takeout (tier 1) | connecteur templatisé UEAT (API GraphQL) — menus takeout réels de 116 intégrations découvertes | hebdomadaire | | |
| 144 | +| `siteresto` | menus salle | menus + photos publiés sur le site des restos indépendants | hebdo (batch incrémental), re-crawl mensuel | | |
| 145 | +| `sitefinder` | découverte | sites web / plateformes de commande des restos OSM (Serper /maps) | hebdo par lots (3 000 req.), échecs re-sondés 180 j | | |
| 146 | +| `ubereats` | livraison | complément livraison (prix `delivery`, jamais prioritaires sur un menu salle) | quotidienne par petits lots (60 pages), re-vérif 30 j | | |
| 147 | +| `yelp` | annuaire | enrichissement via l'API Yelp Fusion (clé requise — SkipSource sans `YELP_API_KEY`) | hebdo, re-vérification 30 j | | |
| 148 | +| `yelp_scrape` | annuaire | notes, nombre d'avis, gamme de prix, catégories, fermetures via yelp.ca | quotidienne par petits lots (80 pages), re-vérif 30 j | | |
| 149 | + | |
| 150 | +S'y ajoutent deux **enrichissements officiels** exécutés par `ingest.enrich` (garde-fou 6 jours) : `mapaq` (inspections) et `racj` (permis d'alcool), tous deux hebdomadaires. | |
| 151 | + | |
| 152 | +## Données & conformité | |
| 153 | + | |
| 154 | +- **Registre des sources** : `data/sources.json` — **10 sources** au 2026-08-24 (8 actives, 1 « clé requise » : yelp, 1 « à faire » : sthubert). À consulter **avant** tout ajout de source (CLAUDE.md §0.4) : chaque entrée documente l'accès légal, l'extraction et la cadence. | |
| 155 | +- **Prix de première partie** : les menus takeout viennent de la plateforme de commande des restos eux-mêmes (UEAT — la même API GraphQL que le widget officiel, auth anonyme publique) ou de leur propre site — **prix réels non majorés**. Les menus salle (`site-resto`) et takeout passent toujours avant les plateformes de livraison. | |
| 156 | +- **Scraping poli** : throttling (0,35 s sur UEAT), User-Agent identifiable `RestoKaBot`, budgets par passage (Yelp 450 req/j, site-finder 3 000 req, Uber Eats 60 pages/j). | |
| 157 | +- **Données publiques officielles** : inspections MAPAQ et permis d'alcool RACJ (jeux de données gouvernementaux). | |
| 158 | +- **Cadence de resync** : boucle `run.py watch 168` (cycle hebdomadaire) ; les sources quotidiennes (yelp-scrape, ubereats) avancent par petits lots à chaque passage ; alertes de dérive + délai de grâce avant tout retrait. | |
| 159 | +- La base SQLite de prod (`data/restoka.db`) est **gitignorée** ; aucun secret dans le repo (`.env` local, gabarit `.env.example`). | |
| 96 | 160 | |
| 97 | 161 | ## Architecture |
| 98 | 162 | |
| 99 | 163 | Pipeline (patron Lou·Ka) : **connecteurs → normalisation → déduplication → SQLite → API/frontend**. |
| 100 | 164 | |
| 101 | −- **Backend Python 3.14 / FastAPI / Uvicorn** (`restoka/web.py`) : API + service du build Vite. | |
| 102 | −- **SQLite** (`restoka/db.py`) : restos, **menus par contexte de prix**, historique de prix. | |
| 165 | +- **Backend Python 3.14 / FastAPI / Uvicorn** (`restoka/web.py`) : API + service du build Vite + SSR léger SEO (JSON-LD Restaurant, sitemaps chunkés, pages /villes). | |
| 166 | +- **SQLite** (`restoka/db.py`) : restos, **menus par contexte de prix**, historique de prix (`item_price_log`), inspections, favoris, caches détail/géocodage. | |
| 103 | 167 | - **Connecteurs auto-enregistrés** (`restoka/connectors/`) : requests direct / Firecrawl / Scrapfly + cache détail (`base.py`), UEAT templatisé (`ueat.py`), découverte Overpass/OSM. |
| 104 | 168 | - **Ingestion** (`restoka/ingest.py`) : sync → geocode → dedup, délai de grâce et alertes de dérive ; enrichissements inspections/permis/heures. |
| 169 | +- **Structuration LLM** (`restoka/menullm.py`) : menus maison structurés par Claude (API Anthropic). | |
| 105 | 170 | - **Frontend React 18 + Vite + TypeScript** (`frontend/`), design « éditorial sharp » Groupe KA. |
| 106 | −- **45 tests pytest** avec fixtures réelles hors ligne. | |
| 171 | +- **80 tests pytest** avec fixtures réelles hors ligne (connecteurs, normalisation, schéma, horaires, permis…). | |
| 107 | 172 | |
| 108 | −Processus PM2 sur le nœud : | |
| 173 | +Processus PM2 sur le nœud (commandes de start réelles) : | |
| 109 | 174 | |
| 110 | −| Processus | Rôle | Cadence | | |
| 111 | −|---|---|---| | |
| 112 | −| `resto-ka` | serveur FastAPI (API + frontend) sur le port **8115** | continu | | |
| 113 | −| `resto-ka-sync` | boucle de synchronisation (`run.py watch 168`) | cycle hebdomadaire (168 h) | | |
| 114 | −| `resto-ka-ngrok` | tunnel ngrok vers **www.resto-ka.com** | continu | | |
| 175 | +| Processus | Rôle | Commande | Cadence | | |
| 176 | +|---|---|---|---| | |
| 177 | +| `resto-ka` | serveur FastAPI (API + frontend) sur le port **8115** | `.venv/bin/python run.py serve 8115` | continu | | |
| 178 | +| `resto-ka-sync` | boucle de synchronisation | `.venv/bin/python run.py watch 168` | cycle hebdomadaire (168 h) | | |
| 179 | +| `resto-ka-ngrok` | tunnel vers **www.resto-ka.com** | `ngrok http --url=www.resto-ka.com 8115` | continu | | |
| 115 | 180 | |
| 116 | −Points de configuration notables (variables d'environnement, sans secrets dans le repo) : clés Scrapfly/Firecrawl des connecteurs, secret SSO partagé avec le hub KA ID. Le registre des sources vit dans `data/sources.json` ; la base SQLite de prod est gitignorée. | |
| 181 | +## Variables d'environnement | |
| 182 | + | |
| 183 | +Gabarit : `.env.example` (copier vers `.env`, jamais commité). **Noms seulement — aucune valeur dans le repo.** | |
| 184 | + | |
| 185 | +| Variable | Rôle | | |
| 186 | +|---|---| | |
| 187 | +| `SCRAPFLY_KEY` | rendu JS + bypass anti-bot (plateformes de livraison) | | |
| 188 | +| `ANTHROPIC_API_KEY` | structuration des menus maison par Claude (`restoka/menullm.py`) | | |
| 189 | +| `FIRECRAWL_API_KEY` | rendu JS de secours pour les sites de restos SPA (`site-resto`) | | |
| 190 | +| `YELP_API_KEY` | API Yelp Fusion (sans clé : source sautée proprement) | | |
| 191 | +| `YELP_BUDGET` | budget de requêtes Yelp par passage (quota quotidien 500) | | |
| 192 | +| `SERPER_API_KEY` | Google Maps via Serper — découverte des sites web (`site-finder`) | | |
| 193 | +| `SITE_FINDER_BUDGET` | budget de requêtes Serper par passage (défaut 3 000) | | |
| 194 | +| `KA_SSO_SECRET` | SSO Groupe KA (« Se connecter avec KA ») | | |
| 195 | +| `SESSION_SECRET` | sessions signées | | |
| 196 | +| `RESTOKA_BASE_URL` | URL publique du site (défaut `https://www.resto-ka.com`) | | |
| 117 | 197 | |
| 118 | 198 | ## Structure du repo |
| 119 | 199 | |
| 120 | 200 | ``` |
| 121 | 201 | resto-ka/ |
| 122 | 202 | ├── run.py # point d'entrée CLI (sync / watch / serve) |
| 123 | −├── restoka/ # cœur Python : web, db, ingest, dedup, geocode, regions, schema, normalize, auth, stats… + connectors/ | |
| 203 | +├── restoka/ # cœur Python : web, db, ingest, dedup, geocode, regions, schema, normalize, auth, stats, menullm… + connectors/ | |
| 124 | 204 | ├── frontend/ # React 18 + Vite + TypeScript — design éditorial sharp Groupe KA + public/doc/ (guide) |
| 125 | −├── data/ # sources.json (registre) + base SQLite de prod (gitignorée) | |
| 205 | +├── data/ # sources.json (registre), ueat-discovered.json (116 intégrations), base SQLite de prod (gitignorée) | |
| 126 | 206 | ├── scripts/ # scripts d'appoint (captures, déploiement) |
| 127 | −├── tests/ # 45 tests pytest (fixtures réelles hors ligne) | |
| 207 | +├── tests/ # 80 tests pytest (fixtures réelles hors ligne) | |
| 128 | 208 | └── docs/ # captures d'écran + docs connecteurs |
| 129 | 209 | ``` |
| 130 | 210 | |
@@ -143,14 +223,6 @@ resto-ka/ | ||
| 143 | 223 | - `CLAUDE.md` est la source de vérité du projet (règles d'ingestion, en-têtes d'auteur obligatoires). |
| 144 | 224 | |
| 145 | 225 | ```bash |
| 146 | −python3 -m venv .venv && .venv/bin/pip install -r requirements.txt | |
| 147 | −cd frontend && npm install && npm run build && cd .. | |
| 148 | − | |
| 149 | −.venv/bin/python run.py sync # synchronise (+ géocode + dédup) | |
| 150 | −.venv/bin/python run.py serve 8115 # API + frontend | |
| 151 | −.venv/bin/python run.py watch 168 # boucle hebdomadaire (heures) | |
| 152 | −.venv/bin/python -m pytest tests/ # 45 tests | |
| 153 | − | |
| 154 | 226 | pm2 restart resto-ka # après un changement en production |
| 155 | 227 | ``` |
| 156 | 228 | |
@@ -161,6 +233,17 @@ pm2 restart resto-ka # après un changement en production | ||
| 161 | 233 | - **Processus PM2** : `resto-ka` (serveur) + `resto-ka-sync` (synchro) + `resto-ka-ngrok` (tunnel) |
| 162 | 234 | - **Domaine** : **https://www.resto-ka.com** (tunnel ngrok) |
| 163 | 235 | |
| 236 | +## Historique | |
| 237 | + | |
| 238 | +Jalons tirés du `git log` : | |
| 239 | + | |
| 240 | +- **2026-08-17** — naissance : pipeline connecteurs→SQLite→API (patron Lou·Ka), assets Groupe KA, tableau de bord `/stats` + rapport PDF, câblage du widget KA Agent. | |
| 241 | +- **2026-08-18** — vagues 2-3 d'enrichissement : inspections MAPAQ, horaires structurés, Yelp (API + scraping), avis/notes sans clé, menus livraison, permis d'alcool ; documentation standardisée des sources. | |
| 242 | +- **2026-08-19** — Stats v2 (dashboard complet + 5 rapports PDF), campagne mobile (menus tactiles, tabbar), KA Agent v2 plein écran, standard « panneau héro premier dans le DOM ». | |
| 243 | +- **2026-08-22** — SEO : SSR léger (JSON-LD Restaurant), sitemaps chunkés, robots.txt ; chaîne de fetch anti-bot résiliente (Oxylabs → Scrapfly → Bright Data) ; section « Récemment consultés ». | |
| 244 | +- **2026-08-23** — connecteur `site-finder` (Serper /maps), photos extraites des sites des restos, Stats v3 (rapports PDF personnalisés, ReportBuilder), favoris unifiés « Mon univers Ka », pages SEO /villes ; 32 → 116 intégrations UEAT découvertes. | |
| 245 | +- **2026-08-24** — page documentation `/doc` (guide + captures + PDF), refonte du README (v2 puis v3), mise à jour du répertoire UEAT. | |
| 246 | + | |
| 164 | 247 | ## Écosystème Groupe KA |
| 165 | 248 | |
| 166 | 249 | | Plateforme | Vocation | |
| 167 | 250 | |