Go to file
null 8967fd23cd fix(crypto): define single source of truth for encryptionVersion and document v0/v2 drift risk
- Add EncryptionVersion.kt with constants PLAINTEXT(0), MIGRATING(1), STRICT(2)
- Route CoupleEncryptionManager through the new constants and add explicit v2 branch
- Comment acceptInviteCallable.ts:91 explaining the version and sync contract
- Add TODO in iOS FirestoreService.swift warning that iOS MVP creates v0 couples

Fixes Risk #2 from review.md.
2026-06-20 22:29:43 -05:00
.vscode feat(db): add 2 new v2 question categories (difficult_conversations, home_life) — 20 total, 5,500 questions 2026-06-15 21:38:22 -05:00
app fix(crypto): define single source of truth for encryptionVersion and document v0/v2 drift risk 2026-06-20 22:29:43 -05:00
docs chore: update store assets doc with 9 screenshots (batch v1.0.22) 2026-06-20 02:02:05 -05:00
firestore-tests fix: prevent invite code enumeration via Cloud Function (batch v0.2.18) 2026-06-19 21:46:12 -05:00
functions fix(crypto): define single source of truth for encryptionVersion and document v0/v2 drift risk 2026-06-20 22:29:43 -05:00
gradle/wrapper feat: Firebase + RevenueCat stack, PLAN.md integration, 11 implementation batches (v0.1.0) 2026-06-15 18:43:43 -05:00
iphone fix(crypto): define single source of truth for encryptionVersion and document v0/v2 drift risk 2026-06-20 22:29:43 -05:00
seed fix: Q2 grammar quality pass on emotional_intimacy, parenting, stress questions + app.db rebuild 2026-06-19 00:50:23 -05:00
server feat: add onMessageWritten cloud function, notification settings screen, user repo cleanup 2026-06-20 18:25:05 -05:00
.eslintrc.js feat: Expo project bootstrap (v1.0.1) + untrack private docs 2026-05-13 04:21:43 -05:00
.firebaserc feat: Firebase project config — Firestore, Storage rules, Functions setup (batch v0.2.3) 2026-06-19 18:46:25 -05:00
.gitignore feat: implement partner-proof sealed answers (batches 1-8) 2026-06-20 00:23:58 -05:00
.prettierrc feat: Expo project bootstrap (v1.0.1) + untrack private docs 2026-05-13 04:21:43 -05:00
README.md docs(readme): update with MVP scope, both platforms, iOS port status 2026-06-20 22:20:31 -05:00
build.gradle.kts feat: Firebase + RevenueCat stack, PLAN.md integration, 11 implementation batches (v0.1.0) 2026-06-15 18:43:43 -05:00
firebase.json feat: strict E2EE — encryption migration, Firestore rules enforcement, version 2 protocol (batch v0.2.11) 2026-06-19 20:53:52 -05:00
firestore.indexes.json feat: Firebase project config — Firestore, Storage rules, Functions setup (batch v0.2.3) 2026-06-19 18:46:25 -05:00
firestore.rules refactor: update crypto, invite flow, and account screen patterns 2026-06-20 18:09:46 -05:00
gitleaks-current.json feat: update PrivacyScreen, add Firestore test scripts, gitleaks audit artifacts 2026-06-19 03:45:53 -05:00
gitleaks-history.json feat: update PrivacyScreen, add Firestore test scripts, gitleaks audit artifacts 2026-06-19 03:45:53 -05:00
gradle.properties feat: Firebase + RevenueCat stack, PLAN.md integration, 11 implementation batches (v0.1.0) 2026-06-15 18:43:43 -05:00
gradlew refactor: package rename from com.couplesconnect.app to app.closer, update build config and firebase setup 2026-06-16 20:03:58 -05:00
gradlew.bat refactor: package rename from com.couplesconnect.app to app.closer, update build config and firebase setup 2026-06-16 20:03:58 -05:00
local.properties.example feat: Firebase + RevenueCat stack, PLAN.md integration, 11 implementation batches (v0.1.0) 2026-06-15 18:43:43 -05:00
seed_generator.py refactor: package rename from com.couplesconnect.app to app.closer, update build config and firebase setup 2026-06-16 20:03:58 -05:00
settings.gradle.kts security: kimi-k2.7 review fixes — Ed25519 crypto API, Firestore rules try/catch removal, atomic idempotency, RevenueCat 8.20.0, rate limiter fix, remove plaintext fallback, tighten push wording 2026-06-16 22:42:53 -05:00
storage.rules feat: Firebase project config — Firestore, Storage rules, Functions setup (batch v0.2.3) 2026-06-19 18:46:25 -05:00

