Skip to content

Latest commit

 

History

History
857 lines (700 loc) · 41.8 KB

File metadata and controls

857 lines (700 loc) · 41.8 KB

MoreSleep — Project Roadmap

MoreSleep optimizes your device usage throughout the day and week to fix your sleep schedule and facilitate that process. Set a bedtime goal, and your phone gradually winds down with you — science-backed notifications, progressive app restrictions, Apple Watch haptics, and real health tracking.


Table of Contents

  1. Architecture
  2. Data Flow
  3. Data Structures
  4. Deliverables & Implementation Steps
  5. Technical Implementation Details
  6. Demo Flow (5 Minutes)
  7. Success Criteria
  8. Future Enhancements (AI-Powered)

1. Architecture

Pattern: MVVM + Services + Coordinator

Why MVVM: It's the native SwiftUI paradigm. ViewModels are @Observable classes, Views are declarative, and services are injected via environment. Clean separation, easy to test, scales well from hackathon to production.

Layer Breakdown

Layer Role Technology
Views Pure UI, no business logic. Bind to ViewModels. SwiftUI (iOS + watchOS)
ViewModels Transform data for display, handle user actions, call services. @Observable classes
Services Encapsulate system APIs (Notifications, WatchConnectivity, Focus). Each behind a protocol for testability. Protocol-based, dependency-injected
Models Plain Swift structs/enums for domain data. Shared between iOS and watchOS targets. Swift structs, SwiftData @Model
Persistence Local-first storage. No backend needed. SwiftData (iOS 17+)
Coordinator Manages navigation flow (Onboarding → Main Tab → Settings). @Observable class with NavigationPath

Project Structure

MoreSleep/
├── Shared/                              ← Code shared between iOS and watchOS
│   ├── Models/
│   │   ├── SleepGoal.swift
│   │   ├── NightPlan.swift
│   │   ├── NotificationTemplate.swift
│   │   ├── SleepRecord.swift
│   │   ├── AppTier.swift
│   │   ├── ScienceReference.swift
│   │   └── MindfulnessExitState.swift
│   ├── Services/
│   │   └── SleepCalculator.swift        ← Bedtime math, sleep debt, rewind schedule
│   └── Resources/
│       └── ScienceData.json             ← All study references + notification copy
├── MoreSleep iOS/
│   ├── App/
│   │   ├── MoreSleepApp.swift           ← Entry point, permission requests, DI setup
│   │   └── AppCoordinator.swift         ← Navigation state machine
│   ├── ViewModels/
│   │   ├── OnboardingViewModel.swift
│   │   ├── TonightViewModel.swift
│   │   ├── ProgressViewModel.swift
│   │   └── SettingsViewModel.swift
│   ├── Views/
│   │   ├── Onboarding/
│   │   │   ├── WelcomeView.swift
│   │   │   ├── BedtimeGoalView.swift
│   │   │   ├── SetupGuideView.swift     ← Night Shift + Sleep Focus deep links
│   │   │   └── PermissionsView.swift
│   │   ├── Tonight/
│   │   │   ├── TonightView.swift        ← Countdown + checklist + mindfulness exit
│   │   │   ├── CountdownRing.swift      ← Animated circular countdown
│   │   │   ├── ChecklistRow.swift
│   │   │   ├── ScienceModalView.swift   ← "Why?" popup with study citations
│   │   │   └── MindfulnessExitView.swift← Escalating wait to opt out
│   │   ├── MockBlocking/
│   │   │   ├── MockBlockedAppsView.swift← Simulated app grid with shields
│   │   │   ├── AppShieldOverlay.swift   ← "This app is sleeping" shield
│   │   │   └── MockAppTierView.swift    ← Drag apps into restriction tiers
│   │   ├── Progress/
│   │   │   ├── WeekView.swift
│   │   │   └── SleepDebtCard.swift
│   │   └── Settings/
│   │       └── SettingsView.swift
│   ├── Services/
│   │   ├── NotificationService.swift    ← Schedule/cancel UNNotifications
│   │   ├── WatchSyncService.swift       ← WCSession management (iOS side)
│   │   ├── HealthKitService.swift       ← Read sleep, HR, HRV, SpO2, temp (Phase 2)
│   │   └── FocusService.swift           ← Sleep Focus scheduling (Phase 2+)
│   └── Extensions/
│       ├── Date+Sleep.swift
│       └── Color+Theme.swift
├── MoreSleep Watch/
│   ├── App/
│   │   └── MoreSleepWatchApp.swift      ← Watch entry point
│   ├── Views/
│   │   ├── WatchTonightView.swift       ← Bedtime countdown + simplified checklist
│   │   ├── WatchCountdownRing.swift     ← Compact countdown ring for watch
│   │   └── WatchWindDownView.swift      ← "Put your phone down" haptic screen
│   ├── Services/
│   │   ├── WatchSyncService.swift       ← WCSession management (watch side)
│   │   └── HapticEngine.swift           ← Haptic type selection + scheduling
│   └── Complications/
│       └── SleepComplications.swift     ← Watch face complications
└── Assets/
    └── Assets.xcassets

2. Data Flow

Core principle: Unidirectional — View → ViewModel → Service → System API → callback → ViewModel → View

