An iOS app inspired by The Economist's Big Mac Index — a crowdsourced tracker where users report the cost, quality, and context of McDonald's Big Mac meals around the world.
Website: https://bmi.bysam.fun
Mac setup checklist: docs/SETUP_CHECKLIST.md
App Store copy templates: docs/APP_STORE.md
- Sign in with Apple with unique username registration
- CloudKit public index — reports, photos, profiles, and friend links sync globally
- Live exchange rates — Frankfurter API (current + historical per report date)
- Today's dollars — US CPI-U inflation adjustment (live via FRED when API key configured)
- Friend linking — search by username, accept requests, push notifications for incoming requests
- Activity notifications — push + in-app inbox when friends post, tag you, or react to your reports
- Reactions — emoji reactions on public reports (❤️ 👍 🔥 😋 🍔)
- Public profiles — tap any author or friend to view their reports; share profile/report links
- Universal links —
https://bmi.bysam.fun/report/…and/u/usernameopen in the app - Account deletion — remove CloudKit data from Settings
- Meal reporting — price, rating, review, photos, location type, GPS, friend tags
- Feed, map, stats — normalized global comparisons
- Xcode 15+, iOS 17+
- Apple Developer account (Sign in with Apple, CloudKit, Push Notifications, Associated Domains)
- iCloud signed in on device/simulator
- Open
BMI/BMI.xcodeproj - Set your Development Team in Signing & Capabilities
- Enable capabilities: Sign in with Apple, iCloud (CloudKit), Push Notifications, Associated Domains (
applinks:bmi.bysam.fun) - CloudKit container:
iCloud.com.bigmacindex.bmi - Deploy CloudKit schema record types in CloudKit Dashboard:
PublicUser(includesnormalizedUsername)PublicReport(includesphotoCount,authorAppleUserIDqueryable)PublicReportPhoto(includesimageAssetCKAsset)FriendConnectionUserNotification(activity inbox records)ReportReaction
- Replace
TEAMIDindocs/.well-known/apple-app-site-associationwith your Apple Team ID - Enable GitHub Pages from
/docsand point DNSbmi.bysam.fun→svickars.github.io(see checklist) - Optional: add your FRED API key to
Info.plistasFRED_API_KEY - Build and run on a physical iPhone for best CloudKit/push results
Full step-by-step: docs/SETUP_CHECKLIST.md
| Layer | Technology |
|---|---|
| Local cache | SwiftData |
| Global sync | CloudKit Public Database |
| Photos | CKAsset on PublicReportPhoto records (JPEG compressed) |
| FX | Frankfurter API |
| Inflation | FRED CPI-U (live) + bundled fallback |
| Friend push | CloudKit subscriptions + APNs |
| Activity push | UserNotification records + per-user CloudKit subscriptions |
| Reactions | ReportReaction records synced via CloudKit public database |
| Deep links | Universal links via bmi.bysam.fun + in-app AppNavigationRouter |
| Auth | Sign in with Apple + unique username |
Reports upload metadata to PublicReport. Each photo becomes a PublicReportPhoto with a compressed JPEG CKAsset. Other users download photos during public sync.
After Sign in with Apple, users choose a username checked against CloudKit normalizedUsername before joining the public index.
CloudKit query subscriptions notify recipients when a pending friend request arrives. The app syncs connections and posts a local notification.
When a friend publishes a public report, tags you, or reacts to your report, the app writes a UserNotification record in CloudKit for each recipient. A per-user CloudKit subscription triggers a silent push; the app fetches the record, caches it in SwiftData, and shows a local alert (respecting Settings toggles). Profile → Notifications shows the full inbox with links to each report.
On any public report detail screen, signed-in users can react with emoji. Reactions sync globally via ReportReaction records; reacting to someone else's report notifies the author.
Tap a reporter on any card or report detail to open their public profile. Share buttons copy universal links:
- Report:
https://bmi.bysam.fun/report/{uuid} - Profile:
https://bmi.bysam.fun/u/{username}
- Historical FX converts local price → USD at report date (
usdAtReportDate) - CPI inflation adjusts USD to today's purchasing power
- Live FX converts to viewer's comparison currency
Profile → Currency & Sync Settings:
- Device locale vs custom comparison currency
- Today's dollars toggle
- CloudKit sync toggle + manual sync
- Activity notification toggles (friend posts, tags, reactions)
- Delete account
- Data source info (Frankfurter, FRED/bundled CPI)
Profile → Notifications:
- In-app inbox with unread badge
- Tap through to the related report
- Location, Photo Library, Sign in with Apple, iCloud/CloudKit, Push Notifications
- Privacy policy: https://bmi.bysam.fun/privacy.html
MIT