README.md

Closer

A private space for two people to talk, reflect, and stay close.

Closer is a couples relationship app built for partners who want a steadier way to talk, reflect, and make time for each other. It turns relationship check-ins into small, intentional rituals — one daily question, curated conversation packs, private answers, partner reveal flows, gentle reminders, and shared date planning.

The app is not a social network, not a therapy replacement, and not a productivity tracker. There are no public feeds, no likes, no followers, and no infinite scroll. The core loop is simple: answer honestly, choose what to reveal, and keep a record of the conversations that mattered.

Closer is built as native apps on Android (Kotlin / Jetpack Compose) and iOS (SwiftUI), both backed by the same Firebase stack and shared data model.


Screenshots

Closer onboarding screen Closer home dashboard Closer daily question answer screen Closer question pack library

Closer answer history Closer play hub Closer date planning screen Closer settings screen

Closer login screen


What Closer Does

Closer gives couples a private, shared space for guided connection:

  • Daily question — one prompt a day, with written, scale, multiple-choice, and this-or-that answer modes.
  • Private-first answers — each partner answers independently before deciding whether to reveal or discuss.
  • Question packs — 22+ curated categories spanning 6,000+ bundled prompts (communication, conflict, trust, intimacy, parenting, marriage, money, stress, date night, and more).
  • Answer history — review past questions and answers, delete controls, and partner reveal support.
  • Discussion threads — question-specific conversation threads and reactions for follow-up.
  • Partner pairing — 6-character invite code, email invite flow, and partner-aware home states.
  • Spin the wheel — category-based random questions for date nights, road trips, and low-pressure moments.
  • Date tools — swipe-to-match date ideas, date planning preferences, and a shared bucket list.
  • Settings & privacy — account, notifications, appearance, subscription, relationship, privacy, and account deletion flows.
  • Subscriptions — free and premium tiers powered by RevenueCat (Google Play Billing on Android, StoreKit on iOS).

Product Shape

Closer is optimized for short, meaningful sessions rather than endless engagement.

Area Behavior
Home Surfaces the next best action — daily question, partner activity, streaks, saved answers
Questions Local-bundled content so the app stays fast and usable without waiting on the network
Partner Sync Firebase Auth + Firestore isolate user, couple, invite, thread, and entitlement data per couple
Reminders FCM + local notification preferences and quiet-hour controls
Premium Unlocks deeper packs, wheel session history, full answer history, and advanced suggestion features

Platform Status

Platform Stack Status
Android Kotlin · Jetpack Compose · Material 3 · Hilt · Room · DataStore Active development — feature-complete MVP
iOS SwiftUI · MVVM · async/await · Firebase iOS SDK In progress — full scaffold + screen parity landed on dev branch
Backend Firebase Auth · Firestore · Cloud Functions (TypeScript) · FCM · App Check Shared source of truth for both platforms
Billing RevenueCat · Google Play Billing · StoreKit Server-verified entitlements via Cloud Function webhook

The Android app is the reference implementation — the iOS port is built to mirror it screen-for-screen and consume the same backend.


MVP Feature Scope

