4.4 KiB
4.4 KiB
Technology Stack
Analysis Date: 2026-01-18
Languages
Primary:
- Swift 5.0 - iOS app (
SportsTime/) - Python 3.11+ - Data scraping and CloudKit uploading (
Scripts/sportstime_parser/)
Secondary:
- JSON - Data interchange format, bundled bootstrap data, configuration
Runtime
iOS Environment:
- iOS 26+ (iOS 26.2 targeted per Xcode 26.2)
- Swift 6 concurrency model enabled (
SWIFT_APPROACHABLE_CONCURRENCY = YES,SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor) - Deployment targets: iPhone and iPad (
TARGETED_DEVICE_FAMILY = "1,2")
Python Environment:
- Python 3.11, 3.12, or 3.13
- No lockfile (uses requirements.txt + pyproject.toml)
Frameworks
Core iOS Frameworks:
- SwiftUI - UI framework (entire app)
- SwiftData - Local persistence (
Core/Models/Local/) - CloudKit - Remote data sync (
Core/Services/CloudKitService.swift) - StoreKit 2 - In-app purchases (
Core/Store/StoreManager.swift) - MapKit - Geocoding, routing, map snapshots, EV chargers
- CoreLocation - Location services
- PDFKit - PDF generation (
Export/PDFGenerator.swift) - BackgroundTasks - Background sync scheduling
- Network - Network path monitoring (
NWPathMonitor) - Photos/PhotosUI - Photo library access for visit imports
- CryptoKit - Hash generation for canonical data
Testing:
- XCTest - Unit and UI tests (
SportsTimeTests/,SportsTimeUITests/) - pytest 8.0+ - Python tests (
Scripts/sportstime_parser/tests/)
Build/Dev:
- Xcode 26.2 - Build system
- Swift Package Manager - Dependency management (single package)
Key Dependencies
iOS - Swift Package Manager:
- SwiftSoup (HTML parsing) - Used in
HistoricalGameScraper.swiftfor Sports-Reference scraping
Python - pip:
| Package | Version | Purpose |
|---|---|---|
| requests | 2.31.0+ | HTTP client for API calls |
| beautifulsoup4 | 4.12.0+ | HTML parsing |
| lxml | 5.0.0+ | XML/HTML parser backend |
| rapidfuzz | 3.5.0+ | Fuzzy string matching for team names |
| python-dateutil | 2.8.0+ | Date parsing |
| pytz | 2024.1+ | Timezone handling |
| rich | 13.7.0+ | CLI output formatting |
| pyjwt | 2.8.0+ | JWT token generation for CloudKit auth |
| cryptography | 42.0.0+ | ECDSA signing for CloudKit requests |
Dev Dependencies (Python):
- pytest 8.0+ - Test runner
- pytest-cov 4.1+ - Coverage reporting
- responses 0.25+ - HTTP mocking
Configuration
Environment Variables:
- CloudKit Web Services requires ECDSA private key for server-to-server auth
- iOS app uses iCloud container identifier:
iCloud.com.sportstime.app
Build Settings:
| Setting | Value | Purpose |
|---|---|---|
SWIFT_VERSION |
5.0 | Swift language version |
SWIFT_APPROACHABLE_CONCURRENCY |
YES | Modern concurrency |
SWIFT_DEFAULT_ACTOR_ISOLATION |
MainActor | Default isolation |
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY |
YES | Swift 6 prep |
Info.plist:
- Background modes:
remote-notification,fetch,processing - Background task IDs:
com.sportstime.app.refresh,com.sportstime.app.db-cleanup - Photo library usage description for visit imports
Entitlements:
- CloudKit:
iCloud.com.sportstime.app - Push notifications:
aps-environment(development)
Platform Requirements
Development:
- macOS with Xcode 26.2
- Python 3.11+ for data scraping
- iCloud account for CloudKit testing
Production:
- iOS 26+ (uses iOS 26 APIs, deprecated CLGeocoder annotations)
- iCloud account for data sync (optional, works offline)
- Network for CloudKit sync (offline-first architecture)
Data Architecture
Three-Tier Storage:
- Bundled JSON (
SportsTime/Resources/) - Bootstrap data for first launch - SwiftData (local) - Runtime source of truth, offline-capable
- CloudKit (remote) - Public database for schedule updates
Key Data Files:
games_canonical.json- Pre-bundled game schedulesteams_canonical.json- Team definitionsstadiums_canonical.json- Stadium definitionsleague_structure.json- League/conference/division hierarchyteam_aliases.json- Historical team name mappingsstadium_aliases.json- Historical stadium name mappings
SwiftData Models:
- Canonical:
CanonicalStadium,CanonicalTeam,CanonicalGame,CanonicalSport - User:
SavedTrip,StadiumVisit,UserPreferences,Achievement - Sync:
SyncState,LeagueStructureModel,TeamAlias,StadiumAlias
Stack analysis: 2026-01-18