A. Onboarding Flow

  1. User sets current bedtime (e.g., 12:00 AM) and target bedtime (e.g., 10:30 PM)
  2. User sets duration (e.g., 7 days)
  3. OnboardingViewModel creates a SleepGoal and persists via SwiftData
  4. SleepCalculator generates 7 NightPlan objects (one per night, each 15 min earlier)
  5. NotificationService schedules all notifications for tonight's plan
  6. WatchSyncService sends tonight's NightPlan to Apple Watch
  7. App navigates to TonightView

B. Nightly Loop

  1. App foregrounds → TonightViewModel loads today's NightPlan
  2. SleepCalculator computes time remaining, active checklist items
  3. At each notification offset:
    • Phone: system fires notification → user sees science-backed reminder
    • Watch: HapticEngine fires haptic matching current time-to-bed intensity
  4. 15 min before block: phone notification + watch haptic warn "App restrictions in 15 minutes"
  5. 5 min before block: second warning — phone notification + stronger watch haptic
  6. At block time: mock blocking UI activates — apps visually "shut down" in-app
  7. User taps notification → app opens → ScienceModalView shows study details
  8. If user wants to opt out → Mindfulness Exit Flow (replaces snooze — see below)

C. Mindfulness Exit Flow (Replaces Snooze)

There is no snooze button. If a user wants to disable the wind-down:

  1. User taps "I need more time" on TonightView
  2. MindfulnessExitView appears — full-screen, cannot be dismissed
  3. Screen shows a calm mindfulness prompt (breathing exercise, reflection question)
  4. Countdown timer shows how long they must wait before opting out
  5. Escalating wait times (resets each night):
Attempt Wait Time Free Window Prompt Theme
1st 1 minute 10 minutes "Take 3 deep breaths. Is this really worth losing sleep over?"
2nd 3 minutes 10 minutes "Guided box breathing: 4 in, 4 hold, 4 out, 4 hold"
3rd 5 minutes 5 minutes "Think about how you'll feel tomorrow morning."
4th+ 10 minutes 5 minutes "You've opted out 3 times tonight. Your sleep debt is growing."
  1. After wait completes → "Continue anyway" button appears
  2. Wind-down pauses, free window timer starts (visible on TonightView + Watch)
  3. When free window expires → wind-down resumes automatically, watch haptic fires
  4. MindfulnessExitState logged to SwiftData (count, duration, time — for user self-awareness, not shaming)

D. Watch Companion Flow

  1. iPhone → Watch: WatchSyncService sends NightPlan via transferUserInfo
  2. Watch displays simplified TonightView: countdown ring + next checklist item
  3. At each notification milestone: HapticEngine fires appropriate haptic type
  4. Haptic intensity decreases as bedtime approaches (calming, not alarming):
Time to Bed Haptic Type Feel
> 2 hours .notification Strong, attention-grabbing
1–2 hours .directionUp Medium, noticeable
30 min–1 hour .click Light tap
15–30 min .directionDown Gentle, subtle
< 15 min .success Soft, reassuring
Wake-up alarm .notification + .retry Strong, escalating
  1. Watch can send "Start wind-down now" action → iPhone via sendMessage
  2. During free window (mindfulness exit): Watch shows countdown timer

E. Morning Flow

  1. Morning notification fires ("Get sunlight in 30 minutes")
  2. Watch: wake-up haptic fires (.notification — strong, to wake up)
  3. App foregrounds → HealthKitService pulls last night's sleep data (Phase 2)
  4. SleepCalculator computes sleep debt (actual vs. target)
  5. ProgressViewModel updates weekly view with last night's results
  6. NotificationService schedules tonight's notifications (next night in plan)
  7. WatchSyncService sends updated data to Watch

F. Health Data Flow (Phase 2+)

  1. HealthKit observer query runs in background for sleep analysis samples
  2. On new data: HealthKitService publishes via Combine/async stream
  3. SleepRecord created and persisted
  4. Sleep debt recalculated → UI updates
  5. Updated sleep debt synced to Watch

3. Data Structures

SleepGoal
├── id: UUID
├── currentBedtime: Date (time-of-day)
├── targetBedtime: Date (time-of-day)
├── durationDays: Int
├── startDate: Date
├── isActive: Bool
└── computed: nightly increment (minutes) = total delta / durationDays

NightPlan
├── id: UUID
├── date: Date
├── targetBedtime: Date
├── windDownStart: Date (targetBedtime - 4 hours)
├── notifications: [ScheduledNotification]
├── checklistItems: [ChecklistItem]
├── status: .upcoming | .active | .completed | .optedOut
├── mindfulnessExits: [MindfulnessExitEvent]
└── mockBlockingActive: Bool

MindfulnessExitEvent
├── id: UUID
├── timestamp: Date
├── attemptNumber: Int (1st, 2nd, 3rd...)
├── waitDuration: TimeInterval (how long they waited)
├── freeWindowDuration: TimeInterval (how much free time granted)
├── freeWindowUsed: TimeInterval (how much they actually used)
└── resumedAutomatically: Bool (true = timer expired, false = user returned early)

MindfulnessExitState (runtime, not persisted)
├── currentAttempt: Int
├── waitTimeRemaining: TimeInterval
├── freeWindowRemaining: TimeInterval?
├── phase: .waiting | .reflecting | .freeWindow | .inactive
└── computed: nextWaitDuration, nextFreeWindow

ScheduledNotification
├── id: UUID
├── offsetMinutes: Int (negative = before bedtime)
├── template: NotificationTemplate
├── fireDate: Date
├── status: .pending | .delivered | .interacted

