Snap a photo of your meal and let AI log the calories. No search bar, no typing out every ingredient. A personal iOS nutrition diary I vibecoded solo in about two weeks, and now use every day.
Most calorie-counting apps are built for the US market: an English food database and a search-then-select flow for every ingredient. For Vietnamese dishes, a bowl of bun bo or a plate of com tam with a dozen components, looking up each item just to add up the calories is enough friction that most people quit within a few days. Munchi (working title: "Ngoam Ngoam," the Vietnamese word for the sound of chewing) started from that exact personal need: a food diary where logging a meal is faster than eating it.
The bottom tab bar is a custom shape with a concave notch for a floating "+" button. Every meal starts with one tap, no matter which tab you're on.
Dashboard: calorie ring, macro cards, an intake/burn bar, and the day's meals and supplements.
30/90/180 day weight chart, steps and active calories synced from Apple Health, weekly intake vs. burn balance.
Calendar view with a total calorie count per day. Quick to check back a week or a month.
TDEE, calorie goal, AI model choice, supplement tracker, and light/dark appearance.
Photograph the meal. AI returns a list of dishes with estimated calories and macros. The user edits each card before saving. Instead of locking into one API, Munchi lets the user pick a provider in Profile: switch when one runs out of quota, when speed matters more, or when a free model will do.
| Provider | Typical model | Vision | Cost | Notes |
|---|---|---|---|---|
| Claude | claude-haiku-4-5 | Yes | Paid | The most accurate at recognizing Vietnamese dishes of the four |
| Gemini | gemini-2.0-flash | Yes | Free tier | The default. Fast, and enough for daily use |
| Groq | LLaMA vision | Yes | Free tier | The fastest inference. Used when a quick reply matters |
| OpenRouter | Llama 3.2 11B Vision, Qwen2.5 VL | Yes | Has free models | An aggregator that checks which models are actually available, right inside the app |
Photo to logged meal, start to finish
Munchi has its own brand palette (a burnt orange, #D64C30, different from this portfolio's teal) but follows the same semantic token structure: background, text, border, status. Each token has a light and dark pair, so there's no hex code hardcoded somewhere in the code.
SF Pro through the system font stack, no webfont to load. Text sizes follow a display/title/body/label/caption scale, with tabular numbers for every calorie count.
The bottom tab bar is drawn with a custom Shape that has a concave notch in the middle. The "+" button floats above that notch, with its own shadow for light and dark mode.
Munchi was built solo with Claude Code, but "vibecoded" here doesn't mean stopping at prompting features into existence. Once the core app worked, an automated code review pass scanned the whole codebase before the next round of changes went in.
8 SwiftData models (FoodEntry, UserProfile, WeightEntry, and more), a 3-step onboarding flow that calculates TDEE.
Dashboard, add meal, and history, built before AI was wired in, to make sure the manual flow was solid first.
4 providers for photo-to-dish recognition, barcode lookup through Open Food Facts, Apple Health sync.
Scanned 11 key files, sorted findings into critical/warning/info, and fixed whatever was safe to fix automatically.
No App Store, no CI. Just the real setup behind the build that runs on my phone every day.
xcodebuild against iPhone 16 Pro & 17 Pro simulators
Claude Code review pass before the next round of edits
Automatic signing, straight onto my own iPhone
The real production environment, right now
From onboarding to AI meal logging to activity tracking, plus a token-based design system of its own: Munchi covers a full personal product used daily, not a prototype that stops at the happy path.
The most important product decision wasn't which AI to use. It was removing the search bar. A photo replaces typing, scrolling, and picking items one by one, and that's the actual reason logging a meal stuck as a daily habit.
Letting Claude, Gemini, Groq, and OpenRouter be swapped isn't a novelty. It means a feature used every day never gets blocked by one API running out of quota, going slow, or costing too much.
The post-build review pass found exactly the mistakes that happen when coding alone and fast: repeated JSON decoding, retain cycles in async tasks, force-unwraps that could crash. Caught before anyone used it, not after.