Free Tier

  • Anonymous trial → email or Google sign-up
  • 6-character invite code pairing (with email invite fallback)
  • Daily question with full answer modes (text, scale, multiple choice, this-or-that)
  • Private answer reveal flow once both partners have answered
  • Limited spin wheel sessions and basic question packs
  • Recent answer history (last 30 days)
  • Push reminders with quiet-hour support
  • Account deletion and data export

Premium Tier (via RevenueCat)

  • Unlimited daily questions and premium question packs
  • Full answer history and saved spin wheel session history
  • Desire Sync (preferences alignment exercise)
  • Connection Challenges (multi-day programs)
  • Memory Lane (time capsules)
  • Advanced analytics and relationship insights
  • Priority support

Out of Scope (Future)

  • AI-assisted question suggestions
  • Native group/relationship types beyond dyadic couples
  • Wearable (Wear OS / watchOS) companions
  • Live video or voice sessions

Tech Stack

Android

Layer Stack
Language Kotlin 2.x
UI Jetpack Compose, Material 3, Navigation Compose
Architecture Clean architecture — core/ · data/ · domain/ · ui/
State ViewModel · Kotlin Coroutines · Kotlin Flow
Dependency Injection Hilt
Local Data Room · DataStore Preferences · bundled SQLite seed
SDK min 26 · target 35 · compile 35

iOS

Layer Stack
Language Swift 5.9
UI SwiftUI · NavigationStack · TabView
Architecture MVVM · AppState ObservableObject · EnvironmentObject
Concurrency async/await
Dependency Management Swift Package Manager · XcodeGen (project.yml)
SDK iOS 17+

Backend (Shared)

Layer Stack
Auth Firebase Authentication (anonymous, email/password, Google)
Database Cloud Firestore
Server Logic Firebase Cloud Functions (TypeScript)
Push Firebase Cloud Messaging (FCM)
Security Firebase App Check · Play Integrity (Android) · DeviceCheck (iOS)
Billing RevenueCat (server-verified entitlements)
Analytics Firebase Analytics · Crashlytics

Repository Layout

.
├── app/                   # Native Android app (Kotlin)
│   └── src/main/java/app/closer
│       ├── core/          # Firebase, analytics, billing, navigation, notifications, security
│       ├── data/          # Room, Firestore data sources, repositories, seed parsing
│       ├── domain/        # Models and repository contracts
│       └── ui/            # Compose screens and feature ViewModels
├── iphone/                # Native iOS app (SwiftUI)
│   ├── ARCHITECTURE_AUDIT.md   # iOS port blueprint (49 screens, schema, models)
│   ├── project.yml             # XcodeGen project spec
│   ├── Package.swift           # SPM dependency manifest
│   └── Closer/
│       ├── Models/             # Firestore + domain codable types
│       ├── Core/               # Auth, Billing, Notifications
│       ├── Services/           # FirestoreService (callable wrappers)
│       ├── Theme/              # CloserTheme (colors, typography, spacing)
│       ├── Components/         # Shared SwiftUI components
│       ├── Navigation/         # Root ContentView + TabView routing
│       ├── Onboarding/         # Onboarding, login, signup, profile creation
│       ├── Pairing/            # Invite code, partner confirm, recovery
│       ├── Home/               # Home dashboard, streak, partner mirror
│       ├── Questions/          # Daily question, answer reveal, history, packs
│       ├── Play/               # Play hub + games (ThisOrThat, HowWell, DesireSync)
│       ├── Wheel/              # Spin wheel with animated 8-slice picker
│       ├── Dates/              # Date swipe, matches, builder, bucket list
│       └── Settings/           # Settings, paywall, help, data export
├── functions/             # Firebase Cloud Functions (TypeScript)
│   └── src/
│       ├── auth/                # Auth flow + invite lifecycle
│       ├── billing/             # RevenueCat webhook + entitlement sync
│       ├── couples/             # Pairing, leave, daily question triggers
│       ├── questions/           # onAnswerWritten, onMessageWritten, threads
│       └── server/              # Internal Express webhook service (not client-facing)
├── server/                # Optional Express webhook/health service
├── seed/                  # Question pack JSON and local DB generation
├── docs/                  # QA notes, release prep, roadmap, screenshots
└── firestore.rules        # Firestore security rules

