# Lou·Ka — app iOS ### Tous les logements à louer du Québec. Dans votre poche. **Compagnon natif de [www.lou-ka.com](https://www.lou-ka.com)** · [dépôt web](https://git.spboucher.ai/lou-ka.git) ![Swift](https://img.shields.io/badge/Swift-5.9-141814?style=for-the-badge&logo=swift&logoColor=d9f26b) ![SwiftUI](https://img.shields.io/badge/SwiftUI-iOS_17%2B-141814?style=for-the-badge&logo=apple&logoColor=d9f26b) ![XcodeGen](https://img.shields.io/badge/XcodeGen-project.yml-141814?style=for-the-badge&logoColor=d9f26b) ![TestFlight](https://img.shields.io/badge/TestFlight-1.2_(3)-141814?style=for-the-badge&logoColor=d9f26b) ![Annonces](https://img.shields.io/badge/annonces_live-9000%2B-1c5c41?style=flat-square) ![Sources](https://img.shields.io/badge/sources-190%2B-1c5c41?style=flat-square) ![Reco](https://img.shields.io/badge/reco-on--device-1c5c41?style=flat-square) ![Design](https://img.shields.io/badge/design-%C3%A9ditorial_sharp-1c5c41?style=flat-square) *App SwiftUI 100 % native branchée sur l'API de production Lou-Ka — mêmes 9 000+ annonces, même design signature papier/encre/lime, plus un mode Découverte qui apprend vos goûts à chaque swipe.*
--- ## Les cinq onglets | | Onglet | Ce qu'on y fait | |---|---|---| | 📋 | **Annonces** | Recherche débouncée, chips de taille (1½…Studio), filtres complets (ville, **quartier dépendant de la ville**, loyer min–max, disponibilité, animaux, meublé, superficie, gestionnaire), pastilles de filtres actifs retirables d'un tap | | 🔥 | **Découvrir** | Une annonce plein écran à la fois, photos défilables façon *stories*. **Swipe à droite = coup de cœur 💚, à gauche = on passe.** L'algorithme apprend et reclasse la pile en continu | | 🗺 | **Carte** | Pastilles lime sur MapKit, presets de ville (Québec, Lévis, Montréal, Gatineau…), mini-fiche au tap → fiche complète | | 📊 | **Stats** | Tuiles KPI (médian, moyen, libres maintenant), histogramme des loyers, palmarès régions/villes/tailles, inclusions de l'offre, baisses de prix | | 🏢 | **Sources** | Registre des 255 gestionnaires : statut, compteurs, dernière synchronisation, recherche | La **fiche complète** reprend tout le contenu du site : galerie paginée, faits (dispo, superficie, étage, stationnement…), inclusions, description structurée (digest), carte, points d'intérêt à proximité, statistiques de quartier, et le bouton « Voir l'annonce originale » vers le site du gestionnaire. ## L'app en images
| Accueil — recherche & filtres | Découverte — swipe & reco | Fiche complète | |:---:|:---:|:---:| | ![Accueil](docs/captures/accueil.png) | ![Découverte](docs/captures/decouverte.png) | ![Fiche](docs/captures/fiche.png) | | Carte province | Le marché en chiffres | Registre des sources | |:---:|:---:|:---:| | ![Carte](docs/captures/carte.png) | ![Stats](docs/captures/stats.png) | ![Sources](docs/captures/sources.png) |
## Le mode Découverte, en 30 secondes Chaque swipe nourrit un **moteur de recommandation on-device** (`LouKa/Reco.swift`) : 1. Chaque annonce est décomposée en caractéristiques : ville, quartier, taille, tranche de prix (300 $), meublé, animaux, balcon, stationnement, gestionnaire. 2. Pour chaque caractéristique, on maintient un taux d'appréciation **lissé (Laplace)** : `(👍 + 1) / (👍 + 👎 + 2)`, pondéré par la confiance `1 + log(1 + n)`. 3. Le score d'une annonce = moyenne pondérée des taux de ses caractéristiques. La pile est **reclassée toutes les 8 décisions**, et ~1 carte sur 6 vient du reste du bassin (exploration) pour éviter la bulle de filtre. 4. Tout est persisté localement (`UserDefaults`) — **aucune donnée ne quitte l'appareil**. Les coups de cœur se retrouvent sous le ♥ en haut à droite. Après 4 likes de studios à ~900 $, l'en-tête affiche déjà « *Vos goûts : Studio · ~900 $* » et la pile s'adapte. ## Architecture ``` ios/ ├── project.yml # définition XcodeGen (cible, Info.plist, polices) ├── ExportOptions.plist # upload App Store Connect (méthode + team) └── LouKa/ ├── App.swift # point d'entrée, onglets, apparence nav, thème clair forcé ├── API.swift # client HTTPS → www.lou-ka.com (filtres complets) ├── Models.swift # décodage tolérant (un champ inattendu ≠ annonce perdue) ├── Reco.swift # moteur de recommandation du mode Découverte ├── Theme.swift # design system : palette, ombres décalées, typo, fr-CA ├── Fonts/ # Space Grotesk (instances statiques) + JetBrains Mono └── Views/ ├── HomeView.swift # accueil + feuille de filtres ├── DiscoverView.swift # swipe plein écran + coups de cœur ├── ListingCardView.swift # carte d'annonce ├── ListingDetailView.swift # fiche complète ├── MapTabView.swift # carte province ├── StatsView.swift # portrait du marché └── SourcesView.swift # registre des gestionnaires ``` **Design « éditorial sharp »** — porté du site : papier `#f5f3ee`, encre `#141814`, vert profond `#1c5c41`, lime électrique `#d9f26b`, bordures encre et ombres décalées, Space Grotesk pour les titres et les prix, JetBrains Mono pour les micro-étiquettes. Thème clair **forcé** (comme le site) pour que le mode sombre du téléphone ne rende jamais un texte illisible. > Détail typo : la Space Grotesk variable de Google Fonts n'expose aucun nom > PostScript d'instance — iOS ne voyait que « Light ». Les instances statiques > (Regular/Medium/Bold) sont générées avec fontTools et embarquées. ## Développer ```bash brew install xcodegen cd ios xcodegen generate # (ré)génère LouKa.xcodeproj depuis project.yml open LouKa.xcodeproj # ⌘R sur un simulateur iOS 17+ ``` Aucune dépendance externe — SwiftUI, MapKit, Observation, c'est tout. L'app pointe sur l'API de production ; pour une instance locale, changez `API.base` dans `LouKa/API.swift`. ## Publier sur TestFlight ```bash # bump MARKETING_VERSION / CURRENT_PROJECT_VERSION dans project.yml, puis : xcodegen generate xcodebuild archive -project LouKa.xcodeproj -scheme LouKa \ -destination 'generic/platform=iOS' -archivePath build/LouKa.xcarchive \ -allowProvisioningUpdates xcodebuild -exportArchive -archivePath build/LouKa.xcarchive \ -exportOptionsPlist ExportOptions.plist -allowProvisioningUpdates ``` L'export téléverse directement sur App Store Connect (signature automatique, fiche `com.spboucher.louka` existante) ; la build apparaît dans TestFlight après le traitement d'Apple. ## Principes 1. **Fidélité au web** — mêmes données, même langage visuel, aucun prix inventé. 2. **Robustesse** — décodage champ par champ avec repli : une source mal formée ne fait jamais disparaître les autres annonces. 3. **Vie privée** — le profil de goûts reste sur l'appareil, point. 4. **Zéro dépendance** — pas de SPM, pas de Pods : le SDK Apple suffit. ---
## Auteur **Simon-Pierre Boucher** [![Email](https://img.shields.io/badge/contact@spboucher.ai-141814?style=for-the-badge&logo=minutemailer&logoColor=d9f26b)](mailto:contact@spboucher.ai) [![Git](https://img.shields.io/badge/git.spboucher.ai-141814?style=for-the-badge&logo=git&logoColor=d9f26b)](https://git.spboucher.ai) © 2026 Simon-Pierre Boucher — tous droits réservés.