SPB Git forge

spb/auto-ka

Public
61commits 1branches 0releases
14.4 MBsize
maindefault branch
12 days agolast push
Python 61.6% TypeScript 20.9% CSS 11.4% JavaScript 5.1% HTML 1.1%

docs: README à jour avec screenshot

Simon-Pierre Boucher committed 1 mo ago (Aug 18, 2026) parent af9c4a7

2 changed files +84 −203

modified README.md +84 −203
@@ -2,7 +2,7 @@
2 2
3 3 # Auto·Ka
4 4
5 −### Toutes les voitures usagées à vendre au Québec. Un seul endroit.
5 +### **Toutes les voitures usagées à vendre au Québec. Un seul endroit.**
6 6
7 7 **[www.auto-ka.com](https://www.auto-ka.com)**
8 8
@@ -12,170 +12,89 @@
12 12 ![SQLite](https://img.shields.io/badge/SQLite-diff_engine-17181c?style=for-the-badge&logo=sqlite&logoColor=ff5a2a)
13 13 ![PM2](https://img.shields.io/badge/PM2-production-17181c?style=for-the-badge&logoColor=ff5a2a)
14 14
15 −![Véhicules](https://img.shields.io/badge/v%C3%A9hicules_en_vente-17_698-cc3f16?style=flat-square)
16 −![Concessionnaires](https://img.shields.io/badge/concessionnaires_connect%C3%A9s-138-cc3f16?style=flat-square)
17 −![Régions](https://img.shields.io/badge/r%C3%A9gions_couvertes-18-cc3f16?style=flat-square)
18 −![Marques](https://img.shields.io/badge/marques-83-cc3f16?style=flat-square)
19 −![Prix](https://img.shields.io/badge/annonces_avec_prix-99,6_%25-cc3f16?style=flat-square)
20 −
21 −![SEO](https://img.shields.io/badge/URLs_indexables-18_475-17181c?style=flat-square&logo=googlesearchconsole&logoColor=ff5a2a)
22 −![Sitemap](https://img.shields.io/badge/sitemap.xml-dynamique-17181c?style=flat-square&logoColor=ff5a2a)
23 −![JSON-LD](https://img.shields.io/badge/JSON--LD-Car_·_Offer_·_ItemList-17181c?style=flat-square&logoColor=ff5a2a)
24 −![KA ID](https://img.shields.io/badge/KA_ID-SSO_Groupe_KA-17181c?style=flat-square&logoColor=ff5a2a)
25 −
26 −*Agrégateur indépendant de voitures, motos et scooters usagés — chaque annonce
27 −avec ses photos, ses caractéristiques standardisées (année, km, transmission,
28 −carburant, VIN…) et un lien direct vers l'annonce originale du concessionnaire.
29 −Toujours à jour, automatiquement. Suivi des baisses de prix intégré.*
30 −
31 −<img src="docs/screenshot-home.png" alt="Auto-Ka — recherche de véhicules" width="920" />
32 −
33 15 </div>
34 16
17 +![Aperçu de Auto-Ka](docs/screenshot.png)
18 +
35 19 ---
36 20
37 −## Pourquoi Auto-Ka ?
21 +## Description
38 22
39 −Chercher une auto usagée au Québec, c'est ouvrir des dizaines de sites de
40 −concessionnaires — chacun avec sa navigation, ses filtres, son format.
41 −**Auto-Ka retourne le problème** : un connecteur dédié par commerce visite
42 −chaque site **à la source** (aucune plateforme d'annonces revendue), normalise
43 −chaque véhicule vers un schéma unique et détecte les changements en continu.
23 +**Auto-Ka** est un **agrégateur indépendant de voitures, motos et scooters usagés** couvrant la **province de Québec**. Chercher une auto usagée, c'est normalement ouvrir des dizaines de sites de concessionnaires — chacun avec sa navigation, ses filtres, son format. **Auto-Ka retourne le problème** : un **connecteur dédié par commerce** visite chaque site **à la source** (aucune plateforme d'annonces revendue), **normalise** chaque véhicule vers un **schéma unique** et **détecte les changements en continu**.
44 24
45 −> Les sites de concessionnaires n'offrent pas de webhooks. Auto-Ka reproduit
46 −> l'équivalent : **synchronisation périodique + hash de contenu** → arrivages,
47 −> baisses de prix et ventes détectés automatiquement. Un véhicule qui disparaît
48 −> du site source est marqué vendu dans Auto-Ka — et sa page renvoie alors un
49 −> vrai `410 Gone` aux moteurs de recherche.
25 +> Les sites de concessionnaires n'offrent pas de webhooks. Auto-Ka reproduit l'équivalent : **synchronisation périodique + hash de contenu** → **arrivages**, **baisses de prix** et **ventes** détectés automatiquement. Un véhicule qui disparaît du site source est **marqué vendu** — et sa page renvoie alors un vrai **`410 Gone`** aux moteurs de recherche.
50 26
51 −## Les chiffres
27 +### Les chiffres
52 28
53 29 | Métrique | Valeur |
54 30 |---|---|
55 31 | Véhicules en vente | **17 698** — 17 082 autos · 591 motos · 25 scooters |
56 32 | Concessionnaires connectés | **138** (125 autos + 13 motos/scooters) |
57 −| Régions administratives couvertes | **18** · **72 villes** · **83 marques** |
33 +| Couverture | **18 régions** · **72 villes** · **83 marques** |
58 34 | Annonces avec prix affiché | **99,6 %** (jamais de prix inventé) |
59 −| Annonces avec kilométrage | **99,7 %** · VIN **95,1 %** |
60 −| Annonces avec description | **85 %** · équipements **72 %** |
35 +| Kilométrage / VIN | **99,7 %** / **95,1 %** |
61 36 | Photos par véhicule (moyenne) | **~16** (galeries complètes) |
62 37 | Prix moyen / médian du parc | **28 529 $** / **24 995 $** |
63 38 | URLs indexables (SEO) | **18 475** — 17 698 fiches + 777 pages de recherche |
64 −| Cycle de rafraîchissement | **2 h** (PM2 watcher + enrichissement progressif) |
65 −
66 −## La fiche véhicule
39 +| Cycle de rafraîchissement | **2 h** (watcher PM2 + enrichissement progressif) |
67 40
68 −Galerie photos complète, caractéristiques standardisées, VIN, équipements,
69 −**historique de prix**, véhicules similaires toutes sources confondues, favoris
70 −KA ID — et le lien vers l'annonce originale, toujours.
41 +## Fonctionnalités
71 42
72 −<div align="center">
73 −<img src="docs/screenshot-vehicle.png" alt="Auto-Ka — fiche véhicule : galerie, caractéristiques, VIN, lien source" width="920" />
74 −</div>
75 −
76 −## Le marché en direct
43 +- **Recherche unifiée** — filtres **marque / modèle / année / prix / km / carburant / motricité / carrosserie / région / ville / concessionnaire**, avec facettes dynamiques et tri.
44 +- **Fiches véhicule complètes** — galerie photos, caractéristiques standardisées, **VIN**, équipements, **historique de prix**, véhicules similaires toutes sources confondues, et **lien direct vers l'annonce originale** du concessionnaire, toujours.
45 +- **Trois verticales, un moteur** — le champ `kind` (**`auto` / `moto` / `scooter`**) traverse tout le pipeline ; motos et scooters ont leurs onglets dédiés (13 concessionnaires **PowerGo**).
46 +- **Suivi des baisses de prix** — le **diff engine** (upsert par hash de contenu) détecte nouveau / modifié / vendu, avec délai de grâce de 2 syncs et détection de dérive.
47 +- **Statistiques du marché en direct** — tuiles de synthèse, distribution des prix, répartitions par région / marque / carrosserie, baisses récentes, et **rapport PDF** généré à la demande (`autoka/pdfgen.py`).
48 +- **SEO programmatique massif** — la SPA React est servie avec un **rendu serveur complet** (`autoka/seo.py`) : title/meta uniques, canonical, Open Graph, hreflang `fr-CA`, **JSON-LD `Car`/`Motorcycle` + `Offer` + `BreadcrumbList`**, **~900 pages programmatiques** (`/usagees/{marque}`, `/usagees/{marque}/{modele}`, `/region/…`, `/ville/…`, `/carrosserie/…`, `/motos/…`), **sitemaps dynamiques** (18 475 URLs, `lastmod` réels), vendu → **410**, inconnu → **404**.
49 +- **Compte KA ID** — SSO **« Se connecter avec KA ID »** via le hub [groupe-ka.com](https://www.groupe-ka.com) : même compte sur toutes les plateformes du groupe, page **/profil**, **favoris ♥ « Mon univers Ka »** centralisés.
50 +- **Connecteurs auto-découvrants** — ajouter un concessionnaire = **~6 lignes** : une sous-classe de `BaseConnector` avec un `source_id` déposée dans `autoka/connectors/`, c'est tout.
77 51
78 −Tuiles de synthèse, distribution des prix, répartitions par région / marque /
79 −carrosserie, baisses de prix récentes — et un **rapport PDF** généré à la
80 −demande (`autoka/pdfgen.py`).
81 −
82 −<div align="center">
83 −<img src="docs/screenshot-stats.png" alt="Auto-Ka — statistiques du marché et distribution des prix" width="920" />
84 −</div>
52 +### Principes
85 53
86 −## Trois verticales, un moteur
87 −
88 −Le champ `kind` (`auto` / `moto` / `scooter`) traverse tout le pipeline —
89 −connecteurs, base, API, frontend. Les motos et scooters ont leurs onglets
90 −dédiés, alimentés par 13 concessionnaires sur plateforme **PowerGo**.
91 −
92 −<div align="center">
93 −<img src="docs/screenshot-motos.png" alt="Auto-Ka — verticale motos usagées" width="920" />
94 −</div>
95 −
96 −## L'architecture en 30 secondes
97 −
98 −```mermaid
99 −flowchart LR
100 − subgraph Sources["138 concessionnaires"]
101 − S1["D2C Media ×50 · SM360 ×8<br/>AMVOQ ×6 · EvalAuto ×11<br/>Convertus ×4 · PowerGo ×13<br/>HGrégoire · AED · customs…"]
102 − end
103 − subgraph AutoKa["Auto-Ka"]
104 − C["Connecteurs<br/><i>1 adaptateur / plateforme</i>"] --> N["Normalisation<br/><i>schéma Vehicle unique</i>"]
105 − N --> D[("SQLite<br/>hash + diff + prix")]
106 − D --> A["API FastAPI<br/>/api/vehicles · /api/facets"]
107 − D --> SEO["Rendu serveur SEO<br/><i>HTML complet + JSON-LD<br/>sitemaps · 410 · canonical</i>"]
108 − A --> F["React 18 + Vite<br/>filtres · fiches · stats"]
109 − SEO --> F
110 − end
111 − W["⏱ Watcher 2 h<br/>(PM2)"] -.-> C
112 − S1 --> C
113 − F --> U["🔑 Acheteur"]
114 − SEO --> G["🕷 Googlebot"]
115 −```
116 −
117 −| Couche | Rôle | Fichiers |
118 −|---|---|---|
119 −| **Connecteurs** | 1 module par plateforme de site (D2C Media, SM360, AMVOQ Focus 360, EvalAuto Gatsby/Next.js, Convertus VMS, ADWS, EDealer, PowerGo…) avec 1 sous-classe par concessionnaire ; JSON-LD schema.org, API JSON internes, sitemaps ; Firecrawl/Scrapfly pour les sites derrière Cloudflare | `autoka/connectors/*.py` |
120 −| **Schéma** | `Vehicle` standardisé : marque, modèle, année, prix, km, transmission, carburant, motricité, carrosserie, couleurs, VIN, photos, région, `kind` | `autoka/schema.py` |
121 −| **Normalisation** | Prix/km/année depuis le texte, marques canoniques, ville → région administrative, inférence motricité/carburant depuis les badges du titre (AWD, PHEV…) | `autoka/normalize.py` |
122 −| **Diff engine** | Upsert par hash de contenu — nouveau / modifié / vendu (délai de grâce 2 syncs), **historique de prix**, détection de dérive | `autoka/db.py` |
123 −| **API** | Filtres marque / modèle / année / prix / km / carburant / motricité / région / ville / concessionnaire, facettes, stats marché, baisses de prix | `autoka/web.py` |
124 −| **SEO / SSR** | HTML complet servi dès la 1ʳᵉ requête, meta uniques, JSON-LD, pages programmatiques, sitemaps dynamiques, 410/404 | `autoka/seo.py` |
125 −| **Compte** | SSO **KA ID** (hub groupe-ka.com), profil Groupe KA, favoris « Mon univers Ka » centralisés | `autoka/auth.py` · `hubprofile.py` · `hubfav.py` |
126 −| **Frontend** | Design « éditorial sharp », accent orange racing : filtres auto complets, fiches avec galerie, historique de prix et similaires | `frontend/` |
127 −
128 −## Référencement : chaque recherche a sa page
129 −
130 −Le site est une SPA React, mais **les moteurs de recherche ne voient jamais une
131 −page vide** : `autoka/seo.py` intercepte chaque route publique et sert le HTML
132 −complet — title et meta description uniques, canonical, Open Graph, hreflang
133 −`fr-CA`, données structurées et le contenu intégral (24 fiches, stats, liens)
134 −dans `#root`. React monte ensuite par-dessus et reprend la main.
135 −
136 −<div align="center">
137 −<img src="docs/screenshot-seo-marque.png" alt="Auto-Ka — page programmatique Toyota usagées à vendre au Québec" width="920" />
138 −</div>
54 +1. **À la source** — les annonces viennent des sites des concessionnaires eux-mêmes, jamais des plateformes d'agrégation existantes.
55 +2. **Politesse** — délai ≥ 1 s entre requêtes, cache des pages détail, backoff sur rate-limit, User-Agent identifié.
56 +3. **Fidélité** — **aucun prix inventé** : si la source n'affiche pas de prix, `price = null` (« Prix sur demande »).
57 +4. **Traçabilité** — chaque fiche renvoie vers l'annonce originale.
58 +5. **Robustesse** — un connecteur qui casse n'affecte jamais les autres ; détection de dérive (chute de volume → retraits suspendus + alerte).
59 +6. **Honnêteté envers les moteurs** — le HTML servi aux robots est le même que celui servi aux humains.
139 60
140 −**~900 pages programmatiques**, alignées sur les recherches réelles, maillées
141 −entre elles (modèles voisins, autres marques, villes de la région) :
61 +## Stack technique
142 62
143 −| Gabarit d'URL | Exemple | Contenu |
63 +| Couche | Technologie | Rôle |
144 64 |---|---|---|
145 −| `/usagees/{marque}` | `/usagees/toyota` | H1, nombre d'annonces, prix moyen/médian, 24 fiches, modèles de la marque |
146 −| `/usagees/{marque}/{modele}` | `/usagees/honda/civic` | idem, ciblé modèle (fil d'Ariane complet) |
147 −| `/region/{region}` | `/region/monteregie` | inventaire de la région + liens vers ses villes |
148 −| `/ville/{ville}` | `/ville/sherbrooke` | inventaire de la ville + villes voisines |
149 −| `/carrosserie/{type}` | `/carrosserie/vus` | liste blanche de 10 carrosseries propres |
150 −| `/motos/{marque}` · `/scooters/{marque}` | `/motos/harley-davidson` | verticales moto/scooter |
151 −
152 −**Fiches** : URL lisible `/vehicule/{uid}/{annee-marque-modele}` (301 depuis
153 −l'uid nu), JSON-LD `Car`/`Motorcycle` + `Offer` complet (prix CAD, km, VIN,
154 −concessionnaire, ville), `BreadcrumbList`, og:image.
155 −
156 −**Cycle de vie honnête** : véhicule vendu → **410 Gone** avec liens vers la
157 −page modèle parente ; URL inconnue → vrai **404** (fin des soft-404).
65 +| **Backend** | **Python 3.14** · **FastAPI** · **Uvicorn** | API `/api/*` + rendu serveur SEO + service du frontend |
66 +| **Base de données** | **SQLite** | Diff engine : hash de contenu, historique de prix, cycle de vie des annonces |
67 +| **Connecteurs** | requests · BeautifulSoup · Firecrawl/Scrapfly (sites derrière Cloudflare) | **1 adaptateur par plateforme** : D2C Media ×50, SM360 ×8, AMVOQ ×6, EvalAuto ×11, Convertus ×4, PowerGo ×13, HGrégoire, AED, customs… |
68 +| **Frontend** | **React 18** · **Vite** · **TypeScript** | Design « éditorial sharp », accent orange racing — filtres, fiches, stats |
69 +| **PDF** | reportlab · fpdf2 (`autoka/pdfgen.py`, `kapdf.py`) | Rapport « Le marché de l'occasion » |
70 +| **Production** | **PM2** · **ngrok** | 3 processus résilients + tunnel www.auto-ka.com |
158 71
159 −**Découvrabilité** : `robots.txt` + `sitemap.xml` dynamique (index →
160 −`pages.xml` + `vehicules-N.xml` par tranches de 10 000, `lastmod` réels) —
161 −**18 475 URLs** régénérées à la volée. Compression gzip, images lazy avec
162 −dimensions explicites.
72 +## Structure du projet
163 73
164 −```bash
165 −$ curl -s https://www.auto-ka.com/usagees/toyota | grep -o "<title>[^<]*"
166 −<title>Toyota usagées à vendre au Québec — 1 163 en inventaire | Auto·Ka
74 +```
75 +auto-ka/
76 +├── run.py # Point d'entrée : sync | watch | serve
77 +├── requirements.txt # Dépendances backend
78 +├── autoka/
79 +│ ├── connectors/ # 1 module par plateforme, 1 sous-classe par concessionnaire
80 +│ ├── schema.py # Schéma Vehicle standardisé (kind: auto/moto/scooter)
81 +│ ├── normalize.py # Prix/km/année, marques canoniques, ville → région
82 +│ ├── ingest.py # Pipeline d'ingestion
83 +│ ├── db.py # SQLite — diff engine, hash, historique de prix
84 +│ ├── web.py # API FastAPI (/api/vehicles, /api/facets, /api/stats…)
85 +│ ├── seo.py # Rendu serveur SEO : HTML complet, JSON-LD, sitemaps, 410/404
86 +│ ├── auth.py # SSO KA ID (hub groupe-ka.com)
87 +│ ├── hubprofile.py # Profil Groupe KA
88 +│ ├── hubfav.py # Favoris « Mon univers Ka »
89 +│ ├── marketstats.py # Statistiques du marché
90 +│ ├── statsdash.py # Tableau de bord analytique
91 +│ └── pdfgen.py · kapdf.py# Rapport PDF
92 +├── frontend/ # React 18 + Vite + TypeScript (build → dist/)
93 +├── data/ # sources.json (registre des concessionnaires) + base
94 +└── docs/ # Captures d'écran
167 95 ```
168 96
169 −## Compte KA ID — l'identité du Groupe KA
170 −
171 −Connexion **« Se connecter avec KA ID »** via le hub
172 −[groupe-ka.com](https://www.groupe-ka.com) : le même compte (et le même
173 −`ka-…`) sur toutes les plateformes du groupe. Page **/profil** avec la carte
174 −de membre Groupe KA, profil enrichi lu depuis le hub, et **favoris ♥
175 −« Mon univers Ka »** — posés sur n'importe quelle carte ou fiche, stockés
176 −centralement, visibles depuis toutes les plateformes.
177 −
178 −## Démarrage rapide
97 +## Démarrage local
179 98
180 99 ```bash
181 100 git clone https://git.spboucher.ai/auto-ka.git && cd auto-ka
@@ -190,17 +109,12 @@ cd frontend && npm install && npm run build && cd ..
190 109 echo "FIRECRAWL_API_KEY=fc-votre-cle" > .env
191 110
192 111 # Ingestion puis service
193 −.venv/bin/python run.py sync # toutes les sources (ou: run.py sync forceoccasion)
112 +.venv/bin/python run.py sync # toutes les sources (ou : run.py sync forceoccasion)
194 113 .venv/bin/python run.py serve 8080 # → http://localhost:8080
195 114 .venv/bin/python run.py watch 120 # resynchronisation en boucle (minutes)
196 115 ```
197 116
198 −## Ajouter un concessionnaire (≈ 6 lignes)
199 −
200 −L'enregistrement est **auto-découvrant** : déposez un module dans
201 −`autoka/connectors/` contenant une sous-classe de `BaseConnector` avec un
202 −`source_id` — c'est tout. Pour un site D2C Media (le fournisseur le plus
203 −répandu au Québec) :
117 +### Ajouter un concessionnaire (≈ 6 lignes)
204 118
205 119 ```python
206 120 # dans autoka/connectors/d2c_dealers.py
@@ -211,12 +125,9 @@ class MonConcessionnaire(D2CConnector):
211 125 city = "Sherbrooke"
212 126 ```
213 127
214 −Puis : `.venv/bin/python run.py sync monconcessionnaire` — et l'inventaire
215 −apparaît sur le site avec fiches, galeries, liens sources… et dans le sitemap.
216 −Ajoutez l'entrée correspondante dans `data/sources.json` pour la page
217 −**Sources**.
128 +Puis `.venv/bin/python run.py sync monconcessionnaire` — l'inventaire apparaît sur le site avec fiches, galeries, liens sources… et dans le sitemap. Ajouter l'entrée correspondante dans `data/sources.json` pour la page **Sources**.
218 129
219 −## API
130 +### API
220 131
221 132 | Endpoint | Description |
222 133 |---|---|
@@ -230,73 +141,43 @@ Ajoutez l'entrée correspondante dans `data/sources.json` pour la page
230 141 | `GET /api/auth/ka/login` · `/api/favorites` | SSO KA ID + favoris hub |
231 142 | `GET /robots.txt` · `/sitemap.xml` | SEO — sitemaps dynamiques avec lastmod |
232 143
233 −## Mobile d'abord (aussi)
234 −
235 −<div align="center">
236 −<img src="docs/screenshot-mobile.png" alt="Auto-Ka — version mobile" width="320" />
237 −</div>
238 −
239 −## Couverture
240 −
241 −**Grands réseaux** — HGrégoire (mégacentres partout au Québec), Automobile En
242 −Direct, Occasion Beaucage (7 concessions), Le Prix du Gros, Méga Centre de
243 −liquidation, St-Jérôme Auto Dépôt, Ste-Foy Chrysler, Desmeules, Entrepôt Auto
244 −Durocher… **Motos & scooters** — Motos Illimitées, concessionnaires
245 −Harley-Davidson, Honda, Yamaha, Kawasaki, BMW, Vespa via PowerGo.
144 +## Déploiement
246 145
247 −**Toutes les régions** — Montérégie, Capitale-Nationale, Laurentides, Mauricie,
248 −Laval, Estrie, Outaouais, Centre-du-Québec, Chaudière-Appalaches, Lanaudière,
249 −Montréal, Saguenay–Lac-Saint-Jean, Bas-Saint-Laurent, Abitibi-Témiscamingue,
250 −Côte-Nord, Gaspésie…
146 +L'application tourne en production sur le **nœud M4M64b** du cluster MacLustr, sur le **port 8095**, exposée publiquement via **ngrok** sur **[www.auto-ka.com](https://www.auto-ka.com)**.
251 147
252 −Chaque source non connectable est **documentée avec sa raison** dans
253 −`data/sources.json` (ex. : doublon d'inventaire d'un autre site du même
254 −groupe, vérifié par VIN).
148 +Trois processus **PM2** :
255 149
256 −## Production
150 +| Processus PM2 | Commande | Rôle |
151 +|---|---|---|
152 +| **`auto-ka-web`** | `.venv/bin/python run.py serve 8095` | **API + frontend + SSR SEO** |
153 +| **`auto-ka-sync`** | `.venv/bin/python run.py watch 120` | **Resynchronisation toutes les 2 h** |
154 +| **`auto-ka-ngrok`** | `ngrok http --url=www.auto-ka.com 8095` | **Tunnel public** |
257 155
258 −Déployé sous **PM2** (3 processus) derrière **ngrok** :
156 +Philosophie d'exploitation : **on ne pousse que le code — le serveur maintient ses données lui-même.**
259 157
260 −```
261 −auto-ka-web .venv/bin/python run.py serve 8095 # API + frontend + SSR SEO
262 −auto-ka-sync .venv/bin/python run.py watch 120 # resync 2 h
263 −auto-ka-ngrok ngrok http --url=www.auto-ka.com 8095 # tunnel
264 −```
158 +## Développement remote-first (IMPORTANT)
265 159
266 −Philosophie d'exploitation : **on ne pousse que le code — le serveur maintient
267 −ses données lui-même.**
160 +- La **source de vérité** est le **repo git sur le nœud M4M64b** (`~/auto-ka`) — **il n'existe aucune copie laptop**.
161 +- Toute modification se fait **sur le nœud via SSH** : édition, build, `pm2 restart`, puis `git add / commit / push` **depuis le nœud** (agent forwarding actif).
162 +- Le remote **`origin` = spbgit** (git perso **[git.spboucher.ai](https://git.spboucher.ai)**), via l'**alias SSH `gitsrv`** → `gitsrv:srv/git/auto-ka.git`. **Pas GitHub.**
268 163
269 −## Principes
164 +## Captures supplémentaires
270 165
271 −1. **À la source** — les annonces viennent des sites des concessionnaires
272 − eux-mêmes, jamais des plateformes d'agrégation existantes.
273 −2. **Politesse** — délai ≥ 1 s entre requêtes, cache des pages détail
274 − (revalidation hebdomadaire), backoff sur rate-limit, User-Agent identifié.
275 −3. **Fidélité** — aucun prix inventé : si la source n'affiche pas de prix,
276 − `price = null` (« Prix sur demande »).
277 −4. **Traçabilité** — chaque fiche renvoie vers l'annonce originale.
278 −5. **Robustesse** — un connecteur qui casse n'affecte jamais les autres ;
279 − un 404 (véhicule vendu) ne bloque jamais une source ; détection de dérive
280 − (chute de volume → retraits suspendus + alerte).
281 −6. **Honnêteté envers les moteurs** — le HTML servi aux robots est le même
282 − que celui servi aux humains ; un véhicule vendu répond 410, une page
283 − inexistante 404.
166 +| | |
167 +|---|---|
168 +| Fiche véhicule | ![Fiche véhicule](docs/screenshot-vehicle.png) |
169 +| Statistiques du marché | ![Statistiques](docs/screenshot-stats.png) |
170 +| Verticale motos | ![Motos](docs/screenshot-motos.png) |
171 +| Page programmatique SEO | ![SEO marque](docs/screenshot-seo-marque.png) |
284 172
285 173 ---
286 174
287 175 <div align="center">
288 176
289 −## Auteur
290 −
291 −**Simon-Pierre Boucher**
292 −
293 −[![Email](https://img.shields.io/badge/contact@spboucher.ai-17181c?style=for-the-badge&logo=minutemailer&logoColor=ff5a2a)](mailto:contact@spboucher.ai)
294 −[![Git](https://img.shields.io/badge/git.spboucher.ai-17181c?style=for-the-badge&logo=git&logoColor=ff5a2a)](https://git.spboucher.ai)
295 −
296 −*Conçu, construit et déployé en une journée — du sondage de plateformes
297 −(60+ sites classifiés) aux 138 connecteurs, trois verticales et 18 475 pages
298 −indexables en production.*
177 +**Simon-Pierre Boucher** — [contact@spboucher.ai](mailto:contact@spboucher.ai) · [git.spboucher.ai](https://git.spboucher.ai)
299 178
300 179 © 2026 Simon-Pierre Boucher — tous droits réservés.
301 180
181 +Un service **Groupe Ka**
182 +
302 183 </div>
added docs/screenshot.png +0 −0

Binary file not shown.