1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
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
|