Closer feature graphic

Closer

A private space for two.
Daily questions, mutual reveals, shared games, and calm rituals for couples.

Screenshots · What makes it different · Status · Run locally · QA

Android reference app · iOS scaffold in progress · Firebase backend · RevenueCat billing · Private repo

Android iOS Firebase RevenueCat License

--- Closer is a native relationship app for couples who want a quieter way to check in with each other. Each partner answers privately, reveals intentionally, and keeps a record of the conversations that matter. It is not a social network, therapy replacement, or productivity tracker. There are no public feeds, likes, followers, or infinite-scroll loops. The product loop is small on purpose: ```text answer honestly -> reveal together -> keep the conversation going ```

Screenshots

Fresh Android dark-mode captures from the current emulator build.
Ready Your turn Reveal ready
Home screen with the daily question ready to answer in dark mode Home screen after the partner answered and it is your turn in dark mode Home screen with the daily question reveal ready in dark mode
Play This or That Today Challenge
Play hub in dark mode This or That in dark mode Daily question in dark mode Connection challenge in dark mode

What makes it different

Private first
Partners answer independently before seeing each other's response.
Mutual reveal
The app is built around intentional sharing, not performative posting.
Couple-owned trust
Android encrypts answers, chat, history, and media on-device with couple-owned keys.
One subscription per couple
Premium unlocks for both partners through server-verified entitlements.
Curated prompts
Question packs are written and reviewed, not generated at answer time.
Calm by design
No feeds, likes, followers, public profiles, or pressure mechanics.

Product surface

| Area | Free | Premium | | --- | --- | --- | | Daily question | Included | Included | | Private answers + mutual reveal | Included | Included | | Curated question packs | Free + mixed access | Full access | | Spin the Wheel | Included | Included | | This or That / How Well Do You Know Me | Included | Included | | Recent answer history | Included | Included | | Memory Lane capsules | Limited | Full access | | Desire Sync | Limited | Full access | | Connection Challenges | Free + mixed access | Full access | | Date ideas, matches, and bucket list | Included | Premium ideas gated | | Push reminders + quiet hours | Included | Included | | Account deletion | Included | Included | Data export is not currently offered. The in-app privacy copy intentionally says so until a real export flow exists.

Platform status

| Platform | Status | Notes | | --- | --- | --- | | Android | Reference implementation | Kotlin, Jetpack Compose, Material 3, Hilt, Room, DataStore, Firebase, Tink | | iOS | Scaffold in progress | SwiftUI screen parity exists; pairing is blocked until E2EE interop is complete | | Backend | Shared source of truth | Firebase Auth, Firestore, Cloud Functions, FCM, App Check | | Billing | Server verified | RevenueCat webhook writes Firestore entitlements observed by the app | Android is the product source of truth today. iOS has the app shell, Firebase/RevenueCat integration, and SwiftUI screens, but end-to-end pairing waits on CryptoKit/Tink interoperability.

Architecture

```text Android (Kotlin/Compose) iOS (SwiftUI) Hilt · Room · DataStore MVVM · AppState · SPM Tink AEAD · Argon2id CryptoKit interop in progress \ / \ / v v Firebase + RevenueCat Auth · Firestore · Functions · FCM App Check · server-verified billing ``` Core rules: - Couple-scoped Firestore data. Users only read/write their own couple surface. - Server-mediated pairing. Invite lifecycle runs through Cloud Functions. - Local-first question content. Prompts ship with the app; assignment/sync uses Firebase. - Server-verified premium. Clients observe entitlements; they do not self-grant access. - No anonymous auth. Accounts use email/password or Google sign-in.

Security and privacy

- Android encrypts answer content, chat messages, media, capsules, and backed-up conversation history on-device before sync. - The server stores ciphertext for private content and never receives plaintext answers. - Recovery phrase wrapping uses Argon2id-derived keys. - Partner-assisted restore lets a trusted partner help restore the couple key to a new device. - Quiet hours are enforced server-side before push delivery. - Account deletion exists; data export does not yet. The canonical technical reference is [docs/Engineering_Reference_Manual.md](docs/Engineering_Reference_Manual.md).

Local development

Prerequisites - Android Studio, Android SDK, and JDK 17 - Node 20 for Firebase Functions tooling - Firebase project with Auth, Firestore, Cloud Messaging, Crashlytics, Analytics, and App Check - `app/google-services.json` - RevenueCat project and Android API key For iOS work: - macOS, Xcode 16, XcodeGen, and iOS 17+ - `iphone/Closer/GoogleService-Info.plist` - RevenueCat iOS API key
Android ```bash cp local.properties.example local.properties ``` ```properties sdk.dir=/path/to/Android/Sdk RC_API_KEY_ANDROID=your_revenuecat_android_key RC_API_KEY_IOS=your_revenuecat_ios_key ``` ```bash ./gradlew :app:assembleDebug ./gradlew :app:installDebug ./gradlew :app:testDebugUnitTest ```
iOS ```bash cd iphone xcodegen generate xed Closer.xcodeproj ``` ```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 test ``` ```bash npm run serve ```

QA and release

The repo keeps repeatable QA checks close to the code: | Check | Purpose | | --- | --- | | `scripts/theme-scan.sh` | Finds hardcoded theme/color regressions | | `scripts/wiring-scan.sh` | Finds orphaned routes, dead actions, and silent wiring breaks | | [docs/qa/](docs/qa/) | Manual QA playbooks and private MVP checklist | | [docs/release/](docs/release/) | Internal testing, store assets, and release prep | Live emulator fixtures and related credentials are intentionally local-only. Keep them in gitignored files under `qa/`, never in the tracked README or public docs.

Repository map

```text app/ Android app iphone/ iOS app functions/ Firebase Cloud Functions server/ Optional Express service seed/ Question content and seed tooling scripts/ Static QA scanners qa/ Local-only emulator fixture notes and smoke helpers docs/ Architecture, release, screenshots, and QA docs firestore.rules Firestore rules source of truth ```

Roadmap

In progress: - iOS E2EE interoperability with Android's Tink key material - More on-device/instrumented smoke coverage - Activity `uiMode` sync for in-app theme and dark artwork - Internal-testing release configuration, legal/support URLs, and RevenueCat offering validation Out of scope for now: - AI-generated core questions - Group relationship spaces beyond dyadic couples - Wear OS / watchOS companions - Live video or voice sessions

Project docs

| Doc | Purpose | | --- | --- | | [docs/Engineering_Reference_Manual.md](docs/Engineering_Reference_Manual.md) | Architecture, security model, data model, and known landmines | | [docs/brand/](docs/brand/) | Visual identity, asset system, generated art | | [docs/release/](docs/release/) | Release prep and store assets | | [docs/qa/](docs/qa/) | Manual QA checklist | | [Future.md](Future.md) | Backlog and roadmap | | [HISTORY.md](HISTORY.md) | Changelog and release notes | | [PROJECT.md](PROJECT.md) | Scope, feature matrix, architectural decisions |

License

Private project. All rights reserved.