Resto·Ka — Chaque resto, chaque plat, chaque prix

Resto·Ka

Chaque resto, chaque plat, chaque prix

Site Santé API (live) Documentation PDF Nœud Port PM2
Restaurants (live) Plats avec prix (live) Menus capturés (live) Chaînes (live) Régions (live) Inspections MAPAQ (live) Permis d'alcool (live) Sources au registre (live)
Python FastAPI React Vite SQLite PM2 ngrok Groupe KA remote-first spbgit
**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 %). **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. ## Visite guidée *Captures du 2026-08-25 — front-end v2 « éditorial premium » (mobile 390×844 · desktop 1440×900).* ### Mobile
Accueil mobile
Accueil — recherche resto ou plat, KA Tabbar
Résultats mobile
Restos de Montréal
Fiche resto mobile
Fiche restaurant — menu complet, prix réels
Stats mobile
Statistiques
Villes mobile
Répertoire des villes
Menu mobile
Nav v2 — panneau plein écran
### Desktop
Accueil desktop
Accueil — bande « signes vitaux » encre, héros typographique
Résultats desktop
Résultats — cartes à filets d'encre, ombre safran au survol
Fiche resto
Fiche restaurant — infos structurées + lien commande
Menu du resto
Menu structuré — plats, formats, prix contextualisés
Villes
Répertoire des villes (pages SEO)
Stats
Statistiques — 21 200+ restos, 18 régions
### Nouveautés front-end (2026-08-25) - **Front-end v2 « éditorial premium »** — bande signes vitaux pleine largeur (chiffres géants tabulaires sur fond encre), nav soulignée, héros typographique agrandi, cartes/plats/menus/filtres allégés (filets d'encre au lieu de boîtes), ombre safran signature au survol. - **KA Tabbar v1** — barre de navigation mobile commune Groupe KA. - **7 nouvelles sources** — mtl-alim, Tastet, ChowNow, GloriaFood, Square, DoorDash, Skip + hub de découverte multi-plateformes. - **Widget ka-agent v4** — cartes de restos cliquables et choix en boutons. > 🗄️ Les captures d'époque sont conservées dans [`docs/archive/`](docs/archive/). ## Fonctionnalités - **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. - **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). - **Options & formats capturés** avec leurs suppléments (« Mini +3,70 $ ») — ils changent le prix réel. - **Historique des prix par item** (`item_price_log`, 155 312 entrées au 2026-08-24) à chaque changement. - **Alerte de dérive** — chute anormale du volume d'une source ou du nombre d'items d'un menu → retraits suspendus / ancien menu conservé. - **Déduplication inter-sources** (les succursales ne sont jamais fusionnées) et **géocodage à 100 %** (Nominatim + Adresses Québec, cache persistant). - **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…). - **Découverte des sites web** des restos OSM (connecteur `site-finder`, Serper /maps) et **extraction des photos** depuis les sites des restos (`site-resto`). - **Enrichissements officiels** : inspections MAPAQ (2 994 importées, 288 appariées à 204 restos) et permis d'alcool RACJ (1 859 restos). - **Avis & notes** : Yelp par scraping quotidien (177 restos notés) et croisement Uber Eats (36 restos, prix marqués `delivery`). - **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). - **Registre des sources** — `data/sources.json` (10 sources), à consulter avant tout ajout (statut et raison des sources non connectables). ## Démarrage rapide ```bash # Backend python3 -m venv .venv && .venv/bin/pip install -r requirements.txt # Frontend (build servi par FastAPI) cd frontend && npm install && npm run build && cd .. # ou en dev : cd frontend && npm run dev # Lancer .venv/bin/python run.py sync # synchronise (+ géocode + dédup) .venv/bin/python run.py serve 8115 # API + frontend sur :8115 .venv/bin/python run.py watch 168 # boucle hebdomadaire (heures) # Tests (80 tests pytest, fixtures réelles hors ligne) .venv/bin/python -m pytest tests/ ``` ## API (endpoints) Servis par `restoka/web.py` (FastAPI) sur le port 8115. | Méthode | Endpoint | Description | |---|---|---| | `GET` | `/api/restaurants` | recherche de restos (ville, région, cuisine, texte libre, `uids=`, pagination) | | `GET` | `/api/restaurants/{uid}` | fiche complète : menu structuré par contexte de prix, photos, coordonnées, horaires | | `GET` | `/api/restaurants/{uid}/prices` | historique des prix des items du resto (`item_price_log`) | | `GET` | `/api/restaurants/{uid}/inspections` | inspections/permis (enrichissements MAPAQ + RACJ) | | `GET` | `/api/dishes` | recherche par plat dans les 149 569 items, groupée par marque | | `GET` | `/api/facets` | facettes de filtres (régions, villes, cuisines, types) | | `GET` | `/api/sources` | registre des sources (statuts, cadences) | | `GET` | `/api/stats` | statistiques publiques JSON (alimente les pastilles ci-dessus) | | `GET` | `/api/stats/dashboard` | données du tableau de bord `/stats` | | `GET` | `/api/stats/report` | rapport PDF principal | | `GET` | `/api/stats/catalog` | catalogue des rapports disponibles | | `POST` | `/api/stats/report/custom` | rapport PDF personnalisé (ReportBuilder) | | `GET` | `/api/favorites` | favoris « Mon univers Ka » (session KA ID) | | `POST` | `/api/favorites/toggle` | ajout/retrait d'un favori | | `POST` | `/api/sync` | déclenchement d'une synchronisation | | `GET` | `/healthz` | santé du service (`{"status":"ok"}`) | | `GET` | `/doc/` | guide d'utilisation en ligne | | `GET` | `/{full_path}` | SPA + pages SSR légères (accueil, fiches JSON-LD, /villes) | ## Connecteurs 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) : | Connecteur | Famille | Rôle | Cadence | |---|---|---|---| | `osm` | découverte | OpenStreetMap (Overpass, miroirs fiabilisés) — 13 427 établissements nommés, 17/17 régions | mensuelle | | `ueat` | menus takeout (tier 1) | connecteur templatisé UEAT (API GraphQL) — menus takeout réels de 116 intégrations découvertes | hebdomadaire | | `siteresto` | menus salle | menus + photos publiés sur le site des restos indépendants | hebdo (batch incrémental), re-crawl mensuel | | `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 | | `ubereats` | livraison | complément livraison (prix `delivery`, jamais prioritaires sur un menu salle) | quotidienne par petits lots (60 pages), re-vérif 30 j | | `yelp` | annuaire | enrichissement via l'API Yelp Fusion (clé requise — SkipSource sans `YELP_API_KEY`) | hebdo, re-vérification 30 j | | `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 | 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. ## Données & conformité - **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. - **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. - **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). - **Données publiques officielles** : inspections MAPAQ et permis d'alcool RACJ (jeux de données gouvernementaux). - **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. - La base SQLite de prod (`data/restoka.db`) est **gitignorée** ; aucun secret dans le repo (`.env` local, gabarit `.env.example`). ## Architecture Pipeline (patron Lou·Ka) : **connecteurs → normalisation → déduplication → SQLite → API/frontend**. - **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). - **SQLite** (`restoka/db.py`) : restos, **menus par contexte de prix**, historique de prix (`item_price_log`), inspections, favoris, caches détail/géocodage. - **Connecteurs auto-enregistrés** (`restoka/connectors/`) : requests direct / Firecrawl / Scrapfly + cache détail (`base.py`), UEAT templatisé (`ueat.py`), découverte Overpass/OSM. - **Ingestion** (`restoka/ingest.py`) : sync → geocode → dedup, délai de grâce et alertes de dérive ; enrichissements inspections/permis/heures. - **Structuration LLM** (`restoka/menullm.py`) : menus maison structurés par Claude (API Anthropic). - **Frontend React 18 + Vite + TypeScript** (`frontend/`), design « éditorial sharp » Groupe KA. - **80 tests pytest** avec fixtures réelles hors ligne (connecteurs, normalisation, schéma, horaires, permis…). Processus PM2 sur le nœud (commandes de start réelles) : | Processus | Rôle | Commande | Cadence | |---|---|---|---| | `resto-ka` | serveur FastAPI (API + frontend) sur le port **8115** | `.venv/bin/python run.py serve 8115` | continu | | `resto-ka-sync` | boucle de synchronisation | `.venv/bin/python run.py watch 168` | cycle hebdomadaire (168 h) | | `resto-ka-ngrok` | tunnel vers **www.resto-ka.com** | `ngrok http --url=www.resto-ka.com 8115` | continu | ## Variables d'environnement Gabarit : `.env.example` (copier vers `.env`, jamais commité). **Noms seulement — aucune valeur dans le repo.** | Variable | Rôle | |---|---| | `SCRAPFLY_KEY` | rendu JS + bypass anti-bot (plateformes de livraison) | | `ANTHROPIC_API_KEY` | structuration des menus maison par Claude (`restoka/menullm.py`) | | `FIRECRAWL_API_KEY` | rendu JS de secours pour les sites de restos SPA (`site-resto`) | | `YELP_API_KEY` | API Yelp Fusion (sans clé : source sautée proprement) | | `YELP_BUDGET` | budget de requêtes Yelp par passage (quota quotidien 500) | | `SERPER_API_KEY` | Google Maps via Serper — découverte des sites web (`site-finder`) | | `SITE_FINDER_BUDGET` | budget de requêtes Serper par passage (défaut 3 000) | | `KA_SSO_SECRET` | SSO Groupe KA (« Se connecter avec KA ») | | `SESSION_SECRET` | sessions signées | | `RESTOKA_BASE_URL` | URL publique du site (défaut `https://www.resto-ka.com`) | ## Structure du repo ``` resto-ka/ ├── run.py # point d'entrée CLI (sync / watch / serve) ├── restoka/ # cœur Python : web, db, ingest, dedup, geocode, regions, schema, normalize, auth, stats, menullm… + connectors/ ├── frontend/ # React 18 + Vite + TypeScript — design éditorial sharp Groupe KA + public/doc/ (guide) ├── data/ # sources.json (registre), ueat-discovered.json (116 intégrations), base SQLite de prod (gitignorée) ├── scripts/ # scripts d'appoint (captures, déploiement) ├── tests/ # 80 tests pytest (fixtures réelles hors ligne) └── docs/ # captures d'écran + docs connecteurs ``` ## Documentation - **Guide en ligne** : [www.resto-ka.com/doc/](https://www.resto-ka.com/doc/) — à quoi sert le site, le parcours en 4 étapes (recherche → restos d'une ville → fiche → /stats), d'où viennent les données, FAQ. - **Guide PDF** : [resto-ka-documentation.pdf](https://www.resto-ka.com/doc/resto-ka-documentation.pdf) — la même documentation, téléchargeable. - Les captures du guide sont versionnées dans `frontend/public/doc/img/` (etape1 → etape4). ## Développement (remote-first) **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. - Remote `origin` = **spbgit** (git perso [git.spboucher.ai](https://git.spboucher.ai), bare repos sur M3U96a). **Pas GitHub.** - L'agent forwarding SSH est actif : le `git push origin main` fonctionne pendant une session SSH depuis le laptop. - `CLAUDE.md` est la source de vérité du projet (règles d'ingestion, en-têtes d'auteur obligatoires). ```bash pm2 restart resto-ka # après un changement en production ``` ## Déploiement - **Nœud** : M3U96b (Mac Studio, cluster MacLustr) — répertoire `~/apps/resto-ka` - **Port** : **8115** (local, exposé uniquement via le tunnel) - **Processus PM2** : `resto-ka` (serveur) + `resto-ka-sync` (synchro) + `resto-ka-ngrok` (tunnel) - **Domaine** : **https://www.resto-ka.com** (tunnel ngrok) ## Historique Jalons tirés du `git log` : - **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. - **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. - **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 ». - **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 ». - **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. - **2026-08-24** — page documentation `/doc` (guide + captures + PDF), refonte du README (v2 puis v3), mise à jour du répertoire UEAT. ## Écosystème Groupe KA | Plateforme | Vocation | |---|---| | [groupe-ka.com](https://www.groupe-ka.com) | portail du groupe et compte unique KA ID | | [lou-ka.com](https://www.lou-ka.com) | logements à louer | | [immo-ka.com](https://www.immo-ka.com) | propriétés à vendre | | [vrai-prix.com](https://www.vrai-prix.com) | estimation immobilière | | [auto-ka.com](https://www.auto-ka.com) | véhicules | | [fabri-ka.com](https://www.fabri-ka.com) | produits québécois | | [food-ka.com](https://www.food-ka.com) | épicerie et alimentation | | [resto-ka.com](https://www.resto-ka.com) | restaurants *(ce repo)* | | [sorti-ka.com](https://www.sorti-ka.com) | sorties et événements | | [job-ka.com](https://www.job-ka.com) | emplois | | [crea-ka.com](https://www.crea-ka.com) | créateurs de contenu | | [trouve-ka.com](https://www.trouve-ka.com) | petites annonces | | [api-ka.com](https://www.api-ka.com) | API de données | ## Contact **Simon-Pierre Boucher** — fondateur, Groupe KA 📧 [contact@spboucher.ai](mailto:contact@spboucher.ai) --- © Groupe KA — Simon-Pierre Boucher · contact@spboucher.ai Ce repo vit sur **spbgit** ([git.spboucher.ai](https://git.spboucher.ai)).