15 KiB
Closer
Private daily questions for couples who want honest answers before shared conversations.
Product goal: private, mutual-reveal relationship questions with real encryption and calmer UX.
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.
Pricing Philosophy
No shady trials. No cancellation friction. One subscription per couple, not per person.
Subscription apps for couples have a trust problem — confusing trial wording, hard-to-cancel flows, and partners getting double-billed. Closer treats pricing the same way it treats relationships: clear, straightforward, and built on honesty.
| Principle | How Closer Handles It |
|---|---|
| Free tier | Generous by default. Daily questions, basic packs, recent history, spin wheel — all free, no time limit. |
| One sub per couple | One premium purchase unlocks it for both partners. No second billing. |
| Trial wording | No auto-renewal trials that silently convert. If there's a free period, you'll know exactly when and how it ends. |
| Cancellation | Clear, actionable instructions in-app and in docs. No hidden unsubscribe paths. |
| Restore | Works with one tap. If it breaks, support fixes it — no escalation maze. |
Screenshots
What Closer Does
Closer gives couples a private, shared space for guided connection. Every feature should support the product goal: private, mutual-reveal relationship questions with real encryption and calmer UX.
- 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 with copy and share, 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, 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, full history, Desire Sync, Connection Challenges, Memory Lane, and analytics — one subscription for both partners |
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 — No Time Limit, No Hidden Cap
All of this is free, forever. No credits, no daily limits that magically shrink after a week.
- Anonymous onboarding → email or Google sign-up
- 6-character invite code pairing (copy or share via any app)
- Daily question with full answer modes (text, scale, multiple choice, this-or-that)
- Private answer reveal flow once both partners have answered
- Question packs — 6,000+ bundled prompts across 22 categories (most packs included free)
- Spin wheel — category-based random questions for date nights
- Recent answer history (last 30 days)
- Push reminders with quiet-hour support
- Account deletion and data export
Premium Tier (Per-Couple, Not Per-Person)
One purchase unlocks premium for both partners. No separate subscriptions.
- Unlimited daily questions with premium-only question packs
- Full answer history — search, filter, export the complete timeline
- Saved spin wheel session history — revisit what landed
- Desire Sync — preferences alignment exercise for tough conversations
- Connection Challenges — multi-day guided programs (communication, trust, intimacy)
- Memory Lane — time capsules with locked prompts that open on future dates
- 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
devbranch - 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.mddocs/release/store-assets.mddocs/qa/private-mvp-checklist.mddocs/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.