Getting Started

Prerequisites

  • Android: Android Studio · Android SDK · JDK 17
  • iOS: Xcode 16 · macOS · XcodeGen (brew install xcodegen)
  • Firebase: Project with Auth, Firestore, Cloud Messaging, Crashlytics, Analytics, App Check
  • Android config: app/google-services.json
  • iOS config: iphone/Closer/GoogleService-Info.plist
  • Billing: RevenueCat project with Android and iOS API keys
  • Node 20 for Firebase Functions tooling

Local config

# Android
cp local.properties.example local.properties
# iOS
cp iphone/Closer/GoogleService-Info.plist.example iphone/Closer/GoogleService-Info.plist

Add local-only values such as:

sdk.dir=/path/to/Android/Sdk
RC_API_KEY_ANDROID=your_revenuecat_android_key
RC_API_KEY_IOS=your_revenuecat_ios_key

Android

./gradlew :app:assembleDebug
./gradlew :app:installDebug

Useful verification command:

./gradlew :app:compileDebugKotlin

iOS

cd iphone
xcodegen generate
xed Closer.xcodeproj

Build from the command line:

xcodebuild -project iphone/Closer.xcodeproj \
           -scheme Closer \
           -destination 'platform=iOS Simulator,name=iPhone 15' \
           build

Firebase Functions

cd functions
npm install
npm run build
npm run serve

Optional Server

cd server
npm install
npm run dev

Data Model

Closer combines local-first question content with cloud sync for shared relationship state:

  • Room (Android) / local bundled JSON (iOS) stores seeded question categories, questions, and date preferences — the app stays usable offline.
  • DataStore (Android) / UserDefaults (iOS) stores local settings and lightweight preferences.
  • Firestore stores users, couples, invites, daily questions, answer history, date matches, bucket-list state, time capsules, gentle reminders, and entitlements.
  • Cloud Functions handle pairing lifecycle, reminder workflows, billing entitlement sync, RevenueCat webhooks, partner activity triggers (FCM), and security checks.
  • FCM delivers reminders and partner activity notifications to both platforms.

Privacy & Safety Principles

  • Couple data is scoped by couple ID and protected by Firestore security rules — no other couple can read another couple's data.
  • Answers are private first, then revealed intentionally by the partner.
  • Account deletion and privacy screens are first-class surfaces in the app.
  • App Check (Play Integrity on Android, DeviceCheck on iOS) blocks abusive backend access.
  • Subscription state is verified server-side via Cloud Functions rather than trusting the client.
  • All private answer and capsule content is end-to-end encrypted with couple-owned keys (Android uses Tink; iOS uses Apple CryptoKit in a follow-up batch).

Current Status

This is a private MVP / internal testing codebase.

Complete

  • Android MVP — onboarding, auth (anonymous/email/Google), pairing, home, daily questions, question packs, answer history, spin wheel, date tools, settings, billing, notifications, Firebase integration, E2EE crypto layer
  • iOS port scaffold — all 49 screens mapped to SwiftUI views, Firebase/RevenueCat integration, full screen parity landed on dev branch
  • Backend — 17 Cloud Functions (callable, triggers, scheduled, webhook) covering full relationship lifecycle
  • Seeded question content — 6,000+ prompts across 22 categories

In Progress

  • iOS Xcode project generation and build verification
  • iOS E2EE layer (CryptoKit interop with Android Tink)
  • Final QA pass on both platforms

Release Prep

  • docs/release/internal-testing-checklist.md
  • docs/release/store-assets.md
  • docs/qa/private-mvp-checklist.md
  • docs/qa/ui-review.md

Project History

See HISTORY.md for the full changelog and release notes.

See PROJECT.md for detailed scope, feature matrix, and architectural decisions.


License

Private project. All rights reserved.