← Retour aux projets

Halvyn

Projet phare

L'app couple interactive qui transforme les conversations en jeu. ~117K lignes de code, 1 099 commits, 98 tables DB, 376 endpoints, 17 services Docker en prod.

FR EN
~117K Lignes TS
1 099 Commits
98 Tables DB
376 Endpoints
17 Services prod
9 Langues

Pourquoi j'ai construit ça

Avec ma chérie, il y avait toute une couche de petites choses du quotidien — préférences, souvenirs, réflexes — qu'on apprend l'un de l'autre au fil des mois, parfois des années. Je n'avais pas envie d'attendre. Halvyn est née de cette impatience : transformer la découverte mutuelle en jeu pour créer plus de complicité, plus vite. Un espace où chaque quiz, chaque mini-jeu et chaque conversation ajoute une brique à la connaissance qu'on a l'un de l'autre.

Décisions techniques structurantes

01
Dual-backend progressif

Un Express legacy qui proxy /v1 vers un backend V1 en clean architecture (modules / repositories / services / presenters). Permet de migrer le monolithe vers une API moderne sans big-bang ni downtime.

02
Monorepo React 18 + Capacitor

Un seul codebase client qui tourne natif sur iOS, Android et Web avec plus de 95 % de code partagé — un design system unifié, trois plateformes livrées.

03
Realtime couples + sync offline

WebSocket avec rooms user / couple / session côté serveur, et mutation queue IndexedDB v3 (LWW) côté client. Les deux partenaires jouent simultanément et les mutations offline (moods, bucket-list) rejouent déterministement à la reconnexion.

04
Edge Cloudflare multi-Workers

Cinq Workers devant l'origine (rate-limiter, showcase-cache, media-cdn, cron dispatch, og-renderer) qui absorbent les bursts et le trafic public sans toucher à l'API.

Le challenge non-trivial

Synchroniser une session de quiz temps réel à deux

Chaque partenaire répond indépendamment à une question A/B, la révélation ne se fait que quand les deux ont répondu, on calcule le match, on distribue les Love Coins — et tout ça doit survivre à une déconnexion mobile en plein round, une double-réponse, un partenaire qui quitte l'app, ou un Worker qui tombe. Idempotent, avec reprise d'état propre, et les événements missions / badges / streaks qui se déclenchent au bon moment sans double-comptage. Une state machine WebSocket distribuée avec persistance Postgres et reconcile offline, pas juste du pub/sub.

Leçon retenue

Si je refaisais, je démarrerais directement sur la clean architecture V1 dès le premier commit au lieu de traîner un Express legacy en parallèle pendant des mois — le proxy /v1 a coûté plus cher en complexité deploy et en mental-load qu'une réécriture franche l'aurait coûté.

Fonctionnalités

🎯
Quiz A/B temps réel

Questions interactives entre partenaires

💰
Économie gamifiée

Love Coins, streaks & missions

🎮
8 mini-jeux couple

Des jeux pour renforcer la complicité

💬
Chat temps réel

Messages texte & notes vocales

📖
Journal duo & calendrier

Souvenirs partagés et événements

🧠
Insights IA

Analyse de compatibilité par l'IA

💳
Premium Stripe

Abonnement et paiements sécurisés

🌍
Multi-plateforme

Web + iOS + Android, 9 langues

Stack technique

Frontend
React 18ViteTailwindCSSRadix UIFramer Motion
Backend
ExpressTypeScriptDrizzle ORMPostgreSQL 16
Real-time
WebSocketRedis Pub/SubBullMQ
Mobile
Capacitor 8iOSAndroid
Infra
Docker ComposeGitHub ActionsCloudflare R2Prometheus
Services
OpenAIStripeFirebasePostHogSentry