NotificationTemplate
├── id: String (e.g., "stop_eating")
├── offsetMinutes: Int (-240 = 4 hrs before)
├── emoji: String
├── title: String
├── body: String
├── scienceReference: ScienceReference

SleepRecord
├── id: UUID
├── date: Date
├── actualBedtime: Date?
├── actualWakeTime: Date?
├── sleepDuration: TimeInterval?
├── sleepStages: [SleepStage]? (from HealthKit)
├── hrv: Double?
├── restingHeartRate: Double?
├── source: .healthKit | .manual | .estimated

ScienceReference
├── claim: String
├── studies: [Study]
└── struct Study
    ├── authors: String
    ├── year: Int
    ├── journal: String
    ├── finding: String
    └── doi: String?

MockBlockedApp
├── id: UUID
├── name: String
├── iconName: String (SF Symbol or bundled asset)
├── tier: .blockFirst | .block30Min | .alwaysAllowed
├── isCurrentlyBlocked: Bool
└── blockedAt: Date?

ChecklistItem
├── id: String
├── title: String
├── description: String
├── offsetMinutes: Int
├── isCompleted: Bool
└── scienceReference: ScienceReference?

WatchPayload (Codable, sent via WatchConnectivity)
├── targetBedtime: Date
├── windDownStart: Date
├── nightNumber: Int
├── totalNights: Int
├── sleepDebt: TimeInterval (mocked in Phase 1)
├── currentChecklistItems: [ChecklistItem]
├── mockBlockingActive: Bool
└── mindfulnessExitState: MindfulnessExitState?

HapticScheduleEntry
├── fireDate: Date
├── hapticType: WKHapticType
├── repeatCount: Int (e.g., wake-up alarm repeats)
└── associatedNotificationId: String?

4. Deliverables & Implementation Steps

Phase 1 — Hackathon MVP

Goal: End-to-end wind-down experience with Apple Watch companion, mock app blocking UI, science-backed notifications, and mindfulness exit flow. No HealthKit, no Screen Time API. Mocked sleep debt. Real notifications and real Watch haptics.

1.1 Project Setup

  • 1.1.1 Create Xcode project with two targets:
    • iOS app (SwiftUI, iOS 17+, SwiftData)
    • watchOS app (SwiftUI, watchOS 10+)
  • 1.1.2 Set up folder structure per architecture above with Shared/ group for cross-target code
  • 1.1.3 Add capabilities:
    • UNUserNotifications (iOS)
    • WatchConnectivity (both targets)
  • 1.1.4 Create Info.plist entries:
    • NSUserNotificationsUsageDescription: "MoreSleep sends wind-down reminders at your target bedtime"
  • 1.1.5 Create color theme and basic design tokens
    • Dark-mode-first palette (sleep-themed deep blues, purples, warm ambers)
    • Define Color+Theme.swift extension with semantic colors
    • Ensure colors work on both iOS and watchOS

1.2 Shared Data Layer

  • 1.2.1 Define SleepGoal as SwiftData @Model (in Shared/)
    • Properties: id, currentBedtime, targetBedtime, durationDays, startDate, isActive
  • 1.2.2 Define NightPlan as SwiftData @Model (in Shared/)
    • Properties: id, date, targetBedtime, windDownStart, status, mindfulnessExits, mockBlockingActive
    • Relationship: belongs to SleepGoal
  • 1.2.3 Define NotificationTemplate as plain Codable struct (in Shared/)
  • 1.2.4 Define MindfulnessExitEvent and MindfulnessExitState (in Shared/)
  • 1.2.5 Define MockBlockedApp model with preset app list (in Shared/)
  • 1.2.6 Define WatchPayload Codable struct (in Shared/)
  • 1.2.7 Define HapticScheduleEntry struct (in Shared/)
  • 1.2.8 Create ScienceData.json with all 11 notification templates + study references
  • 1.2.9 Implement SleepCalculator service (in Shared/):
    • 1.2.9.1 calculateNightlyPlans(from goal: SleepGoal) -> [NightPlan]
    • 1.2.9.2 tonightsTarget(from goal: SleepGoal, on date: Date) -> Date
    • 1.2.9.3 notificationSchedule(for bedtime: Date) -> [ScheduledNotification]
    • 1.2.9.4 hapticSchedule(for bedtime: Date) -> [HapticScheduleEntry]
    • 1.2.9.5 mindfulnessWaitTime(attemptNumber: Int) -> (wait: TimeInterval, freeWindow: TimeInterval)

