Online halvyn.app
Halvyn
The couple app that turns conversations into a game.
Compatibility 87% illustration
In short
The interactive couple app that turns conversations into a game.
~159K lines of code, 102 DB tables, 380 endpoints, 17 Docker services in prod.
Highlights


-
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
By the numbers
- ~159K TS Lines
- 102 DB Tables
- 380 Endpoints
- 17 Prod services
- 9 Languages
The story
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
Progressive dual-backend
A legacy Express server proxying /v1 to a V1 backend in clean architecture (modules / repositories / services / presenters). The monolith moves to a modern API route by route, no big-bang rewrite, no downtime.
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.
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.
Cloudflare multi-Worker edge
Six Workers in front of the origin (rate-limiter, showcase-cache, media-CDN, cron dispatch, og-renderer, seo-localizer) absorb bursts and public traffic before it ever reaches 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.
Tech specs
Where it runs Docker Compose · PostgreSQL 16 · Redis Pub/Sub · Cloudflare R2 · OpenAI · Stripe
| Frontend | React 18 · Vite · TailwindCSS · Radix UI · Framer Motion |
|---|---|
| Backend | Express · TypeScript · Drizzle ORM · PostgreSQL 16 |
| Real-time | WebSocket · Redis Pub/Sub · BullMQ |
| Mobile | Capacitor 8 · iOS · Android |
| Infra | Docker Compose · GitHub Actions · Cloudflare R2 · Prometheus |
| Services | OpenAI · Stripe · Firebase · PostHog · Sentry |