d10517b356
La 2.0 salio a la App Store el 2026-07-28 con los dos ultimos pasos del onboarding sin mostrarse. 2.0.1 lleva ese fix. El Info.plist del widget lleva la version hardcodeada y fastlane no la toca, asi que se alinea a mano (2.0.1 / 65) antes de construir. Documentado en CLAUDE.md para no volver a tropezar. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Ks8uUcMA9mjypVK7F2Pkt
3.7 KiB
3.7 KiB
MealMood — Project Context for Claude Code
App
- Name: MealMood: Family Meal Planner
- Bundle ID: com.alexandrevazquez.mealmood
- Platform: iOS/iPadOS (also runs as iOS app on Mac)
- Current version: 2.0.1 (dev, beta-bound; 2.0 shipped to the App Store 2026-07-28)
- Main branch:
1.0.1(production), feature branches named after versions
Branch ↔ version convention (IMPORTANT)
The active dev branch is named after the current MARKETING_VERSION, not the one it was created with. Whenever the iOS app version changes, rename the branch to match:
# after bumping MARKETING_VERSION in the Xcode project to e.g. 1.1.6
git branch -m <old-version> 1.1.6 # e.g. git branch -m 1.1.5 1.1.6
Right now: MARKETING_VERSION = 2.0.1 → active branch is 2.0.1. Keep them in sync. (The build number bump within the same version does NOT rename the branch — only a version change does.)
The widget version is not automated. MealMoodWidget/Info.plist hardcodes CFBundleShortVersionString and CFBundleVersion; fastlane's increment_build_number only touches the app target. Update the widget by hand to match the app before running fastlane beta, or App Store Connect rejects the upload for a version mismatch:
plutil -replace CFBundleShortVersionString -string "<version>" MealMoodWidget/Info.plist
plutil -replace CFBundleVersion -string "<build>" MealMoodWidget/Info.plist
Credentials — all managed via pass (GPG-encrypted, syncs to Gitea)
Never hardcode credentials. Always read from pass:
# Apple
pass show apple/mealmood/apple-id # alexandre.vazquez@gmail.com
pass show apple/mealmood/developer-team-id # 2825Q76T7H
pass show apple/mealmood/appstore-connect-team-id # 128443966
pass show apple/mealmood/app-store-app-id # 6759255553
pass show apple/mealmood/app-specific-password-fastlane # for fastlane uploads
# Firebase
pass show firebase/mealmood/api-key
pass show firebase/mealmood/project-id
pass show firebase/mealmood/google-app-id
# AdMob
pass show admob/mealmood/app-id
pass show admob/mealmood/banner-home-unit-id
TestFlight upload
export FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD=$(pass show apple/mealmood/app-specific-password-fastlane)
fastlane beta
Stack
- SwiftUI + SwiftData (iOS 17+)
- Firebase Analytics (
AnalyticsService.swift) - Google AdMob (banner, free tier only, hidden on Mac)
- StoreKit 2 (subscription
com.mealmood.premium.monthly) - iCloud KV sync (
ICloudSyncService.swift) — does NOT syncisPremium - Widget extension (
MealMoodWidget/) — requires App Groupgroup.com.alexandrevazquez.mealmood - Fastlane for CI/CD
Premium logic
PremiumSyncServiceis the source of truth for premium state transitionsisPremiumis determined only by StoreKit — never by iCloud syncTransaction.updateslistener inContentViewcatches purchases in real-time- Tests:
MealMoodTests/PremiumSyncServiceTests.swift
Key files
| File | Purpose |
|---|---|
MealMood/ContentView.swift |
App root, premium sync, Transaction.updates listener |
MealMood/Services/PremiumSyncService.swift |
Premium state machine (testable) |
MealMood/Services/StoreManager.swift |
StoreKit 2 purchase/restore |
MealMood/Services/ICloudSyncService.swift |
Cross-device sync (dishes, tags, plans — NOT isPremium) |
MealMood/Views/Home/WeekPlanShareView.swift |
Export styles (default, school, vertical A4) |
MealMoodWidget/MealMoodWidget.swift |
Home screen widget |
fastlane/Fastfile |
beta and release lanes |
fastlane/metadata/ |
App Store metadata in 6 languages |