1.3 Apple Watch — WatchConnectivity + Haptics

  • 1.3.1 Create WatchSyncService protocol:
    • sendNightPlan(_ plan: WatchPayload) async
    • sendMindfulnessUpdate(_ state: MindfulnessExitState) async
    • onWindDownRequested(_ handler: @escaping () -> Void) (watch → phone action)
  • 1.3.2 Implement iOS-side WatchSyncService:
    • 1.3.2.1 Activate WCSession in MoreSleepApp.init()
    • 1.3.2.2 Use transferUserInfo for NightPlan sync (reliable, queued)
    • 1.3.2.3 Use sendMessage for real-time updates (mindfulness state, block state)
    • 1.3.2.4 Handle session(_:didReceiveMessage:) for watch → phone actions
  • 1.3.3 Implement watchOS-side WatchSyncService:
    • 1.3.3.1 Activate WCSession in MoreSleepWatchApp.init()
    • 1.3.3.2 Handle session(_:didReceiveUserInfo:) for NightPlan updates
    • 1.3.3.3 Handle session(_:didReceiveMessage:) for real-time state changes
    • 1.3.3.4 Send "start wind-down" message to phone
  • 1.3.4 Implement HapticEngine service (watchOS only):
    • 1.3.4.1 scheduleHaptics(for plan: WatchPayload) — maps notification offsets to haptic types
    • 1.3.4.2 Haptic type mapping by time-to-bed:
      • > 2h: .notification (strong, attention-grabbing)
      • 1-2h: .directionUp (medium, noticeable)
      • 30min-1h: .click (light tap)
      • 15-30min: .directionDown (gentle, subtle)
      • < 15min: .success (soft, reassuring)
      • Wake-up: .notification repeated 3x (strong, to wake)
    • 1.3.4.3 fireHaptic(_ type: WKHapticType) — immediate haptic
    • 1.3.4.4 cancelAllScheduled() — clear pending haptics
  • 1.3.5 Watch face complications:
    • 1.3.5.1 Circular small: mocked sleep debt number
    • 1.3.5.2 Modular large: bedtime countdown + sleep debt
    • 1.3.5.3 Corner: moon icon with hours until bedtime

1.4 Notification Service (iOS)

  • 1.4.1 Create NotificationService protocol:
    • requestPermission() async -> Bool
    • scheduleNotifications(for plan: NightPlan) async
    • cancelAllPending() async
  • 1.4.2 Implement LiveNotificationService using UNUserNotificationCenter:
    • 1.4.2.1 Permission request with proper error handling
    • 1.4.2.2 Schedule using UNCalendarNotificationTrigger with exact date components
    • 1.4.2.3 Cancel by notification identifiers (grouped by night)
    • 1.4.2.4 Schedule pre-block warnings at -15 min and -5 min before each blocking tier activates
  • 1.4.3 Add notification categories:
    • Category: "winddown_reminder" with actions: "why" (opens science modal), "done" (marks checklist item)
    • Category: "block_warning" with action: "ok" (acknowledge)
    • No snooze action — removed entirely
  • 1.4.4 Implement UNUserNotificationCenterDelegate:
    • Handle "why" action → set app state to show science modal
    • Handle "done" action → mark corresponding checklist item complete

1.5 Onboarding Flow (iOS)

  • 1.5.1 WelcomeView:
    • App name + tagline
    • Brief pitch (2-3 sentences)
    • "Get Started" button → navigates to BedtimeGoalView
  • 1.5.2 BedtimeGoalView:
    • 1.5.2.1 DatePicker (time only) for "When do you currently go to bed?"
    • 1.5.2.2 DatePicker (time only) for "When do you want to go to bed?"
    • 1.5.2.3 Stepper for "Over how many days?" (range: 3-30, default: 7)
    • 1.5.2.4 Live preview: "Your bedtime will shift by X minutes per night"
    • 1.5.2.5 Validation: target must be earlier than current, minimum 15-min shift per night
  • 1.5.3 SetupGuideView:
    • 1.5.3.1 Night Shift card with deep link + checkbox
    • 1.5.3.2 Sleep Focus card with deep link + checkbox
    • 1.5.3.3 "Skip for now" link at bottom
  • 1.5.4 PermissionsView:
    • 1.5.4.1 Notification permission request
    • 1.5.4.2 Success/failure state display
    • 1.5.4.3 "Continue" → saves goal, generates plans, schedules notifications, syncs to Watch, navigates to TonightView

1.6 Tonight Screen (iOS)

  • 1.6.1 TonightView — main screen layout:
    • 1.6.1.1 CountdownRing — large, centered, animated circular countdown
    • 1.6.1.2 Tonight's target bedtime displayed prominently (e.g., "11:45 PM")
    • 1.6.1.3 "Night X of Y" progress badge
    • 1.6.1.4 Scrollable wind-down checklist:
      • Each item: emoji, title, scheduled time, completion state
      • Items unlock as their time arrives
    • 1.6.1.5 "I need more time" button (replaces snooze):
      • Styled to be intentionally inconspicuous — small text, bottom of screen, muted color
      • Tapping opens MindfulnessExitView
  • 1.6.2 CountdownRing:
    • 1.6.2.1 Circular arc filling clockwise (0% at wind-down start → 100% at bedtime)
    • 1.6.2.2 Color: green (>2h) → yellow (1-2h) → orange (30min-1h) → red (<30min)
    • 1.6.2.3 Updates every second via TimelineView(.periodic(every: 1))
    • 1.6.2.4 Center text: hours and minutes remaining
  • 1.6.3 ChecklistRow:
    • 1.6.3.1 Emoji + title + scheduled time
    • 1.6.3.2 States: locked (greyed), active (highlighted), done (checked)
    • 1.6.3.3 Tap → toggle done
    • 1.6.3.4 "Why?" trailing button → ScienceModalView
  • 1.6.4 ScienceModalView (.sheet):
    • 1.6.4.1 Emoji + claim header
    • 1.6.4.2 Plain-language science explanation
    • 1.6.4.3 Study citations with authors, year, journal, key finding
    • 1.6.4.4 "Read full study" DOI link
    • 1.6.4.5 "Got it" dismiss button

