# CloudKit Setup Guide for SportsTime ## 1. Configure Container in Apple Developer Portal 1. Go to [Apple Developer Portal](https://developer.apple.com/account) 2. Navigate to **Certificates, Identifiers & Profiles** > **Identifiers** 3. Select your App ID or create one for `com.sportstime.app` 4. Enable **iCloud** capability 5. Click **Configure** and create container: `iCloud.com.sportstime.app` ## 2. Configure in Xcode 1. Open `SportsTime.xcodeproj` in Xcode 2. Select the SportsTime target 3. Go to **Signing & Capabilities** 4. Ensure **iCloud** is added (should already be there) 5. Check **CloudKit** is selected 6. Select container `iCloud.com.sportstime.app` ## 3. Create Record Types in CloudKit Dashboard Go to [CloudKit Dashboard](https://icloud.developer.apple.com/dashboard) ### Record Type: `Stadium` | Field | Type | Notes | |-------|------|-------| | `stadiumId` | String | Unique identifier | | `name` | String | Stadium name | | `city` | String | City | | `state` | String | State/Province | | `location` | Location | CLLocation (lat/lng) | | `capacity` | Int(64) | Seating capacity | | `sport` | String | NBA, MLB, NHL | | `teamAbbrevs` | String (List) | Team abbreviations | | `source` | String | Data source | | `yearOpened` | Int(64) | Optional | **Indexes**: - `sport` (Queryable, Sortable) - `location` (Queryable) - for radius searches - `teamAbbrevs` (Queryable) ### Record Type: `Team` | Field | Type | Notes | |-------|------|-------| | `teamId` | String | Unique identifier | | `name` | String | Full team name | | `abbreviation` | String | 3-letter code | | `sport` | String | NBA, MLB, NHL | | `city` | String | City | **Indexes**: - `sport` (Queryable, Sortable) - `abbreviation` (Queryable) ### Record Type: `Game` | Field | Type | Notes | |-------|------|-------| | `gameId` | String | Unique identifier | | `sport` | String | NBA, MLB, NHL | | `season` | String | e.g., "2024-25" | | `dateTime` | Date/Time | Game date and time | | `homeTeamRef` | Reference | Reference to Team | | `awayTeamRef` | Reference | Reference to Team | | `venueRef` | Reference | Reference to Stadium | | `isPlayoff` | Int(64) | 0 or 1 | | `broadcastInfo` | String | TV channel | | `source` | String | Data source | **Indexes**: - `sport` (Queryable, Sortable) - `dateTime` (Queryable, Sortable) - `homeTeamRef` (Queryable) - `awayTeamRef` (Queryable) - `season` (Queryable) ## 4. Import Data After creating record types: ```bash # 1. First scrape the data cd Scripts python3 scrape_schedules.py --sport all --season 2025 --output ./data # 2. Run the import script (requires running from Xcode or with proper entitlements) # The Swift script cannot run standalone - use the app or create a macOS command-line tool ``` ### Alternative: Import via App Add this to your app for first-run data import: ```swift // In AppDelegate or App init Task { let importer = CloudKitImporter() // Load JSON from bundle or downloaded file if let stadiumsURL = Bundle.main.url(forResource: "stadiums", withExtension: "json"), let gamesURL = Bundle.main.url(forResource: "games", withExtension: "json") { // Import stadiums first let stadiumsData = try Data(contentsOf: stadiumsURL) let stadiums = try JSONDecoder().decode([ScrapedStadium].self, from: stadiumsData) let count = try await importer.importStadiums(from: stadiums) print("Imported \(count) stadiums") } } ``` ## 5. Security Roles (CloudKit Dashboard) For the **Public Database**: | Role | Stadium | Team | Game | |------|---------|------|------| | World | Read | Read | Read | | Authenticated | Read | Read | Read | | Creator | Read/Write | Read/Write | Read/Write | Users should only read from public database. Write access is for your admin imports. ## 6. Testing 1. Build and run the app on simulator or device 2. Check CloudKit Dashboard > **Data** to see imported records 3. Use **Logs** tab to debug any issues ## Troubleshooting ### "Container not found" - Ensure container is created in Developer Portal - Check entitlements file has correct container ID - Clean build and re-run ### "Permission denied" - Check Security Roles in CloudKit Dashboard - Ensure app is signed with correct provisioning profile ### "Record type not found" - Create record types in Development environment first - Deploy schema to Production when ready