A food diary you look at instead of read. Photograph a meal, and the food alone is cut out of the picture and becomes a sticker you arrange on a board of your own.
Everything stays on the device: no account, no server, no analytics, no ads.
- 홈: https://cobyapp.github.io/food-diary/
- 개인정보 처리방침: https://cobyapp.github.io/food-diary/privacy.html
- 이용약관: https://cobyapp.github.io/food-diary/terms.html
- 지원: https://cobyapp.github.io/food-diary/support.html
The store name differs per language because another developer holds "Yumkie": 얌키 (ko) · Yamki Food Sticker Diary (en) · ヤムキー ごはんステッカー日記 (ja) · 雅米吉 美食贴纸日记 (zh-Hans).
- Cuts the food out of a photo on device with Vision. Several dishes in one shot come out as separate stickers, and each dish becomes its own entry.
- A board you arrange yourself — the whole screen is the canvas. Drag a sticker anywhere; drop it on the tray to take it off the board (which is not the same as deleting it).
- Your own tags, and a star rating, shown everywhere the dish appears.
- A drawer holding every sticker ever saved. Deleting from the drawer is the only delete that is permanent.
- A map of where each meal was eaten, from the photo's own EXIF.
- A recap card that turns the board into one shareable image, with a closing line written by Apple Intelligence on device where the device supports it.
- A food world cup to decide what to eat, and a Game Center version where everyone votes within five seconds.
- Streaks, badges, and a home screen widget.
Tuist generates the project; the app is split into three static frameworks so the layers cannot import each other backwards.
| Target | What lives there |
|---|---|
Models |
SwiftData entities and the Sendable snapshots that cross actors |
ClientKit |
dependency clients — persistence, cutouts, place search, Game Center, captions |
FeatureKit |
TCA reducers and SwiftUI views, one folder per feature |
FoodDiary |
the app target: assets, Localizable.strings, entitlements |
FoodDiaryWidget |
the widget extension |
State is TCA;
storage is SwiftData behind a @ModelActor, so the UI only ever sees value-type
snapshots.
Four languages ship: Korean (base), English, Japanese, Simplified Chinese. Localizable keys are the Korean source text.
brew install tuist
bash Scripts/setup.sh # tuist install && tuist generate
open FoodDiary.xcworkspaceConfigurations/Secrets.xcconfig is gitignored — copy
Configurations/Secrets.example.xcconfig to it. The app builds without any
values filled in.
xcodebuild test -workspace FoodDiary.xcworkspace -scheme FoodDiary \
-destination "id=<simulator udid>" -skipMacroValidationCutouts come from Vision, which does not run in the Simulator — test the capture flow on a device.
The screenshots are rendered with ImageRenderer, not captured from a
simulator, so the pixel size is exact and the boards are full of real food.
swift Scripts/make-cutouts.swift ~/path/to/food/photos # → fastlane/cutout-sources/
bash Scripts/screenshots.sh # → fastlane/screenshots/<locale>/Ten posters per language at 1320 × 2868 (iPhone 6.9"), RGB with no alpha channel — the store rejects anything else. Both folders are gitignored: they are built from personal photos.
Build → TestFlight runs on GitHub Actions (.github/workflows/release.yml,
workflow_dispatch or a v* tag). Signing is cloud-managed through an App Store
Connect API key, so no certificates are stored in the repo.
gh workflow run release.yml --ref mainMetadata and screenshots go up separately, so text changes need no build:
LANG=en_US.UTF-8 \
APPSTORE_KEY_ID=<key id> \
APPSTORE_ISSUER_ID=<issuer id> \
AUTH_KEY_PATH=~/.appstoreconnect/private_keys/AuthKey_<key id>.p8 \
BUNDLE_PATH=vendor/bundle bundle exec fastlane metadataStore text lives in fastlane/metadata/<locale>/ and is version-controlled;
Gemfile.lock deliberately is not — the macOS system bundler writes a version
that breaks Ruby 3.3 on CI.