1.7 Mindfulness Exit Flow (iOS)

  • 1.7.1 MindfulnessExitView — full-screen cover (cannot swipe to dismiss):
    • 1.7.1.1 Calm, dark UI with soft animations (breathing circle, gentle pulse)
    • 1.7.1.2 Reflection prompt that changes per attempt:
      • 1st: "Take 3 deep breaths. Is this really worth losing sleep over?"
      • 2nd: Guided box breathing animation (4-4-4-4 seconds)
      • 3rd: "Think about how you'll feel tomorrow morning."
      • 4th+: "You've opted out X times tonight. Your sleep debt is growing."
    • 1.7.1.3 Countdown timer — large, centered, counting down wait time
    • 1.7.1.4 "Continue anyway" button — hidden until timer reaches zero
    • 1.7.1.5 "Never mind, keep wind-down" button — always visible, returns to TonightView
  • 1.7.2 Free window state:
    • 1.7.2.1 When "Continue anyway" tapped: wind-down pauses
    • 1.7.2.2 TonightView shows free window countdown (e.g., "Apps available for 8:32")
    • 1.7.2.3 Watch shows matching free window countdown
    • 1.7.2.4 Notification at 2 min before window expires: "Wind-down resuming soon"
    • 1.7.2.5 When window expires: wind-down resumes automatically, watch haptic fires
  • 1.7.3 Escalation logic:
    • 1.7.3.1 Attempt counter stored on NightPlan.mindfulnessExits
    • 1.7.3.2 Wait times: 1 min → 3 min → 5 min → 10 min (4th+)
    • 1.7.3.3 Free windows: 10 min → 10 min → 5 min → 5 min (4th+)
    • 1.7.3.4 Counter resets to 0 at start of each new night

1.8 Mock App Blocking UI (iOS)

  • 1.8.1 MockAppTierView — app categorization screen:
    • 1.8.1.1 Grid of preset "apps" (Instagram, TikTok, YouTube, Messages, Phone, etc.) using SF Symbols or bundled icons
    • 1.8.1.2 Three drop zones: "Block first" / "Block 30 min before" / "Always allowed"
    • 1.8.1.3 Drag-and-drop to assign tiers
    • 1.8.1.4 Default suggestions pre-populated
    • 1.8.1.5 Persist assignments in SwiftData
  • 1.8.2 MockBlockedAppsView — the "hero" screen during wind-down:
    • 1.8.2.1 Grid showing all "apps" the user categorized
    • 1.8.2.2 As wind-down progresses, apps in active tiers visually "shut down":
      • Icon dims + grayscale filter
      • AppShieldOverlay slides over the icon
      • Subtle animation (fade or slide down)
    • 1.8.2.3 Apps shut down one by one with staggered timing (not all at once) — 3-5 second delay between each for dramatic effect
    • 1.8.2.4 Tier 1 apps block at wind-down start
    • 1.8.2.5 Tier 2 apps block 30 min before bedtime
    • 1.8.2.6 "Always allowed" apps stay lit throughout
  • 1.8.3 AppShieldOverlay:
    • 1.8.3.1 Dark overlay with moon icon
    • 1.8.3.2 Text: "This app is sleeping. You should be too."
    • 1.8.3.3 Small text: "Unlocks at [wake time]"
    • 1.8.3.4 Sleep-themed color scheme matching app theme

1.9 Watch App Screens

  • 1.9.1 WatchTonightView:
    • 1.9.1.1 Compact countdown ring (adapted for small screen)
    • 1.9.1.2 Target bedtime text
    • 1.9.1.3 Night X of Y badge
    • 1.9.1.4 Next upcoming checklist item (just one, not full list)
    • 1.9.1.5 "Start wind-down now" button → sends message to iPhone
  • 1.9.2 WatchWindDownView — shown during active wind-down:
    • 1.9.2.1 Simplified countdown
    • 1.9.2.2 Current checklist item
    • 1.9.2.3 "Put your phone down" message when close to bedtime
    • 1.9.2.4 Free window countdown (if mindfulness exit active)
  • 1.9.3 Haptic behavior:
    • 1.9.3.1 Fires at each notification milestone (matching phone notifications)
    • 1.9.3.2 Decreasing intensity as bedtime approaches (see haptic table above)
    • 1.9.3.3 Pre-block warnings: 15 min and 5 min before each tier blocks
    • 1.9.3.4 Wake-up: strong .notification haptic repeated 3x

1.10 Polish & Demo Prep

  • 1.10.1 Design and add app icon (moon/crescent/sleep themed)
  • 1.10.2 Add branded launch screen
  • 1.10.3 Create "demo mode" configuration:
    • Flag that compresses timeline (4 hours → 4 minutes)
    • Notifications fire every 20-30 seconds
    • Mock blocking activates visibly with staggered shutdowns
    • Watch haptics fire at compressed intervals
    • Mindfulness exit wait times compressed (60s → 5s)
  • 1.10.4 Test complete flow on physical iPhone + Apple Watch
  • 1.10.5 Prepare fallback: screen recording in case live demo has issues

Phase 2 — Core Health Integration (~2 weeks post-hackathon)

Goal: Replace mocked data with real HealthKit sleep tracking, compute actual sleep debt, and build a progress dashboard.

2.1 HealthKit Setup

  • 2.1.1 Add HealthKit capability and entitlement
  • 2.1.2 Add Info.plist keys for health data usage descriptions
  • 2.1.3 Create HealthKitService protocol
  • 2.1.4 Implement authorization for: sleep analysis, heart rate, HRV, resting HR, SpO2, respiratory rate, body temperature, steps, active energy, mindful minutes
  • 2.1.5 Register background delivery for sleep analysis

