SPB Git forge

spb/resto-ka

Public

Resto·Ka — tous les restaurants du Québec, menus complets et prix réels (famille ·Ka)

52commits 1branches 0releases
11.6 MBsize
maindefault branch
19 days agolast push
Python 69.3% TypeScript 16.7% CSS 7.9% JavaScript 4.7% HTML 1.4%
26.5 KB · 573 lines markdown
Rendered Raw Blame History
1<!--2================================================================================3  Author: Simon-Pierre Boucher <contact@spboucher.ai>4  File:   CLAUDE.md5  Project: Resto·Ka — Agrégateur québécois de tous les restaurants (menus + prix)6================================================================================7-->89# CLAUDE.md — Resto·Ka1011> **Agrégateur exhaustif de tous les restaurants du Québec, avec leurs menus12> complets et leurs prix.**13> Chaque resto, chaque plat, chaque prix — dans les 17 régions, au même endroit,14> comparable et cherchable.1516Ce fichier est la source de vérité pour tout agent Claude (ou humain) qui travaille17sur ce dépôt. Lis-le **en entier** avant d'écrire une seule ligne de code.1819---2021## 0. À LIRE EN PREMIER — Règles non négociables22231. **En-tête d'auteur obligatoire.** **Chaque fichier** du dépôt (code, config,24   doc, script) doit commencer par un en-tête mentionnant l'auteur :25   `Simon-Pierre Boucher <contact@spboucher.ai>`. Voir la **section 17** pour le26   format exact selon le type de fichier. Aucun fichier ne doit être commité sans27   cet en-tête.28292. **Inspire-toi du dépôt Lou·Ka.** Avant de concevoir ou d'écrire **le moindre30   connecteur**, va lire le **dépôt de Lou·Ka** (le site jumeau, agrégateur de31   logements locatifs). Ses connecteurs sont le patron de référence : structure32   des modules, extraction (Firecrawl / Scrapfly), normalisation, déduplication,33   gestion des mises à jour, planification des tâches. **Ne réinvente rien** :34   reprends les mêmes conventions, la même architecture de connecteur, les mêmes35   utilitaires partagés. Resto·Ka doit être cohérent avec l'écosystème `·Ka`36   (Lou·Ka, Immo·Ka, Auto·Ka, Food·Ka, Fabri·Ka, Sorti·Ka). Voir **section 3**.37383. **Travail de moine.** L'agrégation de menus est un travail minutieux, source par39   source, plat par plat, sans rien précipiter. Un menu mal parsé (mauvais prix,40   plat manquant, option ignorée) détruit la confiance dans toute la base. Mieux41   vaut un connecteur robuste de plus que dix fragiles.42434. **Vérifie l'existant avant d'ajouter.** Avant d'intégrer un resto ou une source,44   confirme qu'il/elle n'est **pas déjà couvert(e)** (voir le registre des sources45   et l'index des restaurants, sections 9 et 12). Ne duplique jamais un connecteur46   ni une fiche resto. Un restaurant = une fiche canonique, quelles que soient les47   sources qui l'alimentent.48495. **Chaque source a son connecteur sur mesure**, mais les sources qui partagent50   une **même plateforme** (livraison, commande en ligne, POS, réservation)51   doivent être couvertes par un **connecteur générique templatisé** réutilisable.52   Voir **section 8**.53546. **La provenance du prix est sacrée.** Un prix de livraison (Uber Eats, DoorDash,55   Skip) est **majoré de 25-30 %** par rapport à la salle à manger. Ne **jamais**56   présenter un prix sans son contexte (`price_context`). Voir **sections 5 et 11**.5758---5960## 1. Mission6162Rendre visible, en un seul endroit, **tous les restaurants du Québec avec leurs63menus et leurs prix réels**, dans les 17 régions — pour que quiconque puisse64répondre à *« qu'est-ce que je mange, où, et combien ça coûte ? »* sans ouvrir65quinze applis.6667### Ce qui nous distingue6869Les plateformes existantes sont soit des **apps de livraison** (Uber Eats, Skip,70DoorDash — menus complets mais prix majorés, périmètre limité aux restos inscrits71et payants), soit des **annuaires** (Google, Yelp, TripAdvisor — avis et coordonnées,72mais **pas de menus structurés ni de prix comparables**), soit des **médias food**73(Tastet, RestoMontréal — éditorial, pas exhaustif).7475Personne n'offre **le menu complet + les prix de tous les restos, comparables entre76eux, partout au Québec.** C'est le créneau de Resto·Ka.7778---7980## 2. Périmètre — TOUS les établissements où l'on mange8182Périmètre maximaliste. Si on peut y commander à manger, ça doit finir dans Resto·Ka :8384- **Restaurants** (tous services : gastronomique, décontracté, familial).85- **Fast-food & chaînes** (menus standardisés, multi-succursales).86- **Cafés & salons de thé** (avec offre alimentaire).87- **Bars & pubs** avec cuisine.88- **Comptoirs pour emporter, cantines, casse-croûtes, food trucks.**89- **Pizzérias, sushis, poulet, burgers, shawarma**, etc.90- **Boulangeries-pâtisseries et traiteurs** avec menu et prix.91- **Microbrasseries et établissements** avec menu de bouffe.92- **Restaurants d'hôtel**, cuisines fantômes (ghost kitchens).9394> Règle d'or : en cas de doute sur l'inclusion, **on inclut** et on catégorise par95> type d'établissement. Le périmètre est large par conception.9697---9899## 3. Dépôts de référence — étudier Lou·Ka AVANT de coder100101Resto·Ka fait partie de la famille `·Ka`. **Le dépôt de Lou·Ka est la référence102canonique pour l'architecture des connecteurs.** Avant tout développement, l'agent103Claude doit :1041051. **Ouvrir le dépôt de Lou·Ka** et localiser le dossier des connecteurs106   (typiquement `connectors/`, `scrapers/` ou `sources/`).1072. **Lire 2 ou 3 connecteurs complets** de bout en bout pour comprendre :108   - la structure d'un module connecteur (interface commune, méthodes attendues) ;109   - l'**extraction** (Firecrawl / Scrapfly, endpoints JSON, sitemaps) ;110   - la **normalisation** vers le schéma commun ;111   - la **déduplication** (annonces publiées sur plusieurs plateformes) ;112   - la gestion des **mises à jour** (nouveautés, changements, retraits) ;113   - la **planification** (cadence, files, retries, backoff), les **erreurs** et le114     **logging**.1153. **Réutiliser** les utilitaires partagés de Lou·Ka (client Firecrawl/Scrapfly,116   helpers de normalisation, déduplication, géocodage) plutôt que d'en réécrire.1174. **Calquer** les conventions de nommage, la structure des dossiers et le style118   de code de Lou·Ka. Un dev qui connaît Lou·Ka doit se retrouver immédiatement.119120> Adaptation propre à Resto·Ka : là où Lou·Ka normalise une **annonce**, Resto·Ka121> normalise un **restaurant + un menu imbriqué (catégories → plats → prix →122> options)**. Le schéma est plus profond ; le reste du patron s'applique tel quel.123124> Si tu ne trouves pas le dépôt Lou·Ka ou l'accès aux connecteurs, **arrête-toi et125> demande** plutôt que d'inventer une architecture divergente.126127Écosystème complet, pour contexte :128129| Site        | Domaine          | Agrège                                    |130|-------------|------------------|-------------------------------------------|131| Lou·Ka      | lou-ka.com       | Logements à louer                         |132| Immo·Ka     | immo-ka.com      | Propriétés à vendre                       |133| Auto·Ka     | auto-ka.com      | Véhicules usagés                          |134| Food·Ka     | food-ka.com      | Prix d'épicerie & circulaires             |135| Fabri·Ka    | fabri-ka.com     | Produits québécois                        |136| Sorti·Ka    | sorti-ka.com     | Sorties & événements                      |137| **Resto·Ka**| **resto-ka.com** | **Restaurants, menus & prix (ce dépôt)**  |138139---140141## 4. Architecture142143Pipeline standard de la famille `·Ka`, adapté aux restaurants et menus :144145```146  ┌─────────────┐   ┌──────────────┐   ┌────────────────┐   ┌──────────────┐   ┌──────────┐147  │  CONNECTEUR │──▶│  EXTRACTION  │──▶│  NORMALISATION │──▶│ DÉDUPLICATION │──▶│  STOCKAGE │148  │ (par source)│   │ FC / Scrapfly│   │ resto + menu   │   │ identité resto│   │   (DB)    │149  │             │   │ + parse PDF  │   │ (schéma commun)│   │ + items       │   │           │150  └─────────────┘   └──────────────┘   └────────────────┘   └──────────────┘   └────┬─────┘151                                                                                     │152                                                                          ┌──────────▼──────────┐153                                                                          │  API / RECHERCHE /   │154                                                                          │  UI (menus & prix)   │155                                                                          └─────────────────────┘156```157158Composants :159160- **Connecteurs** : un module par source (ou par plateforme), interface commune.161- **Orchestrateur** : planifie et exécute (cadence, retries, backoff).162- **Extraction** : Firecrawl & Scrapfly + clients d'API + **parsing de menus PDF /163  images** (OCR) pour les menus non structurés.164- **Normalisation** : mappe le brut vers le **schéma Restaurant + Menu** (section 5).165- **Déduplication** : fusionne les restos et les items en double inter-sources.166- **Stockage** : base restos + menus + **historique des prix** (suivi des hausses).167- **API / UI** : recherche géolocalisée, filtres (cuisine, prix, diète), comparaison.168169---170171## 5. Modèle de données — schéma Restaurant + Menu172173### 5.1 Restaurant174175```jsonc176{177  "id": "string",                    // * id interne canonique (post-déduplication)178  "source_ids": ["ubereats:abc"],    // * id(s) d'origine par source (préfixés)179  "name": "string",                  // * nom normalisé180  "chain": "string|null",            // marque/chaîne si applicable181  "cuisines": ["italien", "pizza"],  // * taxonomie cuisine (section 6)182  "establishment_type": "restaurant",// restaurant|fast-food|cafe|bar|food-truck|traiteur...183  "price_range": "$$",               // $ à $$$$ (estimé à partir des prix)184  "address": "string",               // *185  "city": "string",                  // *186  "region": "string",                // * une des 17 régions (section 7)187  "postal_code": "string",188  "lat": 0.0,                         // * géolocalisation189  "lng": 0.0,                         // *190  "phone": "string",191  "website": "string",192  "hours": { /* horaires par jour */ },193  "services": ["salle", "emporter", "livraison"], // dine-in|takeout|delivery194  "dietary_options": ["vegan", "sans-gluten", "halal"],195  "languages": ["fr", "en"],196  "menu": { /* voir 5.2 */ },197  "status": "open",                  // open|temporarily_closed|closed198  "first_seen": "ISO-8601",          // *199  "last_seen":  "ISO-8601",          // *200  "updated_at": "ISO-8601"           // *201}202```203204### 5.2 Menu (imbriqué)205206```jsonc207"menu": {208  "currency": "CAD",209  "price_context": "delivery",       // * dine-in | takeout | delivery (voir §6)210  "price_source": "ubereats",        // * source du prix (traçabilité)211  "captured_at": "ISO-8601",         // * quand ce menu/prix a été capté212  "sections": [213    {214      "name": "Pizzas",215      "items": [216        {217          "id": "string",218          "name": "Margherita",       // *219          "description": "string",220          "price": 16.50,             // * prix de l'item (dans price_context)221          "currency": "CAD",222          "tags": ["vegetarien"],223          "options": [                // modificateurs / variantes224            {225              "group": "Format",226              "required": true,227              "choices": [228                { "name": "10 pouces", "price_delta": 0.00 },229                { "name": "14 pouces", "price_delta": 6.00 }230              ]231            }232          ]233        }234      ]235    }236  ]237}238```239240Règles :241- `price_context` et `price_source` sont **obligatoires** : un prix sans contexte242  est inutilisable (livraison ≠ salle).243- `lat`/`lng` obligatoires → **géocoder** l'adresse si absente.244- Capturer les **options/modificateurs** (formats, suppléments, choix) : ils245  changent le prix réel.246- Conserver la **devise** partout (CAD). Au QC, TPS/TVQ s'ajoutent ; ne pas les247  inclure dans `price` sauf si la source le fait, et alors le **documenter**.248249---250251## 6. Taxonomies252253### 6.1 Cuisines (multi-valué)254`quebecois` · `francais` · `italien` · `pizza` · `burgers` · `poulet` ·255`bbq-grillades` · `fruits-de-mer` · `sushi-japonais` · `chinois` · `thai` ·256`vietnamien` · `coreen` · `indien` · `libanais-moyen-orient` · `mexicain` ·257`grec` · `mediterraneen` · `dejeuner-brunch` · `cafe-dessert` · `vegetarien-vegan` ·258`fast-food` · `autre`259260### 6.2 Contexte de prix (`price_context`) — CRITIQUE261- `dine-in` — prix en salle (référence idéale).262- `takeout` — prix pour emporter (souvent = salle).263- `delivery` — prix sur plateforme de livraison, **majoré de 25-30 %**.264265> Toujours privilégier `dine-in`/`takeout` (menu du resto lui-même ou sa plateforme266> de commande en ligne) plutôt que `delivery` quand les deux existent. Si on n'a que267> `delivery`, on l'affiche **clairement étiqueté**.268269### 6.3 Diètes / tags270`vegan` · `vegetarien` · `sans-gluten` · `halal` · `casher` · `sans-noix` · `epice`271272---273274## 7. Régions du Québec (obligatoire pour chaque restaurant)275276Bas-Saint-Laurent · Saguenay–Lac-Saint-Jean · Capitale-Nationale · Mauricie ·277Estrie · Montréal · Outaouais · Abitibi-Témiscamingue · Côte-Nord ·278Nord-du-Québec · Gaspésie–Îles-de-la-Madeleine · Chaudière-Appalaches · Laval ·279Lanaudière · Laurentides · Montérégie · Centre-du-Québec.280281Rattacher chaque resto à sa région via la ville/adresse (table de correspondance282ville → région, comme dans Lou·Ka).283284---285286## 8. Philosophie des connecteurs287288- **Un connecteur par source**, taillé sur mesure.289- **Connecteurs templatisés par plateforme** : c'est le levier d'échelle nº 1. Une290  plateforme de commande en ligne ou de livraison couvre des **milliers** de restos291  avec la même structure → un seul connecteur paramétré les couvre tous (exactement292  comme les connecteurs par plateforme d'Auto·Ka et Fabri·Ka).293- **Deux types de sources à combiner** :294  1. **Découverte** (liste des restos + métadonnées) : annuaires, cartes, tourisme.295  2. **Menus + prix** (le cœur) : commande en ligne, livraison, sites de restos, PDF.296- Interface commune (à calquer sur Lou·Ka) : `fetch()` → `normalize()` → `emit()`.297  Idempotent et incrémental quand c'est possible.298- **Robustesse** : timeouts, retries + backoff, tolérance aux changements mineurs,299  alerte si le nombre d'items d'un menu chute anormalement (connecteur cassé).300301---302303## 9. Catalogue des sources à connecter (priorisé)304305> ⚠️ Vérifie le registre des sources et l'index des restos **avant** d'ajouter.306307### Palier 1 — Plateformes de commande en ligne des restos (MEILLEUR prix + volume)308309Ces plateformes propulsent les **sites/apps des restos eux-mêmes** → menus complets310à des **prix réels (dine-in/takeout, non majorés)**. À templatiser par plateforme :311312- **UEAT** (foodtech de Québec, marque blanche, **très répandue au QC**).313- **Square Online Ordering**, **Toast**, **Clover**, **GloriaFood (Oracle)**,314  **Flipdish**, **Foodiv**, **ChowNow**, **Bite (DoorDash)**.315316### Palier 2 — Plateformes de livraison (menus complets, prix MAJORÉS)317318Menus riches et structurés, mais prix `delivery` (+25-30 %), anti-bot fort et CGU319restrictives (voir **section 15** — risque légal réel) :320321- **Uber Eats**, **SkipTheDishes**, **DoorDash**.322- Plateformes québécoises : **RestoLoco** et autres services locaux régionaux.323324> Politique : utiliser la livraison surtout pour la **découverte** et pour les325> restos qu'on ne trouve nulle part ailleurs. Toujours étiqueter `price_context:326> delivery`. Préférer une source `dine-in` dès qu'elle existe.327328### Palier 3 — Sites web des restaurants (menus « maison »)329330- Menus en **HTML** (parse direct) ou en **PDF / image** (→ parsing PDF + OCR,331  voir section 10). Détecter la plateforme de commande embarquée (souvent Palier 1).332333### Palier 4 — Découverte & métadonnées (liste des restos)334335- **Google Places / Maps**, **Yelp**, **TripAdvisor** (coordonnées, horaires, type336  de cuisine, fourchette de prix — **rarement les menus** ; respecter les CGU/API).337- **Associations touristiques régionales (ATR)**, Tourisme Québec.338- Médias food : **Tastet**, **RestoMontréal** et annuaires régionaux (découverte).339340### Palier 5 — Réservation (métadonnées + parfois menus)341342- **OpenTable**, **LibroReserve** (Québec), **Resy**, **Zenchef** — horaires,343  services, parfois menus.344345### Palier 6 — Chaînes (menus standardisés)346347- Sites des grandes chaînes : menus et prix souvent uniformes par bannière et348  parfois par région → un connecteur par chaîne couvre toutes les succursales.349350---351352## 10. Extraction — Firecrawl, Scrapfly & parsing de menus353354Les connecteurs s'appuient **souvent sur Firecrawl et Scrapfly** (comme tout355l'écosystème `·Ka`). Règle de choix :356357- **API / endpoint JSON de la plateforme** → toujours privilégié (données358  structurées, stables). Beaucoup de plateformes de commande chargent leur menu359  via un appel JSON interne : **le trouver et le consommer directement.**360- **Firecrawl** → crawl et extraction en volume de sites relativement ouverts361  (sites de restos, annuaires), extraction structurée (markdown/JSON).362- **Scrapfly** → sites protégés, JavaScript lourd, anti-bot, rendu navigateur,363  rotation d'IP. **Requis** pour les plateformes de livraison (Uber Eats, Skip,364  DoorDash) qui bloquent agressivement.365- **Parsing de menus PDF / images** : de nombreux restos publient un menu en PDF ou366  en photo. Prévoir extraction de texte PDF + **OCR** + un post-traitement (LLM) qui367  transforme le texte brut en structure `sections → items → price → options`.368  Valider systématiquement (un prix mal OCR-isé est pire que pas de prix).369370Chaque connecteur doit **documenter** en tête de fichier son mode d'extraction et371pourquoi. Réutiliser les clients partagés de Lou·Ka.372373---374375## 11. Normalisation376377- Nettoyer noms de restos, sections et plats (HTML résiduel, majuscules, doublons).378- Mapper vers le **schéma Restaurant + Menu** (section 5) intégralement.379- **Cuisines** et **type d'établissement** classés dès la normalisation (section 6).380- **Géocoder** (lat/lng obligatoires) et **rattacher la région** (section 7).381- **Prix** : renseigner **obligatoirement** `price_context` et `price_source` ;382  capturer les **options/modificateurs**. Ne jamais mélanger des prix de contextes383  différents dans un même menu.384- **Devise** CAD ; documenter le traitement des taxes (TPS/TVQ hors prix au QC).385- Conserver les **`source_ids`** préfixés (ex. `ueat:1234`, `ubereats:abcd`).386387---388389## 12. Déduplication — restaurants ET items390391Un même resto apparaît sur Uber Eats + DoorDash + Skip + son propre site + Google.392393### 12.1 Identité du restaurant3941. **Clé** : nom normalisé + adresse (géoloc arrondie) + téléphone → empreinte.3952. **Approché** : noms proches + même adresse → fusion candidate (journaliser).3963. **Fusion** : un enregistrement canonique, agréger les `source_ids`, choisir la397   meilleure source par champ.3984. **Multi-succursales / chaînes** : chaque **adresse** est une fiche resto399   distincte, reliée par `chain`. Ne pas fusionner deux succursales.400401### 12.2 Menus & prix402- Ne pas écraser un menu `dine-in` par un menu `delivery` : **conserver les deux403  contextes** et présenter le meilleur (dine-in prioritaire), en gardant delivery404  étiqueté.405- Dédupliquer les **items** au sein d'un même contexte (même plat listé deux fois).406- **Historiser** les prix : à chaque capture, si le prix d'un item change, garder la407  série temporelle (utile pour détecter les hausses et pour la crédibilité).408409S'inspirer de la déduplication de **Lou·Ka** (multi-plateformes) et d'Auto·Ka410(identité forte par clé).411412---413414## 13. Fraîcheur des menus & états415416- **Menus changeants** : prix et plats évoluent (saisonnier, table d'hôte,417  spéciaux). Rafraîchir régulièrement et **horodater** chaque capture (`captured_at`).418- **Fermetures** : resto fermé temporairement / définitivement → `status` mis à jour419  plutôt que suppression brutale (politique de grâce via `last_seen`, comme Lou·Ka).420- **Items retirés** : disparition d'un plat → le marquer inactif, conserver421  l'historique.422- **Spéciaux / table d'hôte** : capturer si structurés, avec leur période de validité.423424---425426## 14. Cadence de rafraîchissement427428- Grandes plateformes (commande en ligne, livraison, chaînes) : **hebdomadaire** au429  minimum ; **quotidien** pour les prix sur les gros volumes urbains.430- Sites de restos indépendants : **hebdomadaire à mensuel** (menus stables).431- Découverte (annuaires) : **mensuel** pour repérer nouveaux restos / fermetures.432- Toujours mettre à jour `last_seen` et `captured_at` à chaque passage réussi.433434---435436## 15. Conformité & aspects légaux — À PRENDRE AU SÉRIEUX437438> C'est le point le plus sensible de ce projet. Les plateformes de livraison439> **protègent activement** leurs données (menus/prix) et l'interdisent dans leurs440> CGU. Ne pas traiter ça à la légère.441442- Respecter les **CGU** et `robots.txt` de chaque source. Les plateformes de443  livraison sont explicitement restrictives : **minimiser**, privilégier d'autres444  sources pour les mêmes restos, et **demander** en cas de doute avant d'industrialiser.445- Privilégier les **sources de première partie** : le **site du resto** et sa446  **plateforme de commande** (UEAT, etc.) sont la voie la plus légitime pour le447  menu et le prix réel.448- **Rate-limiting** raisonnable, identification honnête, pas de surcharge.449- Utiliser les **API officielles** quand elles existent (Google Places, Yelp) et450  en respecter les quotas et conditions d'affichage/attribution.451- Ne republier que ce qui est nécessaire à la découverte (nom, plats, prix, infos452  pratiques, lien vers la source). **Attribuer** les sources requises.453- Consigner par source la base légale/mode d'accès retenu (API vs scraping) en tête454  de connecteur.455456---457458## 16. Conventions de code459460- Suivre **les mêmes conventions que Lou·Ka** (langage, structure de dossiers,461  nommage, linting, formatage). Cohérence > préférences personnelles.462- Un connecteur = un module isolé, testable indépendamment.463- Secrets (clés Firecrawl/Scrapfly, API Google/Yelp) via variables d'environnement /464  gestionnaire de secrets. Jamais en clair.465- Logging structuré (source, nb de restos, nb d'items, erreurs, durée).466- Commits atomiques, messages clairs.467468---469470## 17. En-tête d'auteur — OBLIGATOIRE dans chaque fichier471472**Tout fichier** du dépôt doit débuter par un en-tête d'auteur. L'auteur est473toujours **Simon-Pierre Boucher \<contact@spboucher.ai\>**.474475**Python / Shell / YAML / TOML / Dockerfile :**476```python477# ==============================================================================478# Author: Simon-Pierre Boucher <contact@spboucher.ai>479# File:   <nom_du_fichier>480# Desc:   <brève description>481# ==============================================================================482```483484**JavaScript / TypeScript / Go / Rust / Java / C :**485```javascript486// ==============================================================================487// Author: Simon-Pierre Boucher <contact@spboucher.ai>488// File:   <nom_du_fichier>489// Desc:   <brève description>490// ==============================================================================491```492493**Markdown / HTML / XML :**494```html495<!--496  Author: Simon-Pierre Boucher <contact@spboucher.ai>497  File:   <nom_du_fichier>498  Desc:   <brève description>499-->500```501502**CSS / SCSS :**503```css504/*505  Author: Simon-Pierre Boucher <contact@spboucher.ai>506  File:   <nom_du_fichier>507*/508```509510Règles :511- **Aucun** fichier commité sans cet en-tête.512- Pour un connecteur, indiquer dans `Desc:` la **source/plateforme couverte**, le513  **mode d'extraction** (API / Firecrawl / Scrapfly / PDF-OCR) et le **contexte de514  prix** produit (dine-in / takeout / delivery).515- Vérifier la présence de l'en-tête en revue de code (idéalement hook de pré-commit).516517---518519## 18. Tests & qualité520521- Chaque connecteur : **tests unitaires** de normalisation sur des fixtures réelles522  (réponses JSON, HTML, PDF de menus figés).523- Tests de **parsing de menus** : vérifier prix, options et sections sur des524  échantillons connus (les prix sont l'actif le plus critique).525- Tests de **déduplication** resto + items multi-sources.526- **Validation de schéma** : tout resto/menu émis doit passer la validation avant527  stockage ; rejeter un menu sans `price_context`/`price_source`.528- **Monitoring** : alerte si le nb d'items d'un resto ou le volume d'une source529  chute anormalement (connecteur probablement cassé).530531---532533## 19. Checklist — ajouter un nouveau connecteur / restaurant5345351. [ ] Lire les connecteurs de référence dans le **dépôt Lou·Ka** (section 3).5362. [ ] Vérifier que la source/le resto **n'est pas déjà couvert** (registres).5373. [ ] Identifier la **plateforme** : peut-on templatiser/réutiliser un connecteur ?5384. [ ] Choisir le **mode d'extraction** : API > site du resto > Firecrawl > Scrapfly ;539       PDF/OCR si menu non structuré (section 10).5405. [ ] Déterminer le **`price_context`** produit et le documenter.5416. [ ] Implémenter `fetch()` → `normalize()` → `emit()` (interface commune).5427. [ ] Mapper **tout** le schéma resto + menu, géocoder, région, cuisines, options.5438. [ ] Brancher la **déduplication** resto + items (section 12).5449. [ ] Gérer **fraîcheur, fermetures, items retirés, historique des prix** (§13).54510. [ ] Vérifier la **conformité** CGU/robots et consigner la base d'accès (§15).54611. [ ] Ajouter l'**en-tête d'auteur** (section 17).54712. [ ] Écrire les **tests** + fixtures, dont le parsing de prix (section 18).54813. [ ] Enregistrer la source dans le **registre** avec sa cadence.54914. [ ] Valider volume et qualité sur un premier run, journaliser.550551---552553## 20. Roadmap / MVP554555**MVP** : templatiser **un** connecteur pour la plateforme de commande en ligne la556plus répandue au QC (**UEAT**) → menus complets à prix réels (`dine-in`/`takeout`)557pour des milliers de restos d'un coup. Ajouter la découverte via Google Places/Yelp558pour la liste et les métadonnées, et le parsing des menus PDF des sites de restos.559UI de recherche géolocalisée avec filtres (cuisine, prix, diète, service) et560affichage clair du **contexte de prix**.561562**Ensuite** : plateformes de livraison (avec étiquetage strict), chaînes,563réservation, régions moins couvertes. Puis historique des prix, comparaison entre564restos, et cross-linking avec les autres sites `·Ka`.565566**Nord stratégique** : être **le seul** à offrir menus **et** prix **comparables**567de **tous** les restos du Québec — là où la livraison est chère et partielle, les568annuaires sans menus, et les médias food non exhaustifs.569570---571572*Fin de CLAUDE.md — Resto·Ka. Auteur : Simon-Pierre Boucher \<contact@spboucher.ai\>.*573