REQ-MOB-010: BarcodeScreen.tsx — barcode scanner via react-native-camera REQ-VIZ-001: WeeklyCalorieChart.tsx — 7-day bar chart on History screen REQ-VIZ-002: Streak tracker — GET /meals/streak + HomeScreen badge REQ-UX-001: Quick-add calories — POST /meals/quick-add + QuickAddScreen REQ-UX-002: Food favourites — UserFoodMemory.favourite + toggle endpoint + FoodRow star REQ-UX-003: GoalBanner.tsx — in-app slide-in when daily target hit REQ-EXP-001: ExportController — GET /export/meals CSV download REQ-WTR-001: Water tracking — WaterEntry entity + POST/GET /water + DailyDetails widget REQ-UX-004: Daily logging reminder — HomeScreen after-18:00 banner Also: Flyway V2 (favourite), V3 (water_entries), V4 (source constraints) Traceability, CHANGELOG, PLAN updated after each feature
11 KiB
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:
- Confidence-aware calories — show
500 kcal ± 80 kcal (confidence 85%)instead of a false-precision single number - Personal food memory — app learns your typical portions, pre-fills next time
- 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
{
"id": "uuid",
"email": "string",
"createdAt": "timestamp",
"profile": {
"age": 30,
"weightKg": 80,
"heightCm": 180,
"goal": "lose | maintain | gain",
"dailyCaloriesTarget": 2200
}
}
FoodItem (normalised DB)
{
"id": "uuid",
"name": "Chicken breast",
"source": "openfoodfacts | custom | ai",
"caloriesPer100g": 165,
"macros": {
"proteinG": 31,
"fatG": 3.6,
"carbsG": 0
}
}
MealEntry
{
"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)
{
"id": "uuid",
"userId": "uuid",
"imageUrl": "string",
"detectedItems": [
{ "name": "rice", "estimatedGrams": 150, "confidence": 0.76 }
],
"userCorrections": [
{ "name": "rice", "correctedGrams": 180 }
]
}
UserFoodMemory (personalisation layer)
{
"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:
{
"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:
{
"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)
- Always require user confirmation before saving AI-detected meals — never auto-save
- 1-tap access to Add Meal from Home screen
- Sliders over number inputs for portion adjustment — faster, fewer errors
- Calories update in real-time while adjusting portions
- 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)
alttext 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
- User auth (register / login)
- User profile + BMR-based calorie target
- Food search (OpenFoodFacts API)
- Manual meal logging
- Barcode scan backend endpoint
- Daily calorie dashboard
- Meal history
Phase 2 — AI Layer ✅ Implemented
- Photo capture screen
- OpenAI Vision API integration (
/ai/analyze-meal) - AI result confirmation screen
- Per-item portion sliders (Edit Meal screen)
- AI correction storage
Phase 3 — Intelligence + Polish ✅ Implemented
- Confidence-aware display (kcal ± range)
- UserFoodMemory — personalised portion defaults
- "Repeat last meal" shortcut
- Macro tracking display (protein/carbs/fat)
- Fine-tune AI suggestions based on user corrections
Phase 4 — Enhanced Features (v1.1)
- REQ-MOB-010: Barcode scanner mobile screen (HIGH — fix UI gap)
- REQ-VIZ-001: Weekly calorie bar chart on History screen (HIGH)
- REQ-VIZ-002: Streak tracker — consecutive days logged (HIGH)
- REQ-UX-001: Quick-add calories without food search (MEDIUM)
- REQ-UX-002: Food favourites — star items in search (MEDIUM)
- REQ-UX-003: Goal achievement in-app notification (MEDIUM)
- REQ-EXP-001: Data export as CSV (LOW)
- REQ-WTR-001: Water intake tracking (LOW)
- 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.tsxusingreact-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
WeeklyCalorieChartcomponent: proportional-height bar chart for last 7 days (pure RNView, 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
favouriteboolean column touser_food_memories(Flyway V3) - Backend:
POST /foods/{id}/favourite(toggle) → upserts UserFoodMemory withfavourite=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 ≤ 0after 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
ShareAPI
REQ-WTR-001 — Water Intake Tracking (LOW)
- Backend:
WaterEntryentity + 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 === 0for 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)
- Backend language: Spring Boot (Java — familiar) or FastAPI (Python — easier AI integration)?
- Auth provider: Self-managed JWT, Firebase Auth, or Auth0?
- Database: Postgres (more control) or Firestore (faster to start)?
- Image storage: Firebase Storage or S3 for photo uploads?
- AI provider: OpenAI Vision API only, or also evaluate Google Vision / custom model from day 1?
- Platforms: iOS only, Android only, or both from day 1?
- Confidence display: Show to users always, or only when below a threshold (e.g. < 80%)?