2.2 Sleep Tracking

  • 2.2.1 Create SleepRecord SwiftData model
  • 2.2.2 Query HealthKit for last night's sleep analysis
  • 2.2.3 Parse sleep stages (awake, REM, core, deep)
  • 2.2.4 Compute actual bedtime, wake time, sleep efficiency
  • 2.2.5 Display sleep quality score

2.3 Sleep Debt Calculator (Real Data)

  • 2.3.1 Replace mocked sleep debt with HealthKit-derived values
  • 2.3.2 Compute rolling 7-day and 14-day sleep debt
  • 2.3.3 Sync real sleep debt to Watch complications
  • 2.3.4 Display prominently on Tonight screen and Progress screen

2.4 Progress Dashboard

  • 2.4.1 Weekly bar chart: sleep duration vs. target
  • 2.4.2 Bedtime consistency graph: planned vs. actual
  • 2.4.3 Health metrics cards (HRV, resting HR, SpO2 trends)
  • 2.4.4 Sleep debt trend line
  • 2.4.5 Streak counter with reset on missed target
  • 2.4.6 Mindfulness exit history: "You opted out X times this week"

Phase 3 — Real Device Control & App Blocking (~3 weeks)

Goal: Replace mock blocking UI with real Screen Time API integration.

3.1 Screen Time API Integration

  • 3.1.1 Add Family Controls + App Groups capabilities
  • 3.1.2 Request Screen Time authorization
  • 3.1.3 Implement ScreenTimeService using ManagedSettingsStore
  • 3.1.4 Create ShieldConfigurationDataSource extension (custom block screen matching mock UI design)

3.2 Real App Tier System

  • 3.2.1 Replace mock app grid with FamilyActivityPicker
  • 3.2.2 Progressive blocking engine via DeviceActivityMonitor extension
  • 3.2.3 Real shield screens matching the mock design from Phase 1

3.3 Real Mindfulness Exit with System Unblock

  • 3.3.1 Mindfulness exit now actually removes ManagedSettingsStore shields
  • 3.3.2 Free window timer re-applies shields when expired
  • 3.3.3 Track unlock events in SwiftData

3.4 Focus Mode Automation

  • 3.4.1 Programmatic Sleep Focus scheduling
  • 3.4.2 Detect manual Sleep Focus activation → trigger early wind-down
  • 3.4.3 Communication limits during wind-down

Phase 4 — Ecosystem & Polish (~4 weeks)

Goal: Siri, CloudKit, advanced sensors, platform expansion.

4.1 Siri Shortcuts & App Intents

  • 4.1.1 "Start my wind-down routine"
  • 4.1.2 "Set tonight's bedtime to [time]"
  • 4.1.3 "How's my sleep debt?" (spoken response)
  • 4.1.4 "Log I'm going to bed"
  • 4.1.5 Personal automation: charger plugged in → start wind-down

4.2 CloudKit Sync

  • 4.2.1 Sync goals, plans, records across devices
  • 4.2.2 iCloud backup of sleep history
  • 4.2.3 Shared goals for accountability

4.3 Advanced Features

  • 4.3.1 Core Motion: phone face-down detection
  • 4.3.2 Screen Distance API: alert if phone too close during wind-down
  • 4.3.3 Night Shift / Grayscale automation setup flows
  • 4.3.4 Adaptive notifications (learn engagement, retire internalized habits)
  • 4.3.5 Smart bedtime suggestions from health data trends

5. Technical Implementation Details

Minimum Deployment Targets

  • iOS 17.0 — required for SwiftData and @Observable
  • watchOS 10.0 — required for modern SwiftUI watch layouts

Key Frameworks

Feature Framework Key Classes Target
Notifications UserNotifications UNUserNotificationCenter, UNCalendarNotificationTrigger iOS
Watch sync WatchConnectivity WCSession, WCSessionDelegate iOS + watchOS
Watch haptics WatchKit WKInterfaceDevice, WKHapticType watchOS
Watch complications ClockKit / WidgetKit CLKComplicationDataSource or WidgetFamily watchOS
Health data HealthKit HKHealthStore, HKSampleQuery, HKObserverQuery iOS (Phase 2)
App blocking FamilyControls + ManagedSettings AuthorizationCenter, ManagedSettingsStore iOS (Phase 3)
Focus modes Intents INFocusStatusCenter, deep links iOS (Phase 2+)
Persistence SwiftData @Model, ModelContainer, ModelContext iOS
Shortcuts AppIntents AppIntent, AppShortcutsProvider iOS (Phase 4)

Permissions Required (Phase 1 MVP)

Permission Info.plist Key When Requested
Notifications NSUserNotificationsUsageDescription Onboarding
(none for Watch — paired automatically via WatchConnectivity)

WatchConnectivity Strategy

  • transferUserInfo: Used for NightPlan sync — reliable, survives app termination, queued
  • sendMessage: Used for real-time updates — mindfulness exit state, block state changes, "start wind-down" action
  • updateApplicationContext: Used for latest sleep debt / tonight summary — watch reads on launch
  • Fallback: If watch app launches without phone context, show "Open MoreSleep on iPhone" message

Haptic Scheduling on Watch

  • watchOS does not support scheduled haptics in the background
  • Strategy: Use local notifications on the watch (UNUserNotificationCenter on watchOS) as triggers, then fire haptic in userNotificationCenter(_:willPresent:) delegate
  • Alternative: Keep watch app in foreground with a TimelineView that checks against haptic schedule and fires at correct times
  • Wake-up haptic: Schedule as a watchOS local notification with sound, which triggers haptic on delivery

