SB
projets
Live · App Store · 2026 Personnel

Klabi

L'app qui remplace un groupe WhatsApp saturé de 60 maîtres de chiens à Vaulx-en-Velin. D'abord une PWA Spring Boot + React (mai 2026), puis une app iOS native publiée sur l'App Store en octobre 2026, notée 5/5. Une version Android (Kotlin, Jetpack Compose) est en test fermé.

Le problème

Pourquoi j'ai construit ça

Le groupe WhatsApp du quartier accumule 60 maîtres de chiens, mais l'info utile (qui sort ce soir ? à quel spot ? qui rejoint ?) se perd dans le scroll au milieu des photos et autres messages. Les gens hésitent à relancer le groupe « pour rien », et finissent par sortir seuls alors qu'on aurait pu se croiser. Klabi centralise précisément ces deux usages : se voir le soir et partager les parcours. Trois spots fixes affichent en temps réel qui s'y déplace, un membre peut lancer un appel ailleurs en deux clics, et chacun peut enregistrer sa balade GPS en direct puis la partager comme inspiration pour les autres.

iOS · Octobre 2026

L'app native, publiée sur l'App Store

Conçue, développée et publiée seule en SwiftUI. Bouton « Je sors » pour prévenir les voisins, carte du quartier (spots, points d'eau, vétérinaires, dangers signalés), carnet du chien avec rappels santé, alerte chien perdu, entraide pour la garde et la promenade, défi photo hebdomadaire.

Vie privée : la position exacte n'est jamais montrée aux autres, les données sont stockées dans iCloud (CloudKit), les messages privés sont chiffrés, pas de publicité.

Klabi iOS : la carte du quartierKlabi iOS : « Je sors » en deux gestesKlabi iOS : le carnet santé du chienKlabi iOS : le passeport du chienKlabi iOS : le défi photo de la semaine
PWA · Mai 2026

La première version, toujours en service

Klabi PWA : la carte des spots en vue satelliteKlabi PWA : la progression et le niveau
Highlights

Ce qui est intéressant techniquement

01

PWA installable avec enregistrement GPS en arrière-plan

Geolocation API avec watchPosition, Wake Lock API pour empêcher l'écran de s'éteindre pendant la marche, persistance localStorage avec TTL 6h pour reprendre une session interrompue (téléphone fermé, browser killed). Manifest + Service Worker pour l'installation « Ajouter à l'écran d'accueil » sur iOS et Android, le tracé reste fluide même hors-ligne.

02

Storage abstraction R2 ↔ FS via SpEL conditional beans

Interface PhotoStorage avec deux implémentations sélectionnées au boot via `@ConditionalOnExpression("'${klabi.r2.bucket:}'.isEmpty()")` : LocalFs en dev, Cloudflare R2 (S3-compatible, SDK AWS v2 + UrlConnectionHttpClient) en prod. Migration Flyway V25 backfille les avatars existants pour le swap, V26 redirige les photos seedées vers les URLs publiques R2.

03

Spring Boot 3.5 sous le health-check Render free tier

Le tier gratuit Render coupe le déploiement si l'app ne répond pas en 60s. Spring Boot 3.5 + Hibernate + Flyway boot en ~160s à froid : activation de `spring.main.lazy-initialization=true` pour différer la création des beans non-essentiels à la première requête. Combiné à un ping UptimeRobot toutes les 5 min sur `/actuator/health`, le cold-start de 50s disparaît pour les utilisateurs.

04

Auth JWT + magic-link via Brevo, sans Keycloak

Flow passwordless complet : génération d'un token aléatoire (UUID concaténé), hash SHA-256 stocké en DB avec TTL 30 min, email HTML envoyé via Brevo (300/jour gratuit), vérification + délivrance d'un JWT signé HS256. Spring Security configuré en stateless avec un filter JWT custom, CORS strict, endpoints publics whitelistés (auth, invite preview, health).

05

Activity feed + notifications via jsonb Postgres

Table `notifications` avec colonne jsonb pour les payload event-specific, mappée en Hibernate 6.6 via `@JdbcTypeCode(SqlTypes.JSON)`. Le service notification factorise les events (callout lancé, balade partagée, etc.) et l'activity feed du quartier les agrège pour les afficher en chronologique avec liens vers les profils membres et les balades.

06

26 migrations Flyway sans aucune réécriture

De V1 (schéma initial) à V26 (R2 photo URLs), chaque évolution du schéma est une migration versionnée, avec backfill explicite quand nécessaire (V25 strip `/uploads/` des URLs avatar legacy, V23 ajoute `shared_at` sans casser les anciennes balades). Le commentaire en tête de chaque fichier explique le *why* de la migration et pas seulement le *what*.

Stack

Sous le capot

iOS
Swift SwiftUI CloudKit MapKit App Store
Android
Kotlin Jetpack Compose Firebase Google Play (beta)
Backend
Java 17 Spring Boot 3.5 Spring Security JWT (JJWT) Spring Data JPA lazy-init
Frontend
React 18 TypeScript Vite Tailwind v4 React Router v7 Leaflet
PWA
Service Worker Web Manifest Geolocation API Wake Lock API localStorage TTL
Persistence
PostgreSQL 17 (Neon) Hibernate 6.6 Flyway (26 migrations) jsonb + @JdbcTypeCode
Storage
Cloudflare R2 (S3 SDK v2) PhotoStorage abstraction @ConditionalOnExpression
Email
Brevo (free 300/day) Magic-link flow HTML email templates
Ops
Render (free tier) Cloudflare Pages UptimeRobot keep-warm Sentry (errors)

Statut actuel

L'app iOS est publiée sur l'App Store depuis octobre 2026 (notée 5/5). La PWA sur invitation reste en service pour les voisins sans iPhone, et la version Android (Kotlin, Jetpack Compose, Firebase) est en test fermé sur Google Play.