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
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
- Welcome flow with app introduction
- Create profile (display name, photo)
- Sign up with email or Google
- Login and password recovery
- Anonymous trial mode
<p>
<img src="docs/screenshots/06-answer-history.png" alt="Closer answer history" width="180" />
<img src="docs/screenshots/07-settings.png" alt="Closer settings screen" width="180" />
<img src="docs/screenshots/02-login.png" alt="Closer login screen" width="180" />
</p>
### Home
- 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
## What The App Does
### Daily Question
- 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
Closer gives couples a shared space for guided connection:
### Question Packs
**20 categories across 2,500+ questions:**
- Fun, Communication, Conflict, Values, Emotional Intimacy
- Physical Intimacy, Sex & Desire, Future, Money, Stress
- Boundaries, Conflict Repair, Date Night, Difficult Conversations
- Gratitude, Home Life, Marriage, Parenting, Rebuilding Trust, Trust
- **Daily question**: one prompt at a time, with written, scale, choice, and this-or-that answer modes.
- **Private-first answers**: each person can answer privately before deciding whether to reveal or discuss.
- **Question packs**: 20 curated categories across 2,500+ bundled prompts, including communication, conflict, trust, money, stress, intimacy, marriage, parenting, and date night.
- **Answer history**: local answer storage, review flows, delete controls, and partner reveal support.
- **Discussion threads**: question-specific conversation threads and reactions for follow-up.
- **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
- 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
Closer is optimized for short, meaningful sessions rather than endless engagement.
### Spin Wheel (Wheel of Questions)
- Pick a category, spin the wheel, get a random question
- Session-based: spin multiple questions in one session
- Full session history for premium users
- Perfect for date nights, long drives, or quiet moments together
### Partner Pairing
- 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.
| Area | Product Behavior |
| --- | --- |
| Home | Shows the next best action based on pairing, daily question state, saved answers, and streaks. |
| Questions | Uses local bundled content so the app remains fast and usable without waiting on the network. |
| 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. |
| Premium | Unlocks deeper packs, wheel history, expanded answer history, and future advanced suggestions. |
## Tech Stack
| Layer | Tech |
|-------|------|
| Language | Kotlin |
| UI | Jetpack Compose, Material 3 |
| Architecture | Clean Architecture (data / domain / ui / core) |
| Navigation | Navigation Compose |
| DI | Hilt |
| Local Storage | Room, DataStore Preferences |
| Backend | Firebase Auth, Firestore, Cloud Functions |
| Notifications | Firebase Cloud Messaging |
| Analytics | Firebase Analytics, Crashlytics |
| Payments | RevenueCat |
| Security | Firebase App Check (Play Integrity) |
| Min SDK | 26 |
| Target SDK | 35 |
| Layer | Stack |
| --- | --- |
| Android | Kotlin, Jetpack Compose, Material 3, Navigation Compose |
| Architecture | Clean architecture split across `core`, `data`, `domain`, and `ui` |
| State | ViewModel, Kotlin Coroutines, Kotlin Flow |
| Dependency Injection | Hilt |
| Local Data | Room, DataStore Preferences, bundled SQLite seed database |
| Backend | Firebase Auth, Firestore, Cloud Functions, FCM |
| Observability | Firebase Analytics, Crashlytics |
| Billing | RevenueCat, Google Play Billing |
| Security | Firebase App Check, Play Integrity |
| Backend Services | TypeScript Cloud Functions and an optional Express webhook service |
| Android SDK | min 26, target 35, compile 35 |
## Architecture
## Repository Layout
```
app/
├── core/ # Cross-cutting: analytics, billing, crash, features, Firebase, navigation, notifications
├── data/ # Data layer: Room DB, Firestore datasources, repository implementations, question JSON parser
├── domain/ # Domain layer: models, repository interfaces, use cases
└── ui/ # Presentation layer: screens + viewmodels per feature area
├── answers/ # Answer history, answer reveal
├── auth/ # Login, signup, forgot password
├── components/ # Shared UI components (empty, error, loading states, special dates)
├── home/ # Home screen, partner home
├── onboarding/ # Onboarding flow, create profile
├── pairing/ # Invite creation, acceptance, confirmation
├── paywall/ # Subscription upsell
├── 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
```text
.
├── app/ # Native Android app
│ └── 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
├── functions/ # Firebase Cloud Functions, TypeScript
├── 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
```
## Data Sources
- **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)
```
## Getting Started
### Prerequisites
- Android Studio Hedgehog or later
- JDK 17
- Firebase project with Auth, Firestore, Cloud Messaging, and App Check configured
- `google-services.json` in `app/` directory
- RevenueCat project configured for Google Play
- Android Studio / Android SDK with JDK 17
- Firebase project with Auth, Firestore, Cloud Messaging, Crashlytics, Analytics, and App Check
- `app/google-services.json`
- RevenueCat project and Android API key
- 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
- **Privacy-first** — Data isolated by couple, strict Firestore rules
- **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
```bash
cp local.properties.example local.properties
```
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

View File

@ -39,6 +39,14 @@ object DatabaseModule {
@Singleton
fun provideCategoryDao(db: AppDatabase) = db.categoryDao()
@Provides
@Singleton
fun provideDatePlanPreferenceDao(db: AppDatabase) = db.datePlanPreferenceDao()
@Provides
@Singleton
fun provideDatePlanDao(db: AppDatabase) = db.datePlanDao()
@Provides
@Singleton
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