docs: rewrite README with product clarity, add screenshots, register Room DAOs in DI

This commit is contained in:
null 2026-06-17 19:59:07 -05:00
parent 662a49df9d
commit fb87fe149a
9 changed files with 146 additions and 120 deletions

258
README.md
View File

@ -1,147 +1,165 @@
# Closer # Closer
A private, warm, intentional space for couples to build deeper emotional connection. Closer is a private Android app for couples 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, reminders, and date-planning tools.
## About The product is built as a native Kotlin app with Jetpack Compose and Firebase-backed sync. It is not a social network, not a therapy replacement, and not a productivity tracker. The core loop is simple: answer honestly, choose what to reveal, and keep a record of the conversations that mattered.
Closer is a native Android app designed to help couples communicate better, learn more about each other, and create intentional moments together. It focuses on emotional closeness — not task management, not social media, not productivity. ## Screenshots
## Screens & Features <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>
### Onboarding & Auth <p>
- Welcome flow with app introduction <img src="docs/screenshots/06-answer-history.png" alt="Closer answer history" width="180" />
- Create profile (display name, photo) <img src="docs/screenshots/07-settings.png" alt="Closer settings screen" width="180" />
- Sign up with email or Google <img src="docs/screenshots/02-login.png" alt="Closer login screen" width="180" />
- Login and password recovery </p>
- Anonymous trial mode
### Home ## What The App Does
- Suggested next-best action ranked by state
- Latest daily question status
- Quick-action cards for daily question, question packs, and history
- Streak tracking display
- Answer stats at a glance
### Daily Question Closer gives couples a shared space for guided connection:
- One question per day for the couple
- Multiple answer types: written, choice, scale, this-or-that
- Each partner answers privately, then both answers are revealed
### Question Packs - **Daily question**: one prompt at a time, with written, scale, choice, and this-or-that answer modes.
**20 categories across 2,500+ questions:** - **Private-first answers**: each person can answer privately before deciding whether to reveal or discuss.
- Fun, Communication, Conflict, Values, Emotional Intimacy - **Question packs**: 20 curated categories across 2,500+ bundled prompts, including communication, conflict, trust, money, stress, intimacy, marriage, parenting, and date night.
- Physical Intimacy, Sex & Desire, Future, Money, Stress - **Answer history**: local answer storage, review flows, delete controls, and partner reveal support.
- Boundaries, Conflict Repair, Date Night, Difficult Conversations - **Discussion threads**: question-specific conversation threads and reactions for follow-up.
- Gratitude, Home Life, Marriage, Parenting, Rebuilding Trust, Trust - **Partner pairing**: invite-code pairing, email invite flow, and partner-aware home states.
- **Spin wheel**: category-based random questions for date nights, long drives, and low-pressure conversations.
- **Date tools**: date matching, date planning preferences, and a shared bucket list foundation.
- **Settings and privacy**: account, notification, subscription, relationship, privacy, and deletion screens.
- **Subscriptions**: free and premium access paths powered by RevenueCat and Google Play Billing.
Each pack has curated questions at varying depth levels. Packs are labeled as free or premium. ## Product Shape
### Answer System Closer is optimized for short, meaningful sessions rather than endless engagement.
- Private written, choice, scale, or this-or-that answers
- Partner answer reveal flow
- Local answer history with delete
- Emoji reactions to partner answers
- Threaded conversation around specific questions
### Spin Wheel (Wheel of Questions) | Area | Product Behavior |
- Pick a category, spin the wheel, get a random question | --- | --- |
- Session-based: spin multiple questions in one session | Home | Shows the next best action based on pairing, daily question state, saved answers, and streaks. |
- Full session history for premium users | Questions | Uses local bundled content so the app remains fast and usable without waiting on the network. |
- Perfect for date nights, long drives, or quiet moments together | Partner Sync | Uses Firebase Auth and Firestore to isolate user, couple, invite, thread, and entitlement data. |
| Reminders | Uses FCM plus local notification preferences and quiet-hour controls. |
### Partner Pairing | Premium | Unlocks deeper packs, wheel history, expanded answer history, and future advanced suggestions. |
- Generate a 6-character invite code
- Invite partner via email
- Accept invite and confirm pairing
- Partner home screen showing partner's activity
### Settings
- Account management (email, display name, photo)
- Notification preferences (reminders, quiet hours)
- Privacy controls
- Subscription management via RevenueCat
- Relationship settings
- Account deletion
## Subscription Model
| Tier | Key Features |
|------|-------------|
| **Free** | Daily question, recent answer history, basic categories, basic reminders, streak tracking, limited spin wheel sessions |
| **Premium** | All free features + premium question packs, full spin wheel access with saved history, unlimited questions, full answer history with search, custom questions, private notes, exportable memories, advanced reminders, AI-assisted suggestions (future) |
Powered by RevenueCat + Google Play Billing.
## Tech Stack ## Tech Stack
| Layer | Tech | | Layer | Stack |
|-------|------| | --- | --- |
| Language | Kotlin | | Android | Kotlin, Jetpack Compose, Material 3, Navigation Compose |
| UI | Jetpack Compose, Material 3 | | Architecture | Clean architecture split across `core`, `data`, `domain`, and `ui` |
| Architecture | Clean Architecture (data / domain / ui / core) | | State | ViewModel, Kotlin Coroutines, Kotlin Flow |
| Navigation | Navigation Compose | | Dependency Injection | Hilt |
| DI | Hilt | | Local Data | Room, DataStore Preferences, bundled SQLite seed database |
| Local Storage | Room, DataStore Preferences | | Backend | Firebase Auth, Firestore, Cloud Functions, FCM |
| Backend | Firebase Auth, Firestore, Cloud Functions | | Observability | Firebase Analytics, Crashlytics |
| Notifications | Firebase Cloud Messaging | | Billing | RevenueCat, Google Play Billing |
| Analytics | Firebase Analytics, Crashlytics | | Security | Firebase App Check, Play Integrity |
| Payments | RevenueCat | | Backend Services | TypeScript Cloud Functions and an optional Express webhook service |
| Security | Firebase App Check (Play Integrity) | | Android SDK | min 26, target 35, compile 35 |
| Min SDK | 26 |
| Target SDK | 35 |
## Architecture ## Repository Layout
``` ```text
app/ .
├── core/ # Cross-cutting: analytics, billing, crash, features, Firebase, navigation, notifications ├── app/ # Native Android app
├── data/ # Data layer: Room DB, Firestore datasources, repository implementations, question JSON parser │ └── src/main/java/app/closer
├── domain/ # Domain layer: models, repository interfaces, use cases │ ├── core/ # Firebase, analytics, billing, navigation, notifications, security
└── ui/ # Presentation layer: screens + viewmodels per feature area │ ├── data/ # Room, Firestore data sources, repositories, seed parsing
├── answers/ # Answer history, answer reveal │ ├── domain/ # Models and repository contracts
├── auth/ # Login, signup, forgot password │ └── ui/ # Compose screens and feature ViewModels
├── components/ # Shared UI components (empty, error, loading states, special dates) ├── functions/ # Firebase Cloud Functions, TypeScript
├── home/ # Home screen, partner home ├── server/ # Optional Express webhook/health service
├── onboarding/ # Onboarding flow, create profile ├── seed/ # Question pack JSON and local DB generation
├── pairing/ # Invite creation, acceptance, confirmation ├── docs/ # QA notes, release prep, roadmap, screenshots
├── paywall/ # Subscription upsell └── firestore.rules # Firestore security rules
├── questions/ # Daily question, pack library, categories, composer, thread
├── settings/ # Account, notifications, privacy, relationship, subscription, delete
├── theme/ # Color, typography, theme configuration
└── wheel/ # Category picker, spin wheel, session, history, complete
``` ```
## Data Sources ## Getting Started
- **Firestore** — user profiles, couple relationships, question threads, invites, entitlements
- **Room** — local question cache, answered questions offline
- **DataStore** — user preferences, feature flags, settings
- **JSON assets** — bundled questions (2500+ across 20 categories)
## Build
```bash
cd app/
./gradlew assembleDebug # Build debug APK
./gradlew installDebug # Install on connected device/emulator
./gradlew assembleRelease # Build release APK (minified + shrunk)
```
### Prerequisites ### Prerequisites
- Android Studio Hedgehog or later - Android Studio / Android SDK with JDK 17
- JDK 17 - Firebase project with Auth, Firestore, Cloud Messaging, Crashlytics, Analytics, and App Check
- Firebase project with Auth, Firestore, Cloud Messaging, and App Check configured - `app/google-services.json`
- `google-services.json` in `app/` directory - RevenueCat project and Android API key
- RevenueCat project configured for Google Play - Node 20 for Firebase Functions and server tooling
## Design Principles Create local config:
- **Warm & Intimate** — The app should feel like a private emotional space, not a productivity tool ```bash
- **Privacy-first** — Data isolated by couple, strict Firestore rules cp local.properties.example local.properties
- **Offline-resilient** — Room cache keeps the app fast without network ```
- **Intentional** — Short, meaningful interactions. 5 good minutes > endless scrolling
- **2026 modern** — Smooth Material 3 animations, instant feedback, no jank Then add local-only values such as:
```properties
sdk.dir=/path/to/Android/Sdk
RC_API_KEY=your_revenuecat_android_key
```
### Android
```bash
./gradlew :app:assembleDebug
./gradlew :app:installDebug
```
Useful verification command:
```bash
./gradlew :app:compileDebugKotlin
```
### 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** stores bundled question categories, questions, date plans, and date preferences.
- **DataStore** stores local settings and lightweight preferences.
- **Firestore** stores users, couples, invites, question threads, date matches, bucket-list state, and entitlements.
- **Cloud Functions** handle reminder workflows, billing entitlement sync, RevenueCat webhooks, and security checks.
- **FCM** delivers reminders and partner activity notifications.
## Privacy And Safety Principles
- Couple data is scoped by couple ID and protected by Firestore rules.
- Answers are designed to be private first, then revealed intentionally.
- Account deletion and privacy screens are part of the first-class app surface.
- App Check and Play Integrity are included to reduce abusive backend access.
- Subscription state is verified server-side instead of trusting only the client.
## Current Status
This is a private MVP/internal testing codebase. The Android app builds, includes seeded question content, and has active flows for onboarding, auth, home, daily questions, packs, answer history, pairing, settings, wheel sessions, date tools, billing, notifications, and Firebase integration.
Release prep lives in:
- `docs/release/internal-testing-checklist.md`
- `docs/release/store-assets.md`
- `docs/qa/private-mvp-checklist.md`
- `docs/qa/ui-review.md`
## License ## License

View File

@ -39,6 +39,14 @@ object DatabaseModule {
@Singleton @Singleton
fun provideCategoryDao(db: AppDatabase) = db.categoryDao() fun provideCategoryDao(db: AppDatabase) = db.categoryDao()
@Provides
@Singleton
fun provideDatePlanPreferenceDao(db: AppDatabase) = db.datePlanPreferenceDao()
@Provides
@Singleton
fun provideDatePlanDao(db: AppDatabase) = db.datePlanDao()
@Provides @Provides
@Singleton @Singleton
fun provideDataStore(@ApplicationContext context: Context): DataStore<Preferences> = fun provideDataStore(@ApplicationContext context: Context): DataStore<Preferences> =

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB