# 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.swift` for 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:** 1. **Bundled JSON** (`SportsTime/Resources/`) - Bootstrap data for first launch 2. **SwiftData** (local) - Runtime source of truth, offline-capable 3. **CloudKit** (remote) - Public database for schedule updates **Key Data Files:** - `games_canonical.json` - Pre-bundled game schedules - `teams_canonical.json` - Team definitions - `stadiums_canonical.json` - Stadium definitions - `league_structure.json` - League/conference/division hierarchy - `team_aliases.json` - Historical team name mappings - `stadium_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*