# TimeSafari Notifications — LLM Implementation Directive (v2.0) _Last updated: August 12, 2025_ ## 0) Role & Objective **You are the implementation LLM.** Build an **offline-first daily notifications system** for Android (Kotlin) and iOS (Swift) that **prefetches -> caches -> schedules -> displays** content **without requiring network at display time**. Favor **reliability over richness**. ## 1) Golden Rules 1. **Follow the pipeline:** **Prefetch → Cache → Schedule → Display.** 2. **Never depend on network at display time.** All assets must be local. 3. **Design for failure.** Always have a last-known-good and an emergency fallback. 4. **Keep content scannable (<3s), single message, actionable.** 5. **Measure everything** (fetch success, delivery, engagement, stale usage). 6. **Minimize battery impact** and respect platform limitations and user settings. 7. **Ask only when needed:** if a required input is missing, use the defaults below; otherwise proceed. ## 2) Default Assumptions (use unless overridden) - **Product mode:** Lightweight Daily Updates (text + emoji) with option to extend to media later. - **Fetch size:** 1–2 KB JSON daily. - **User schedule default:** 07:30 local time, daily. - **Quiet hours:** None (app-level quiet hours supported but disabled by default). - **Analytics:** Local log + pluggable uploader (no-op by default). ## 3) Deliverables Produce the following artifacts: ### Android (Kotlin) - `:core`: models, storage, metrics, fallback manager. - `:data`: fetchers (WorkManager), mappers, cache policy. - `:notify`: scheduler (AlarmManager), receiver, channels. - App manifest entries & permissions. - Unit tests for fallback, scheduling, metrics. - README with battery optimization instructions (OEMs). ### iOS (Swift) - `NotificationKit`: models, storage, metrics, fallback manager. - BGTaskScheduler registration + handler. - UNUserNotificationCenter scheduling + categories + attachments. - Unit tests for fallback, scheduling, metrics. - README with Background App Refresh caveats + Focus/Summary notes. ## 4) Permissions & Required Setup ### Android Manifest ```xml ``` - Create a high-importance **NotificationChannel** `timesafari.daily`. - If **SCHEDULE_EXACT_ALARM** denied on Android 12+, auto-fallback to inexact. ### iOS App Setup (AppDelegate / SceneDelegate) - Register `BGTaskScheduler` with ID `com.timesafari.daily-fetch`. - Request alerts, sound, badge via `UNUserNotificationCenter`. - Create category `DAILY_UPDATE` with a primary `View` action. - Ensure Background Modes: **Background fetch**, **Remote notifications** (optional for future push). ## 5) Data Model (keep minimal, versioned) ### Canonical Schema (language-agnostic) ``` NotificationContent v1 - id: string (uuid) - title: string - body: string (plain text; may include simple emoji) - scheduledTime: epoch millis (client-local target) - mediaUrl: string? (for future; must be mirrored to local path before use) - fetchTime: epoch millis ``` ### Kotlin ```kotlin @Entity data class NotificationContent( @PrimaryKey val id: String, val title: String, val body: String, val scheduledTime: Long, val mediaUrl: String?, val fetchTime: Long ) ``` ### Swift ```swift struct NotificationContent: Codable { let id: String let title: String let body: String let scheduledTime: TimeInterval let mediaUrl: String? let fetchTime: TimeInterval } ``` ## 6) Storage Layers **Tier 1: Key-Value (quick)** — next payload, last fetch timestamp, user prefs. **Tier 2: DB (structured)** — history, media metadata, analytics events. **Tier 3: Files (large assets)** — images/audio; LRU cache & quotas. - Android: SharedPreferences/DataStore + Room + `context.cacheDir/notifications/` - iOS: UserDefaults + Core Data/SQLite + `Library/Caches/notifications/` ## 7) Background Execution ### Android — WorkManager - Periodic daily work with constraints (CONNECTED network). - Total time budget ~10m; use **timeouts** (e.g., fetch ≤30s, overall ≤8m). - On exception/timeout: **schedule from cache**; then `Result.success()` or `Result.retry()` per policy. ### iOS — BGTaskScheduler - `BGAppRefreshTask` with aggressive time budgeting (10–30s typical). - Submit next request immediately at start of handler. - Set `expirationHandler` first; cancel tasks cleanly; **fallback to cache** on failure. ## 8) Scheduling & Display ### Android - Prefer `AlarmManager.setExactAndAllowWhileIdle()` if permitted; else inexact. - Receiver builds notification using **BigTextStyle** for long bodies. - Limit actions to ≤3; default: `View` (foreground intent). ### iOS - `UNCalendarNotificationTrigger` repeating at preferred time. - Category `DAILY_UPDATE` with `View` action. - Media attachments **only if local**; otherwise skip gracefully. ## 9) Fallback Hierarchy (must implement) 1. **Foreground prefetch path** if app is open. 2. **Background fetch** with short network timeout. 3. **Last good cache** (annotate staleness: “as of X”). 4. **Emergency phrases** (rotate from static list). Provide helper: - `withStaleMarker(content) -> content'` appends age label (e.g., “from 3h ago”). ## 10) Failure Matrix & Responses | Scenario | Detect | Action | |---|---|---| | No network / timeout | Exceptions / status | Use last-good; schedule | | Invalid JSON | Parse error | Use emergency content; log | | Storage full | Write error | Evict old; retry minimal payload | | Notifications disabled | OS state | In-app education screen | | Background killed | Gaps in execution | Catch-up next foreground open | ## 11) Metrics (local first; uploader optional) Track per attempt: ``` NotificationMetrics v1 - scheduledTime, actualDeliveryTime? - contentAge (ms) - engagement: {TAPPED, DISMISSED, IGNORED}? - failureReason? - platformInfo (oem, os version, app state) ``` - Compute: **Fetch Success Rate**, **Delivery Rate**, **Engagement Rate**, **Stale Content Rate**. ## 12) Testing Requirements ### Matrix (minimum) - Android 12+ foreground/background/killed; with/without Battery Saver; Wi‑Fi/Mobile/Offline. - iOS 16+ background/Low Power/Focus/Scheduled Summary on & off. - Offline at trigger time (must still display). ### Unit Tests (examples) - Fallback when fetch fails (uses last-good and marks stale). - Exact vs inexact scheduling path selected correctly. - Metrics recorded for each stage. ## 13) UX Standards - One clear message; no clutter. - ≤2 actions; primary takes user into app. - Respect quiet hours if configured. - Provide onboarding: value explanation → permission request → time picker → test notification → tips for OEM battery settings (Android) or Focus/Summary (iOS). ## 14) Code Stubs (must generate & wire) ### Android — Worker (core pattern) ```kotlin class DailyContentWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) { override suspend fun doWork(): Result = try { withTimeout(8.minutes) { val content = fetchDailyContent(timeout = 30.seconds) saveToCache(content) scheduleNotification(content) } Result.success() } catch (e: TimeoutCancellationException) { scheduleFromCache(); Result.success() } catch (e: Exception) { scheduleFromCache(); Result.retry() } } ``` ### iOS — BG Refresh Handler (core pattern) ```swift func handleBackgroundRefresh(_ task: BGAppRefreshTask) { scheduleNextRefresh() var finished = false task.expirationHandler = { if !finished { cancelNetwork(); task.setTaskCompleted(success: false) } } fetchDailyContent(timeout: 15) { result in defer { finished = true; task.setTaskCompleted(success: result.isSuccess) } switch result { case .success(let content): quickSave(content); scheduleNotification(content) case .failure: scheduleFromCache() } } } ``` ## 15) Security & Privacy - Use HTTPS; pin if required. - Strip PII from payloads; keep content generic by default. - Store only what is necessary; apply cache quotas; purge on logout/uninstall. - Respect OS privacy settings (Focus, Scheduled Summary, Quiet Hours). ## 16) Troubleshooting Playbook (LLM should generate helpers) - Android: verify permission, channel, OEM battery settings; `adb shell dumpsys notification`. - iOS: check authorization, Background App Refresh, Low Power, Focus/Summary state. ## 17) Roadmap Flags (implement behind switches) - `FEATURE_MEDIA_ATTACHMENTS` (default off). - `FEATURE_PERSONALIZATION_ENGINE` (time/frequency, content types). - `FEATURE_PUSH_REALTIME` (server-driven for urgent alerts). ## 18) Definition of Done - Notifications deliver daily at user-selected time **without network**. - Graceful fallback chain proven by tests. - Metrics recorded locally; viewable log. - Clear onboarding and self-diagnostic screen. - Battery/OS constraints documented; user education available. ## 19) Quick Start (LLM execution order) 1. Scaffold modules (Android + iOS). 2. Implement models + storage + fallback content. 3. Implement schedulers (AlarmManager / UNCalendarNotificationTrigger). 4. Implement background fetchers (WorkManager / BGTaskScheduler). 5. Wire onboarding + test notification. 6. Add metrics logging. 7. Ship minimal, then iterate. --- ### Appendix A — Emergency Fallback Lines - "🌅 Good morning! Ready to make today amazing?" - "💪 Every small step forward counts. You've got this!" - "🎯 Focus on what you can control today." - "✨ Your potential is limitless. Keep growing!" - "🌟 Progress over perfection, always."