Notification Scheduling Strategy

  • iOS limit: 64 pending local notifications maximum
  • Strategy: On each app launch, cancel stale, schedule next 7 nights
  • Trigger type: UNCalendarNotificationTrigger with exact DateComponents
  • Categories:
    • "winddown_reminder": actions: "why" (foreground, opens science modal), "done" (background, marks checklist)
    • "block_warning": actions: "ok" (dismiss acknowledgement)
  • No snooze action in any category
  • Pre-block warnings: scheduled at -15 min and -5 min before each tier activation time

Mock Blocking Architecture

  • MockBlockedApp stores a preset list of fake apps with SF Symbol icons
  • No system-level blocking — purely visual within our app
  • MockBlockedAppsView uses SwiftUI animations to show apps "shutting down"
  • Timer-driven: TimelineView checks current time against tier block times
  • Staggered animation: 3-5 second delay between each app blocking for dramatic effect
  • Designed to match what the real Screen Time shield will look like in Phase 3

6. Demo Flow (5 Minutes)

Pre-setup: Demo mode enabled — timeline compressed to minutes. Apple Watch paired and on wrist.

Time What to Show Script
0:00 – 0:30 Open app → Onboarding "You tell MoreSleep your current bedtime and your goal. It builds a personalized plan — midnight to 10:30 PM over 7 nights, shifting 15 minutes per night."
0:30 – 1:00 Tonight screen + Watch "Tonight's target: 11:45 PM. Countdown on your phone AND your wrist. Your Watch will tap you at every milestone."
1:00 – 1:30 Notification fires + Watch haptic "Phone notification: 'Last meal window closing.' Simultaneously, your Watch taps your wrist. Every reminder backed by peer-reviewed research."
1:30 – 2:00 Tap "Why?" → Science modal "Tap 'Why?' — Nakajima et al., 2020: eating within 3 hours of bed shifts your clock 1.5 hours. Full DOI link included."
2:00 – 2:30 App tier list "Drag apps into tiers. Instagram, TikTok — block first. Messages — 30 min before bed. Phone — always allowed."
2:30 – 3:30 HERO MOMENT: Apps shut down one by one "Wind-down starts. Watch taps — Instagram: sleeping. [pause] TikTok: sleeping. [pause] YouTube: gone. Each app shows 'This app is sleeping. You should be too.' Your phone is going to bed WITH you."
3:30 – 4:15 Mindfulness exit flow "What if you NEED your apps? No snooze button. You wait. 1 minute of guided breathing. 'Is this really worth losing sleep over?' Only then can you opt out — for 10 minutes. Second time? 3-minute wait. It gets harder each time."
4:15 – 4:30 Watch shows decreasing haptics "Notice: the Watch haptics get gentler as bedtime approaches. Strong taps early, soft nudges at the end. Calming you down, not alarming you."
4:30 – 5:00 Morning: wake-up haptic + sunlight reminder "Morning: strong Watch haptic wakes you. 'Get sunlight in 30 minutes' — Stanford research. Sleep debt is dropping. Night 3 of 7."

Hero moments:

  1. Apps visually shutting down one by one (2:30-3:30)
  2. Mindfulness exit replacing snooze — friction by design (3:30-4:15)
  3. Watch haptics that calm down as night deepens (4:15-4:30)

7. Success Criteria

Primary Metric

The gradual "shutting down" of apps is visible, dramatic, and satisfying, paired with Watch haptics that transition from alerting to calming. There is no easy escape — opting out requires genuine mindful reflection.

Phase 1 (MVP) Criteria

Core Loop:

  • User can set a bedtime goal in under 30 seconds
  • Tonight screen shows accurate, live countdown to target bedtime
  • Bedtime target advances by correct increment each night
  • Demo mode compresses the full wind-down into under 5 minutes

Notifications:

  • At least 5 unique science-backed notifications fire at correct times
  • Each notification has a working "Why?" button that opens study citations
  • Pre-block warnings fire at 15 min and 5 min before tier activation
  • No snooze action exists anywhere in the app

Apple Watch:

  • Watch receives and displays tonight's plan via WatchConnectivity
  • Watch fires haptics at each notification milestone
  • Haptic type decreases in intensity as bedtime approaches
  • Wake-up haptic fires strongly in the morning
  • Watch complications show bedtime countdown and mocked sleep debt
  • "Start wind-down now" button on Watch sends action to phone

Mock App Blocking:

  • User can drag mock apps into 3 tiers
  • Tier 1 apps visually block at wind-down start
  • Tier 2 apps visually block 30 min before bedtime
  • Apps shut down one-by-one with staggered animation (not all at once)
  • Custom shield overlay appears on "blocked" apps
  • "Always allowed" apps stay unblocked throughout

Mindfulness Exit:

  • "I need more time" button is present but inconspicuous
  • Tapping it opens full-screen mindfulness view with countdown
  • Wait time escalates: 1 min → 3 min → 5 min → 10 min
  • Free window decreases: 10 min → 10 min → 5 min → 5 min
  • "Continue anyway" button only appears after timer completes
  • "Never mind" option always available to return to wind-down
  • Escalation resets each night
  • Wind-down auto-resumes when free window expires

Overall:

  • Full wind-down → bedtime → morning sequence tells a compelling story
  • Every notification is traceable to a peer-reviewed study
  • App feels calm and intentional, not punitive

8. Future Enhancements (AI-Powered)

