← Back to projects

Halvyn

Flagship project

The interactive couple app that turns conversations into a game. ~117K lines of code, 1,135 commits, 17 Docker services in prod, 1,196 automated tests.

FR EN
~117K TS Lines
1,135 Commits
98 DB Tables
376 Endpoints
17 Prod services
9 Languages

Why I built it

With my partner, there was a whole layer of small everyday things — preferences, memories, instincts — that you normally only learn from each other over months, sometimes years. I didn't want to wait. Halvyn was born from that impatience: turn mutual discovery into a game to create more complicity, faster. A space where every quiz, every mini-game and every conversation adds another brick to what we know about each other.

Structural technical decisions

01
Progressive dual-backend

A legacy Express server proxying /v1 to a V1 backend in clean architecture (modules / repositories / services / presenters). Lets the monolith migrate to a modern API with no big-bang rewrite and no downtime.

02
React 18 + Capacitor monorepo

A single client codebase that ships native on iOS, Android and Web with more than 95% shared code — one design system, three platforms delivered.

03
Realtime couples + offline sync

WebSocket with user / couple / session rooms server-side, and an IndexedDB v3 LWW mutation queue client-side. Both partners play simultaneously and offline mutations (moods, bucket-list) replay deterministically on reconnect.

04
Cloudflare multi-Worker edge

Five Workers in front of the origin (rate-limiter, showcase-cache, media-CDN, cron dispatch, og-renderer) absorb bursts and public traffic without hitting the API.

The non-trivial challenge

Syncing a real-time quiz session for two

Each partner answers an A/B question independently, reveal only happens when both have answered, match is computed, Love Coins are distributed — and all of that has to survive a mobile disconnect mid-round, a double-answer, a partner quitting the app, or a Worker crashing. Idempotent, with clean state recovery, and mission / badge / streak events firing at the right time with no double-counting. A distributed WebSocket state machine with Postgres persistence and offline reconcile, not just pub/sub.

Lesson learned

If I did it again, I would start on the V1 clean architecture from commit one instead of dragging a legacy Express alongside for months — the /v1 proxy cost more in deploy complexity and mental load than a straight rewrite would have.

Features

🎯
Real-time A/B Quiz

Interactive questions between partners

💰
Gamified economy

Love Coins, streaks & missions

🎮
8 couple mini-games

Games to strengthen your bond

💬
Real-time chat

Text messages & voice notes

📖
Duo journal & calendar

Shared memories and events

🧠
AI Insights

AI-powered compatibility analysis

💳
Stripe Premium

Secure subscriptions and payments

🌍
Multi-platform

Web + iOS + Android, 9 languages

Tech Stack

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