# Closer

> *Your private moments stay private. Your information is securely encrypted, never read, and never sold. Only you and your paired partner have the key.*
>
> *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

<p>
  <img src="docs/screenshots/01-onboarding.png" alt="Closer onboarding screen" width="180" />
  <img src="docs/screenshots/03-home.png" alt="Closer home dashboard" width="180" />
  <img src="docs/screenshots/04-daily-question.png" alt="Closer daily question answer screen" width="180" />
  <img src="docs/screenshots/05-question-packs.png" alt="Closer question pack library" width="180" />
</p>

<p>
  <img src="docs/screenshots/06-answer-history.png" alt="Closer answer history" width="180" />
  <img src="docs/screenshots/08-play.png" alt="Closer play hub" width="180" />
  <img src="docs/screenshots/09-date-builder.png" alt="Closer date planning screen" width="180" />
  <img src="docs/screenshots/07-settings.png" alt="Closer settings screen" width="180" />
</p>

<p>
  <img src="docs/screenshots/02-login.png" alt="Closer login screen" width="180" />
</p>

---

## 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, select 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
- **Select Connection Challenges** — premium multi-day programs; free challenges available to all users
- **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

```text
.
├── 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](https://github.com/yonaskolb/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

```bash
# 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:

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

### Android

```bash
./gradlew :app:assembleDebug
./gradlew :app:installDebug
```

Useful verification command:

```bash
./gradlew :app:compileDebugKotlin
```

### iOS

```bash
cd iphone
xcodegen generate
xed Closer.xcodeproj
```

Build from the command line:

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

### Firebase Functions

```bash
cd functions
npm install
npm run build
npm run serve
```

### Optional Server

```bash
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.
