# 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)



-141814?style=for-the-badge&logoColor=d9f26b)




*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 |
|:---:|:---:|:---:|
|  |  |  |
| Carte province | Le marché en chiffres | Registre des sources |
|:---:|:---:|:---:|
|  |  |  |
## 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**
[](mailto:contact@spboucher.ai)
[](https://git.spboucher.ai)
© 2026 Simon-Pierre Boucher — tous droits réservés.