# Calorie Counter App — Plan & Requirements **Version**: 1.1 **Date**: 2026-05-19 **Status**: Phase 4 in progress --- ## 1. Product Vision > "The easiest way to track calories with minimal effort and acceptable accuracy, using AI + smart defaults." **Core principle**: Consistent estimation beats absolute precision. Users should trust the app enough to use it daily — not abandon it because it demands too much. **KPI**: Log a meal in under 10 seconds. --- ## 2. Target Users **Primary**: Busy professionals who eat a mix of home-cooked, restaurant, and packaged food. They want low friction, not lab-grade accuracy. --- ## 3. MVP Feature Scope ### IN scope | Feature | Description | |---|---| | Manual food search | Search food DB, select portion, add to day | | Barcode scan | Scan product → auto-fill nutrition | | Photo logging (AI assist) | Snap photo → AI suggests items + portions → user confirms/edits | | Daily calorie tracking | Consumed vs. target, remaining calories | | Macro tracking | Protein / carbs / fat (optional display) | | User profile | Age, weight, height, goal → auto-calculated daily target (BMR) | | History view | Calorie totals per day | | Repeat last meal | One-tap shortcut on home screen | | AI correction loop | User edits AI result → stored to improve future suggestions | ### OUT of scope (MVP) - Social features - Meal plans - Wearable integrations - Deep health analytics - Custom ML model training --- ## 4. Differentiation Strategy Three features that separate this from MyFitnessPal etc: 1. **Confidence-aware calories** — show `500 kcal ± 80 kcal (confidence 85%)` instead of a false-precision single number 2. **Personal food memory** — app learns your typical portions, pre-fills next time 3. **AI correction loop** — every manual correction improves future suggestions, building a personalised model layer over time --- ## 5. Technical Architecture ### Stack decision | Layer | Technology | |---|---| | Mobile | React Native | | Backend | Spring Boot (Java)| | Database | PostgreSQL | | Food DB | Open Food Facts API (free, open) | | AI service | OpenAI Vision API (MVP) → custom fine-tuned model (later) | | Auth | JWT-based auth | ### Architecture diagram ``` Mobile App (React Native) │ REST API │ Backend (Spring Boot / FastAPI) │ ┌────────────────────────────────┐ │ Food DB (OpenFoodFacts cache) │ │ AI Service (Vision API) │ │ User Data (Postgres) │ └────────────────────────────────┘ ``` **Key design decision**: Cache food DB locally for performance. Normalize all food entries to a common schema regardless of source (OpenFoodFacts / barcode / AI / manual). --- ## 6. Data Model ### User ```json { "id": "uuid", "email": "string", "createdAt": "timestamp", "profile": { "age": 30, "weightKg": 80, "heightCm": 180, "goal": "lose | maintain | gain", "dailyCaloriesTarget": 2200 } } ``` ### FoodItem (normalised DB) ```json { "id": "uuid", "name": "Chicken breast", "source": "openfoodfacts | custom | ai", "caloriesPer100g": 165, "macros": { "proteinG": 31, "fatG": 3.6, "carbsG": 0 } } ``` ### MealEntry ```json { "id": "uuid", "userId": "uuid", "date": "2026-05-16", "mealType": "breakfast | lunch | dinner | snack", "items": [ { "foodItemId": "uuid", "quantityGrams": 200, "calories": 330 } ], "source": "manual | barcode | photo", "confidence": 0.82 } ``` ### PhotoAnalysis (AI audit trail) ```json { "id": "uuid", "userId": "uuid", "imageUrl": "string", "detectedItems": [ { "name": "rice", "estimatedGrams": 150, "confidence": 0.76 } ], "userCorrections": [ { "name": "rice", "correctedGrams": 180 } ] } ``` ### UserFoodMemory (personalisation layer) ```json { "userId": "uuid", "foodName": "coffee with milk", "avgPortionGrams": 250, "lastUsed": "timestamp" } ``` --- ## 7. API Design ### Auth ``` POST /auth/register POST /auth/login ``` ### User ``` GET /user/profile PUT /user/profile ``` ### Food ``` GET /foods?query=chicken GET /foods/barcode/{code} ``` ### Meals ``` POST /meals GET /meals/daily?date=YYYY-MM-DD GET /meals/{id} PUT /meals/{id} DELETE /meals/{id} ``` `GET /meals/daily` response: ```json { "totalCalories": 1800, "target": 2200, "remaining": 400, "meals": [...] } ``` ### AI ``` POST /ai/analyze-meal ← multipart image upload POST /ai/correction ← submit user correction ``` `POST /ai/analyze-meal` response: ```json { "analysisId": "uuid", "suggestions": [ { "name": "pasta", "grams": 250, "confidence": 0.78 } ] } ``` --- ## 8. UI / UX Requirements ### Screen map ``` Bottom Nav: [ Home ] [ History ] [ Profile ] FAB: [ + Add Meal ] (accessible from Home) ``` ### Screens | Screen | Key elements | |---|---| | Home | Calorie progress card, meal list (Breakfast/Lunch/Dinner), repeat shortcut, FAB | | Add Meal (bottom sheet) | Photo / Search / Barcode options | | Camera | Full-screen preview, capture button | | AI Result | Detected items with portions + confidence %, Edit and Confirm CTAs | | Edit Meal | Per-item sliders (0–500g), real-time calorie total, Save button | | Manual Search | Search input, results list with kcal/100g, portion selector | | Daily Details | Calorie total, macro breakdown, meal list | | History | Per-day calorie totals (scrollable list) | | Profile | Weight / height / goal / daily target, Edit button | ### Critical UX rules (non-negotiable) 1. **Always require user confirmation** before saving AI-detected meals — never auto-save 2. **1-tap access** to Add Meal from Home screen 3. **Sliders over number inputs** for portion adjustment — faster, fewer errors 4. **Calories update in real-time** while adjusting portions 5. **Confidence score visible** on AI suggestions (supports honest accuracy framing) ### Accessibility - All interactive elements keyboard/touch accessible - Minimum touch target 48×48px - Contrast ratio ≥ 4.5:1 (WCAG 2.2 AA) - `alt` text on all food images / icons --- ## 9. Design System (summary) ### Colours | Token | Value | |---|---| | Primary/Green | `#22C55E` | | Primary/Dark | `#16A34A` | | Error/Red | `#EF4444` | | Warning/Yellow | `#F59E0B` | | Gray/900 (text) | `#0F172A` | | Background | `#FFFFFF` | | Background/Muted | `#F8FAFC` | ### Typography (Inter / SF Pro) - Heading/Large: 24px SemiBold - Body/Large: 16px Regular - Caption: 12px Regular - Number/Kcal: 28px Bold ### Spacing: 8px grid (4 / 8 / 16 / 24 / 32 / 48px) ### Key components `Button`, `MealItemRow`, `FoodRow`, `CalorieCard`, `AISuggestionCard`, `PortionSlider`, `ProgressBar`, `FAB` --- ## 10. Phased Delivery Plan ### Phase 1 — Core MVP ✅ Implemented - [x] User auth (register / login) - [x] User profile + BMR-based calorie target - [x] Food search (OpenFoodFacts API) - [x] Manual meal logging - [x] Barcode scan backend endpoint - [x] Daily calorie dashboard - [x] Meal history ### Phase 2 — AI Layer ✅ Implemented - [x] Photo capture screen - [x] OpenAI Vision API integration (`/ai/analyze-meal`) - [x] AI result confirmation screen - [x] Per-item portion sliders (Edit Meal screen) - [x] AI correction storage ### Phase 3 — Intelligence + Polish ✅ Implemented - [x] Confidence-aware display (kcal ± range) - [x] UserFoodMemory — personalised portion defaults - [x] "Repeat last meal" shortcut - [x] Macro tracking display (protein/carbs/fat) - [x] Fine-tune AI suggestions based on user corrections ### Phase 4 — Enhanced Features (v1.1) - [x] REQ-MOB-010: Barcode scanner mobile screen (HIGH — fix UI gap) - [x] REQ-VIZ-001: Weekly calorie bar chart on History screen (HIGH) - [x] REQ-VIZ-002: Streak tracker — consecutive days logged (HIGH) - [x] REQ-UX-001: Quick-add calories without food search (MEDIUM) - [x] REQ-UX-002: Food favourites — star items in search (MEDIUM) - [x] REQ-UX-003: Goal achievement in-app notification (MEDIUM) - [x] REQ-EXP-001: Data export as CSV (LOW) - [x] REQ-WTR-001: Water intake tracking (LOW) - [x] REQ-UX-004: Daily logging reminder banner (LOW) --- ## 11. Phase 4 Requirement Details ### REQ-MOB-010 — Barcode Scanner Screen (HIGH) **Gap**: Backend and API client for barcode lookup exist; mobile UI omits the scan option. - New `BarcodeScreen.tsx` using `react-native-camera` (already installed) — full-screen camera with barcode overlay - Add "Scan Barcode" as third option in HomeScreen bottom sheet - On successful scan → call `GET /foods/barcode/{code}` → navigate to portion selector → log meal ### REQ-VIZ-001 — Weekly Calorie Chart (HIGH) - New `WeeklyCalorieChart` component: proportional-height bar chart for last 7 days (pure RN `View`, no extra deps) - Rendered at top of History screen above the daily list - Each bar shows day-of-week label + kcal value; target line drawn at user's daily goal - Color-coded: green = at/under goal, amber = over goal ### REQ-VIZ-002 — Streak Tracker (HIGH) - Backend: `GET /meals/streak` → returns `{ currentStreak: N, longestStreak: N }` - Counts consecutive calendar days (ending today) where at least one meal was logged - Mobile: streak badge on Home screen below CalorieCard ### REQ-UX-001 — Quick-Add Calories (MEDIUM) - New `QuickAddScreen.tsx` — number-pad input for kcal + meal type picker - Backend: `POST /meals/quick-add` → `{ date, mealType, calories, label? }` → creates system food "Quick Add" entry - Accessible from Home bottom sheet as "⚡ Quick Add" ### REQ-UX-002 — Food Favourites (MEDIUM) - Add `favourite` boolean column to `user_food_memories` (Flyway V3) - Backend: `POST /foods/{id}/favourite` (toggle) → upserts UserFoodMemory with `favourite=true/false` - Mobile: star icon on each `FoodRow`; Favourites section at top of Search screen ### REQ-UX-003 — Goal Achievement Notification (MEDIUM) - In-app only (no native push required) - When `remaining ≤ 0` after a meal is logged, show an in-app success banner on HomeScreen - Banner auto-dismisses after 4 seconds ### REQ-EXP-001 — Data Export CSV (LOW) - Backend: `GET /export/meals?from=YYYY-MM-DD&to=YYYY-MM-DD` → `Content-Type: text/csv` - Columns: `date, mealType, foodName, grams, calories, source` - Mobile: "Export Data" button in Profile screen → uses React Native `Share` API ### REQ-WTR-001 — Water Intake Tracking (LOW) - Backend: `WaterEntry` entity + Flyway V4 migration; `POST /water`, `GET /water/daily?date=` - Mobile: water counter widget on DailyDetails screen (+250ml / +500ml quick buttons, reset) ### REQ-UX-004 — Daily Logging Reminder (LOW) - In-app banner (no native push) - If it is after 18:00 local time and `totalCalories === 0` for today, show a reminder banner on HomeScreen - Dismissible; does not re-appear once dismissed in the same session --- ## 12. Open Questions (to resolve before development) 1. **Backend language**: Spring Boot (Java — familiar) or FastAPI (Python — easier AI integration)? 2. **Auth provider**: Self-managed JWT, Firebase Auth, or Auth0? 3. **Database**: Postgres (more control) or Firestore (faster to start)? 4. **Image storage**: Firebase Storage or S3 for photo uploads? 5. **AI provider**: OpenAI Vision API only, or also evaluate Google Vision / custom model from day 1? 6. **Platforms**: iOS only, Android only, or both from day 1? 7. **Confidence display**: Show to users always, or only when below a threshold (e.g. < 80%)?