summaryrefslogtreecommitdiffstats
path: root/docs/superpowers
diff options
context:
space:
mode:
authorivar <i@oiee.no>2026-03-23 15:18:33 +0100
committerivar <i@oiee.no>2026-03-23 15:18:33 +0100
commit3a171b163735bac0d497088b8c01b5f94ca5c6e9 (patch)
tree40b9f4a8c8820ca3baa9148e0eaedd28b198f916 /docs/superpowers
parentbfd75822b3e9882ff4e85d13a0e3658b60e6329d (diff)
downloadsolverv-3a171b163735bac0d497088b8c01b5f94ca5c6e9.tar.xz
solverv-3a171b163735bac0d497088b8c01b5f94ca5c6e9.zip
Add solstice widget design spec
Diffstat (limited to 'docs/superpowers')
-rw-r--r--docs/superpowers/specs/2026-03-23-solstice-widget-design.md223
1 files changed, 223 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-03-23-solstice-widget-design.md b/docs/superpowers/specs/2026-03-23-solstice-widget-design.md
new file mode 100644
index 0000000..f3b889c
--- /dev/null
+++ b/docs/superpowers/specs/2026-03-23-solstice-widget-design.md
@@ -0,0 +1,223 @@
+# Solstice Countdown Widget & App Design
+
+**Date:** 2026-03-23
+**Project:** Solverv (Solstice Countdown)
+**Status:** Design Approved
+
+---
+
+## Overview
+
+Build an iOS app that displays a countdown to the next solstice or equinox, with season-specific imagery and detailed information. The app includes:
+- **Widget Extension:** Compact countdown widget in small, medium, and large sizes
+- **Main App:** Info screen showing expanded details including sunrise/sunset times and upcoming events
+
+---
+
+## Requirements
+
+### Functional Requirements
+1. Track all four annual solstices/equinoxes (Spring, Summer, Autumn, Winter)
+2. Display countdown to next event in **days only**
+3. Show season-specific images that change based on upcoming event
+4. Calculate and display sunrise/sunset times for user's current location
+5. Show expanded event details in main app (exact times, season descriptions, upcoming event previews)
+6. Support multiple widget sizes (small, medium, large)
+
+### Non-Functional Requirements
+- All calculations happen locally (no external APIs)
+- Works offline after initial setup
+- Respects location privacy with explicit permission
+- Single location permission prompt (shared via AppGroup)
+- Data synced between app and widget via AppGroup container
+
+---
+
+## Architecture
+
+### Data Models
+
+**SolsticeEvent**
+```
+- name: String (e.g., "Summer Solstice", "Spring Equinox")
+- date: Date (UTC)
+- season: Season (enum: spring, summer, autumn, winter)
+- seasonDescription: String (brief description of the season)
+```
+
+**SolsticeData**
+```
+- events: [SolsticeEvent] (hardcoded data, 2025-2030)
+- nextEvent() -> SolsticeEvent (returns next upcoming event)
+- allUpcoming(count: Int) -> [SolsticeEvent] (returns next N events)
+- daysUntil(_ event: SolsticeEvent) -> Int
+- progressToEvent(_ event: SolsticeEvent) -> (elapsed: Int, total: Int)
+```
+
+**SunTimes**
+```
+- latitude: Double
+- longitude: Double
+- date: Date
+- sunrise() -> Date
+- sunset() -> Date
+```
+
+### Data Sharing
+
+- **AppGroup Container:** Store user location (lat/lon) and cached sunrise/sunset times
+- **Widget Timeline:** Update once daily using WidgetKit's `.atEnd` policy
+- Both app and widget read from the same AppGroup container for consistency
+
+---
+
+## Widget Specification
+
+### Small Widget (169×169)
+- **Layout:** Vertical stack
+ - Seasonal image (fills most of space)
+ - Event name (small caption)
+ - Countdown in days (large, bold text)
+- **Refresh:** Daily
+- **Purpose:** Quick glance at how many days remain
+
+### Medium Widget (364×169)
+- **Layout:** Horizontal split
+ - Left: Seasonal image (square)
+ - Right: Vertical stack with event name, countdown (large), progress bar
+- **Refresh:** Daily
+- **Purpose:** Balance of visual and numeric information
+
+### Large Widget (364×364)
+- **Layout:** Vertical stack
+ - Top half: Seasonal image
+ - Bottom half: Event name, countdown, progress bar, preview of next 3 upcoming events (mini list)
+- **Refresh:** Daily
+- **Purpose:** Comprehensive view with upcoming events preview
+
+### Images
+- One image per season (spring, summer, autumn, winter)
+- Sourced from Assets.xcassets
+- Same image shown for all events in that season
+
+---
+
+## Main App Info Screen
+
+### Top Section
+- Seasonal image (landscape orientation friendly)
+- Next event name (large)
+- Countdown in days (very large, prominent)
+- Progress bar (days elapsed / total days)
+
+### Middle Section
+- **Today's Sun Times**
+ - Sunrise time
+ - Sunset time
+ - Calculated from device location
+- **Season Info**
+ - Season name
+ - Brief description (e.g., "Spring Equinox — Day and night are approximately equal length")
+
+### Bottom Section
+- **Upcoming Events List** (scrollable)
+ - Shows next 8-12 events
+ - Each row: Event name | Date/Time | Days remaining | Season color indicator
+ - Searchable/filterable by season (optional enhancement)
+
+### Navigation
+- Tab bar or simple navigation to this screen
+- Refresh button to manually update sunrise/sunset (in case location changed)
+
+---
+
+## Time Zone & Location Handling
+
+### Location
+- Request permission on first app launch
+- Store latitude/longitude in AppGroup container
+- Fall back to Greenwich/UTC (0°, 0°) if permission denied
+- User can manually update location in app settings
+
+### Time Zones
+- All solstice times stored in UTC (as they are now)
+- Convert to user's local timezone for display
+- Sunrise/sunset calculated for user's timezone and location
+
+### Sunrise/Sunset Algorithm
+- Use NOAA solar position algorithm (lightweight, no external API)
+- Built into iOS or implement a simplified version
+- Cache results in AppGroup container to avoid recalculation
+
+---
+
+## Error Handling & Edge Cases
+
+### Location Permission
+- App requests permission on first launch
+- If denied, use default location (Greenwich) and notify user
+- User can grant permission later in system Settings
+
+### Time Zone Edge Cases
+- Solstice at midnight: Display correctly in both UTC and local time
+- User crosses timezone: Times update automatically on app launch
+- Widget timezone: Uses device timezone (set by system)
+
+### Data Integrity
+- Solstice dates are hardcoded and immutable
+- Sunrise/sunset cached but recalculated daily
+- Widget syncs with app via AppGroup on launch
+
+---
+
+## Testing Strategy
+
+### Widget Testing
+- Preview all three widget sizes with mock solstice data
+- Verify countdown updates correctly across timezone boundaries
+- Test image display in different iOS versions (iOS 17 fallback)
+
+### App Testing
+- Verify sunrise/sunset calculations against known values
+- Test location permission flows (allowed, denied, not yet asked)
+- Test data sync between app and widget
+- Verify time zone conversions for various user locations
+
+### Integration Testing
+- Widget refreshes daily and displays current countdown
+- App and widget show consistent "next event" data
+- Location changes update sunrise/sunset in real time
+
+---
+
+## Implementation Notes
+
+### Existing Code
+- `SolvervDef` already contains solstice dates (2025-2030)
+- Widget structure (`Solsnu_Widget.swift`) is scaffolded
+- Main app has basic SwiftUI structure ready for info screen
+
+### New Components to Build
+- `SunTimes` calculation (sunrise/sunset)
+- `SolsticeEvent` model
+- Widget layout variants (small, medium, large)
+- Info screen UI
+- AppGroup data sharing
+
+### Dependencies
+- None (all calculations are built-in or custom)
+- WidgetKit (already available)
+- SwiftUI (already used)
+
+---
+
+## Success Criteria
+
+✅ Widget displays countdown in days
+✅ Seasonal image changes based on next event
+✅ All four solstices/equinoxes tracked
+✅ Sunrise/sunset times calculated from location
+✅ Info screen shows all requested details
+✅ App and widget data stay in sync
+✅ Works offline after initial setup
+✅ All three widget sizes render correctly