Smart Sleep Coach (On-Device ML)

  • Analyze HealthKit data patterns to suggest optimal personal bedtime
  • Correlate notification compliance with sleep quality improvement over time
  • Personalize notification timing based on user behavior patterns
  • Predict sleep debt recovery timeline: "At this rate, you'll clear your debt in 4 days"
  • Detect weekday vs. weekend patterns and adapt accordingly

Adaptive Notification Engine

  • Track engagement per notification type: tapped, dismissed, ignored
  • A/B test notification copy variations (rotate phrasing weekly)
  • Gradually retire notifications for internalized habits
  • Surface new recommendations based on specific sleep issues

Social & Accountability

  • Share sleep goals with friends/partners
  • "Sleep challenge" — compete on bedtime consistency
  • Accountability groups with anonymized weekly progress
  • Partner mode: "Your partner hit their bedtime target tonight"

Advanced Health Correlations

  • Correlate caffeine intake with sleep onset latency
  • Correlate exercise timing with sleep quality
  • Weekly "Sleep Insights" report with personalized findings
  • Detect patterns suggesting potential sleep disorders → suggest consultation

Platform Expansion

  • iPad companion: detailed analytics dashboard
  • Mac app: Screen Time sync, menu bar countdown widget
  • Widgets: Lock Screen countdown, Home Screen sleep debt
  • Live Activities: wind-down progress on Dynamic Island and Lock Screen

Notification Schedule Reference

Full notification timeline working backwards from target bedtime:

Offset Time (11 PM example) Emoji Title Key Science
-4h 7:00 PM 🍽️ Last meal window closing soon Late eating shifts circadian clock by 1.5h
-3h 8:00 PM 🚫 Stop eating now Body needs 3h to digest before sleep
-2.5h 8:30 PM 💧 Last water for the night Fluids 2h before bed increase wake-ups 40%
-2h 9:00 PM 💡 Switch to warm lighting Blue light suppresses melatonin by 85%
-90min 9:30 PM 📵 Wind-down is starting Melatonin window opens in 90 min
-1h 10:00 PM 📱 Screens off Screen light delays sleep 1-3 hours
-45min 10:15 PM 📖 Time to read 6 min of reading reduces stress by 68%
-30min 10:30 PM 🌡️ Cool your room down Ideal sleep temp: 65-68°F (18-20°C)
-15min 10:45 PM 🌙 Almost bedtime Melatonin is peaking, dim everything
0 11:00 PM 😴 Bedtime. You got this. Night X of goal complete
+8h 7:00 AM ☀️ Get sunlight in 30 minutes Morning light resets circadian clock

Science References

🍽️ Stop Eating 3 Hours Before Bed

  • Nakajima et al. (2020)Nutrients — Eating within 3h of bedtime associated with significantly worse sleep quality. Late eating delays circadian clock by up to 1.5 hours. doi.org/10.3390/nu12010095
  • Crispim et al. (2011)Journal of Clinical Sleep Medicine — High caloric intake at night correlated with longer sleep onset and more wake-ups. doi.org/10.5664/JCSM.1476

💧 Stop Drinking Water 2 Hours Before Bed

  • Abal et al. (2019)Sleep Medicine Reviews — Nocturia is the #1 cause of sleep fragmentation in adults. Fluid restriction 2h before bed reduces nighttime wake-ups by 40%.
  • Asplund (1995)Scandinavian Journal of Urology — Evening fluid intake directly correlated with number of nighttime awakenings.

📱 No Screens 1 Hour Before Bed

  • Chang et al. (2014)PNAS — iPad vs. printed book: iPad readers took 10 min longer to fall asleep, had 90 min less REM sleep, felt less alert next morning. doi.org/10.1073/pnas.1418490112
  • Czeisler et al. (2015)Harvard Medical School — Blue light suppresses melatonin for twice as long as green light. Shifts circadian rhythm by up to 3 hours.

📖 Reading Before Bed

  • Dr. David Lewis (2009)University of Sussex — 6 minutes of reading reduced stress by 68%. More effective than music (61%), walking (42%), or tea (54%).
  • Elphinston & Noller (2011)Journal of Applied Biobehavioral Research — Fiction readers showed greater ability to mentally escape. Readers fell asleep 26 min faster than non-readers.

🔴 Red Light Increases Melatonin

  • Zhao et al. (2012)Journal of Athletic Training — 14 nights of red light therapy significantly improved sleep quality and melatonin secretion. doi.org/10.4085/1062-6050-47.6.08
  • Figueiro et al. (2011)Neuroendocrinology Letters — Red wavelength (620-700nm) does not suppress melatonin. Blue (446-477nm) suppresses melatonin by up to 85%.

🌡️ Cool Room Temperature

  • Walker (2017)Why We Sleep — Core body temp must drop 2-3°F to initiate sleep. Ideal: 65-68°F (18-20°C).
  • Okamoto-Mizuno & Mizuno (2012)Journal of Physiological Anthropology — Thermal environment is one of the most significant factors affecting sleep quality. doi.org/10.1186/1880-6805-31-14

☀️ Morning Sunlight Resets Circadian Clock

  • Lewy et al. (2006)PNAS — Morning light directly sets the phase of the circadian clock for the next 24 hours. doi.org/10.1073/pnas.0601091103
  • Huberman (2021)Stanford / Huberman Lab — 10 min of morning sunlight within 30 min of waking sets circadian rhythm. Directly affects cortisol timing and melatonin onset.