Sorti·Ka
Toutes les sorties et tous les événements du Québec. Un seul endroit.

Description
Sorti·Ka est un agrégateur indépendant de sorties et d'événements — concerts, festivals, spectacles, expositions, sport, famille — couvrant les 17 régions administratives du Québec, avec dates, lieux, gratuité, fiche par événement et lien direct vers la billetterie ou la source originale. Mise à jour horaire, automatiquement.
Trouver quoi faire au Québec, c'est ouvrir dix sites : les billetteries ne montrent que leurs propres spectacles, les calendriers municipaux que leur ville, les sites touristiques que leurs membres. Sorti·Ka retourne le problème : un connecteur dédié par source visite chaque calendrier, normalise chaque événement vers un schéma unique, déduplique les doublons inter-sources et détecte les changements en continu.
Sorti·Ka n'est pas une billetterie : c'est un index fidèle. Aucun prix inventé, aucune date devinée — chaque fiche est attribuée à sa source et renvoie vers la fiche originale pour les billets. Membre de la famille ·Ka (Lou·Ka, Immo·Ka, Auto·Ka, Food·Ka, Fabri·Ka, Resto·Ka…), architecture calquée sur le patron de référence Lou·Ka.
Fonctionnalités
- Recherche filtrée — région, catégorie, période, gratuité, texte libre, tri et pagination
- Fiche par événement — dates, lieu, prix, carte, événements similaires, SSR + JSON-LD Event pour le SEO
- 8 connecteurs actifs — ~15 000+ événements actifs, 428 villes, 17/17 régions :
| Source | Type / accès | Extraction |
|---|---|---|
| Le point de vente | billetterie QC — robots Allow: * |
listes HTML paginées (~2 500 événements, toute la province) |
| SIT Québec (Ministère du Tourisme) | données ouvertes CC 4.0 | API JSON Tourinsoft (~1 600 événements, toutes les régions) |
| Ville de Montréal | données ouvertes CC BY 4.0 | API CKAN datastore (~5 600 événements) |
| evenko | promoteur — robots Allow: /api/search* |
proxy Algolia (~460 grands concerts : Centre Bell, MTELUS…) |
| La Vitrine | Content-Signal search=yes |
sitemap + fiches HTML, cache incrémental (~5 100 représentations) |
| Atuvu.ca | Cloudflare → Scrapfly | sitemaps lastmod + fiches, rattrapage progressif |
| Ville de Sherbrooke | calendrier municipal public | JSON embarqué — 1 requête (~270 événements, heures locales) |
| Ville de Laval | données ouvertes CC 4.0 | JSON officiel (~290 activités, heures locales) |
| Ville de Brossard | API REST WordPress publique | /wp-json/wp/v2/city-event + fiches (bannière ou JSON-LD, ~400 événements) |
| Bandsintown | API publique par artiste | dates QC des artistes connus de la base (rotation 100 artistes/sync) |
| Ticketmaster | Discovery API officielle | prêt — clé requise (TICKETMASTER_API_KEY, gratuite) |
- Déduplication inter-sources — empreinte titre + ville + date : un même concert publié par 3 sources = une seule carte, la fiche la plus riche gagne
- Répertoire des municipalités MAMH — 1 250 villes + arrondissements + alias, homonymes résolus par population
- Persistance robuste — upsert par hash de contenu, délai de grâce 2 syncs, alerte de dérive, historique de syncs
- Page /stats — tableau de bord analytique + rapport PDF Groupe-KA
- Widget KA Agent — bulle de chat Groupe KA intégrée au frontend
- Heure précise (
start_time) et artistes (artists) — captés quand la source les publie (billetteries, calendriers municipaux), jamais inventés - 32 tests sur fixtures réelles, zéro réseau
Stack technique
- Python 3.14 + FastAPI — API JSON + rendu SSR SEO
- SQLite — stockage, diff et historique de synchronisation
- Frontend SPA sans build — HTML/JS, routeur History API, design system Groupe KA « éditorial sharp » (ka-ui)
- PM2 + ngrok — exécution résiliente et exposition publique
- Scrapfly — contournement Cloudflare pour Atuvu (clé
SCRAPFLY_API_KEYdans.env)
Structure du projet
connecteurs (1 module / source) normalisation (Event) SQLite (diff + grâce)
sortika/connectors/*.py → schema.py + normalize.py → db.py
▲ auto-découverts + regions.py (MAMH) │
│ ▼
watcher horaire (PM2) frontend SPA + fiches ← API FastAPI + SSR SEO
ingest.py watch frontend/index.html web.py + seo.py| Couche | Rôle | Fichiers |
|---|---|---|
| Connecteurs | 1 module Python par source : API JSON internes (Algolia evenko, Tourinsoft, CKAN), listes HTML, Scrapfly, caches incrémentaux | sortika/connectors/*.py |
| Schéma | Event standardisé : titre, catégories canoniques, lieu, ville, région (17), lat/lng, dates ISO + heure locale, artistes, gratuité/prix avec price_label source |
sortika/schema.py |
| Normalisation | dates FR/ISO, prix, 14 catégories, villes, entités HTML | sortika/normalize.py |
| Régions | Répertoire MAMH : 1 250 villes + arrondissements + alias | sortika/regions.py + data/villes_regions.json |
| Persistance | upsert par hash, délai de grâce, alerte de dérive | sortika/db.py |
| Dédup | empreinte titre + ville + date | schema.dedup_key() + web.py |
| API + SSR | recherche/filtres JSON, fiches /evenement/{uid} avec <head> unique + JSON-LD Event, robots, sitemaps |
sortika/web.py + sortika/seo.py |
| Frontend | SPA sans build, design system Groupe KA | frontend/index.html |
API
| Route | Description |
|---|---|
GET /api/events |
recherche — q, region, city, category, free, from, to, sort, pagination ; dédupliquée inter-sources |
GET /api/events/{uid} |
fiche complète d'un événement |
GET /api/stats |
volumes par région et par catégorie |
GET /api/sources |
registre des sources + événements actifs + dernière synchro |
GET /evenement/{uid} |
fiche HTML SSR (title/og/canonical + JSON-LD Event) |
GET /sitemap.xml · /robots.txt |
référencement |
GET /docs |
Swagger |
Démarrage local
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
.venv/bin/python -m pytest tests/ -q # 32 tests (fixtures réelles, zéro réseau)
.venv/bin/python run.py sync # ingestion des 10 sources actives
.venv/bin/python run.py web --port 8120 # API + frontend + SSR
.venv/bin/python run.py watch --interval 3600 # boucle d'ingestion horaireSecrets (gabarit : .env.example) : SCRAPFLY_API_KEY (connecteur Atuvu) ; TICKETMASTER_API_KEY (active le connecteur Ticketmaster, clé gratuite).
Déploiement
- Nœud : M3U96a (MacLustr) — répertoire
~/apps/sorti-ka - Port : 8120
- Domaine : www.sorti-ka.com (tunnel ngrok)
- PM2 (3 processus) :
sorti-ka-web— uvicorn sur le port 8120 (API + frontend + SSR)sorti-ka-sync— watcher horaire (mise à jour continue des 10 sources actives)sorti-ka-ngrok— tunnel vers www.sorti-ka.com
- Registre :
~/Desktop/cluster-skill/cluster-deployments.json
Développement remote-first (IMPORTANT)
La source de vérité est le repo git sur le nœud M3U96a (~/apps/sorti-ka), PAS une copie laptop. Toute modification se fait sur le nœud via SSH : édition, tests, pm2 restart, puis commit/push depuis le nœud.
origin= spbgit (git perso, git.spboucher.ai) — sur M3U96a, le remote est le chemin local/Users/simon-pierreboucher/srv/git/sorti-ka.git(les bare repos vivent sur ce même nœud).- Référence complète :
~/Desktop/cluster-skill/KA-REMOTE-DEV.md.
Principes
- Index fidèle — rien d'inventé : prix et dates viennent de la source, avec
price_labeloriginal conservé et attribution systématique. - Sources légitimes d'abord — données ouvertes officielles et sites au robots.txt permissif ; CGU/licences consignées en tête de chaque connecteur.
- Travail de moine — un connecteur robuste à la fois, testé sur fixtures réelles, avec alerte de dérive quand une source casse.
- Cohérence ·Ka — architecture Lou·Ka, design system Groupe KA.
Un service Groupe Ka — © 2026 Sorti·Ka — Simon-Pierre Boucher <contact@spboucher.ai>