# 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."