A science-informed health & fitness app tailored to Indian dietary habits and lifestyle.
Neo Fit helps Indian users track calorie intake & burn, log diverse Indian foods (home, street, thali, regional), follow simple goal-based workouts, and watch their weight & wellness trend — all offline-first, privacy-first, and transparent about estimation.
⚠️ Neo Fit supports general fitness and wellness. It does not replace professional medical or nutrition advice. Calorie values for many Indian dishes are approximations, and the app says so.
- 🌐 Website: https://naveenneog.github.io/NeoFit/
- ⬇️ Latest APK: NeoFit-v1.4.0.apk · Android 8.0 (API 26)+
- 🏛️ Architecture & restart context: docs/ARCHITECTURE.md
- 📜 License: PolyForm Noncommercial 1.0.0 — open-source, free for non-commercial use.
- Highlights
- Tech stack
- Architecture
- Module / package layout
- Screens
- Data models
- How calorie estimation works
- Regional classification
- Wellness score
- Food image system (web → Azure → placeholder)
- Multilingual / native food names
- Setup
- Configuring Health Connect
- Configuring Azure image generation
- Testing
- Assumptions
- Known limitations
- Future improvements / production TODOs
- Indian food intelligence: a seeded knowledge base spanning regions (South, North, North-East, West, Central, East, pan-Indian), home meals, street food, thalis/combos, beverages, snacks and sweets — each with native names and per-serving nutrition.
- Honest calorie estimation: portion multipliers + cooking-style adjustment + confidence
scoring (
High/Medium/Rough estimate) and a human-readable basis. Approximate values are prefixed with~. Users can correct anything. - Activity sync with graceful fallback: reads steps/distance/active-calories from Health Connect when available; otherwise estimates/simulates so the dashboard stays useful.
- Goal-based workouts: 7 plans with step-by-step instructions, a live timer, voice guidance (TTS), calorie accrual, and on-demand generated pose images.
- Weight & transparent wellness score (0–100) you can see the breakdown of.
- Recommendations & nudges (e.g. “You’re short on protein today”, “You’ve already walked 70%”).
- Multilingual with native dish names and Hinglish/Kanglish flavour.
- Offline-first: Room is the source of truth; network/AI sit behind interfaces with mocks.
Kotlin · Jetpack Compose (Material 3) · MVVM + Clean Architecture · Room · Hilt · Coroutines + Flow · DataStore · Retrofit/OkHttp + kotlinx.serialization · Coil · Health Connect · Camera/Photo Picker · JUnit + Truth (unit) · AndroidX Test + Compose UI Test (instrumentation).
- AGP 8.7.3 · Kotlin 2.0.21 · KSP · Compose BOM 2024.12.01 · Hilt 2.52 · Room 2.6.1
compileSdk 35·minSdk 26·targetSdk 35
Clean Architecture with a unidirectional data flow:
UI (Compose screens) ──► ViewModel (StateFlow) ──► UseCase ──► Repository (interface)
│
┌────────────────────────┼───────────────────────┐
▼ ▼ ▼
Room (local, SoT) Integrations (Health Engines (pure
Connect, Azure AI, Kotlin: estimation,
recogniser mock) region, wellness, reco)
- Domain is pure Kotlin: models, repository interfaces, use cases. No Android/framework deps.
- Engines (
engine/) are pure, deterministic and unit-tested:CalorieMath,CalorieEstimationEngine,RegionClassifier,WellnessScoreEngine,RecommendationEngine. - Data implements repositories over Room DAOs and in-memory seed libraries, mapping entities ↔ domain models.
- Integrations wrap external/AI concerns behind interfaces:
HealthConnectManager,ImageGenerationService(+AzureImageGenerationService),FoodImageProvider(WebImageProvider,AzureGeneratedImageProvider),FoodRecognitionService(MockFoodRecognitionService). - DI (Hilt) wires it all in
di/(DatabaseModule,NetworkModule,EngineModule,RepositoryModule).
The brief lists feature modules. We implement strict package separation
(core, data, domain, engine, integration, feature/*, di) inside a single Gradle
module. This maximises "compiles in one shot with minimal manual work" while preserving
clean-architecture boundaries. Splitting into Gradle modules later is mechanical (the package
boundaries already match) — see TODOs.
app/src/main/java/com/neofit/
├── NeoFitApp.kt # @HiltAndroidApp
├── MainActivity.kt # edge-to-edge, theme, locale, NavGraph host
├── core/
│ ├── designsystem/ # Material3 theme, colors, type, dimens
│ ├── i18n/ # LocaleManager, LocalAppLanguage
│ ├── common/ # UiState, DataResult
│ └── util/ # DateUtil, Format
├── domain/
│ ├── model/ # UserProfile, FoodItem, MealLog, ExercisePlan, …
│ ├── repository/ # repository interfaces
│ └── usecase/ # ComputeGoal, GetDashboard, LogMeal, EstimateMeal, …
├── engine/ # pure estimation/region/wellness/recommendation engines
├── data/
│ ├── local/ # Room DB, entities, DAOs, converters, mappers
│ ├── repository/ # repository implementations
│ └── seed/ # FoodKnowledgeBase, ExerciseLibrary
├── integration/
│ ├── health/ # HealthConnectManager
│ └── ai/ # image generation, providers, recognition mock, prompt builder
├── di/ # Hilt modules
└── feature/
├── onboarding/ dashboard/ foodlog/ exercise/ progress/ profile/ insights/
├── common/ # shared Compose components
└── navigation/ # routes + NavGraph
Splash · Onboarding (7 steps) · Home dashboard · Food log · Add meal · Meal search · Camera/photo food log · Meal detail · Exercise plans · Exercise detail (runner) · Progress · Weight history · Profile/settings · Region & preferences · Insights.
UserProfile, Goal, FoodItem, MealLog, NutritionEstimate, FoodRegion, PortionSize,
ExercisePlan, ExerciseItem, WorkoutSession, StepSummary, WeightEntry, WellnessSummary,
FoodImageAsset, Recommendation, SyncStatus, plus the aggregate DashboardSummary.
CalorieEstimationEngine turns a knowledge-base FoodItem + chosen PortionSize (+ optional
cooking-style override) into a NutritionEstimate:
- Base lookup – per-serving calories/macros from
FoodKnowledgeBase. - Portion multiplier –
relativePortion = chosenPortion.multiplier / baseServing.multiplier. - Cooking adjustment – if the user overrides the cooking method, calories (and fat) scale by
override.factor / baseStyle.factor(e.g. frying ≈ ×1.4). - Confidence scoring – starts from the food's
baseConfidence, downgraded for street food/combos, unusual portions, or a cooking override. Surfaced asHigh/Medium/Rough estimate. - Transparency – a plain-language
basisstring and anisApproximateflag (UI shows~). - Manual correction – an entered calorie override is trusted and flagged.
BMR/TDEE/targets use the Mifflin–St Jeor equation (CalorieMath), with safe deficit/surplus
caps and a hard calorie floor.
RegionClassifier infers a broad regional food profile from your logged dishes. It is advisory,
never restrictive, fully overridable, and explains itself ("Detected mostly South India dishes
(3 of 4 regional meals)…"). Pan-Indian/neutral dishes carry no regional signal.
WellnessScoreEngine produces a transparent 0–100 score = Consistency 25 + Activity 25 + Calorie
adherence 30 + Workout 20. The Insights screen shows each component so the number is never a black box.
ImageRepositoryImpl resolves a dish/exercise image through a provider chain and caches the result:
- WebImageProvider – returns a known image URL if the food ships one (plug a real image-search API here — see TODO).
- AzureGeneratedImageProvider – calls the configured Azure model (
gpt-image-2) with a prompt fromPromptBuilder. - Placeholder – a colourful gradient tile with the dish initials (always available).
Lists use placeholders (cheap); generation is triggered on explicit actions (meal detail, workout runner) to avoid unnecessary API calls.
- Language is chosen during onboarding and changeable in Profile.
FoodItem.localizedNamesholds authentic native dish names (never invented words), e.g. इडली / ಇಡ್ಲಿ / இட்லி. Romanized blends (Hinglish/Kanglish/Tanglish) reuse the already-nativenameEn(e.g. "Rajma Chawal").- Android UI strings are localised for English and Hindi; other languages fall back to
English UI while still showing native dish names. Runtime translation of remaining UI is wired as
an Azure AI Translator placeholder (config in
local.properties). LocaleManagerapplies the resource locale at startup;LocalAppLanguagedrives dynamic content.
Prerequisites: Android Studio (Koala+), JDK 17, Android SDK 35.
# 1. Open the project in Android Studio (or use the wrapper)
# 2. Ensure local.properties has your SDK path (Android Studio writes this automatically):
# sdk.dir=/path/to/Android/Sdk
# 3. Build & install on a device/emulator (API 26+):
./gradlew :app:installDebug
# or
./gradlew :app:assembleDebugThe app opens into onboarding, then the home dashboard. Seed data (Indian foods, workout plans) is bundled — no backend required.
- Permissions for steps, distance, active/total calories and exercise are declared in the manifest, plus the permission-rationale intent filters.
- On a device with Health Connect installed, the app reads today's steps/distance/active calories
via
HealthConnectManagerand shows sourcehealth connect. - On a device without Health Connect (e.g. many emulators), reads return null and the app
estimates/simulates steps so the dashboard remains demonstrable (source
estimated). - To grant permissions on a real device: install “Health Connect”, then accept the permission
request the app triggers on first activity sync. (A first-class permission-request button is a
TODO; the plumbing/contract already exists in
HealthConnectManager.)
Credentials are read from local.properties (or environment variables) into BuildConfig — no
secrets are committed. Defaults already point at a verified-working Foundry deployment; supply a
key to enable generation:
# local.properties
AZURE_OPENAI_ENDPOINT=https://<your-resource>.cognitiveservices.azure.com
AZURE_OPENAI_API_KEY=<your-key> # leave blank to disable generation (falls back to placeholder)
AZURE_IMAGE_DEPLOYMENT_NAME=gpt-image-2
AZURE_API_VERSION=2025-04-01-previewThe call uses the deployment-path Images API
(POST {endpoint}/openai/deployments/{deployment}/images/generations?api-version=...) with the
api-key header and parses b64_json. With no key configured, the app is fully usable and shows
gradient placeholders.
Auth note: the in-app client uses API-key auth (simplest for a mobile build). Production deployments should proxy through a backend using Azure AD / Managed Identity (DefaultAzureCredential) rather than shipping a key — see TODOs.
./gradlew :app:testDebugUnitTest # engine unit tests (JUnit + Truth)
./gradlew :app:connectedDebugAndroidTest # Room round-trip + Compose smoke (needs a device/emulator)- Unit:
CalorieMath,CalorieEstimationEngine,RegionClassifier,WellnessScoreEngine,RecommendationEngine. - Instrumentation: Room persistence (
NeoFitDatabaseTest) and a Compose render smoke test (ComposeSmokeTest).
This build has been validated end-to-end on an Android 14 (API 34) emulator: onboarding → dashboard → search → estimate → log → exercise runner (timer + TTS), with unit + instrumentation suites green.
- Single user / single profile (
id = 1). Multi-profile/account sync is out of scope for the MVP. - Single Gradle module with package separation (see rationale above).
- Calorie values are approximate for most Indian dishes by design; the app communicates this.
- Food recognition is a mock that returns confirmable candidates — we never auto-log a guess.
- Water/hydration is a simple per-day glass counter (placeholder card on the dashboard).
- Steps may be simulated when Health Connect is unavailable so the experience is demonstrable.
- English & Hindi UI strings are translated; other languages fall back to English UI with native dish names.
- No real food-image recognition model (mock + manual confirmation).
- Web image provider only resolves URLs already present in the data (no live image search yet).
- Health Connect permission flow relies on the system prompt; no dedicated in-app rationale screen.
- Nutrition data is curated/approximate, not a certified database.
- No cloud backup/sync; data is local to the device.
- Split packages into real Gradle feature modules (boundaries already align).
- Replace
MockFoodRecognitionServicewith an on-device (ML Kit/TFLite) or cloud vision model. - Add a licensed image-search provider for
WebImageProvider. - Back Azure image/translation calls with a server using Azure AD / Managed Identity.
- First-class Health Connect permission & onboarding screen; write-back of workouts.
- Expand the food knowledge base and add per-ingredient composition estimates.
- Full UI localisation for all supported languages (wire
AzureTranslator). - Room migrations (currently destructive fallback for the MVP).
- Cloud sync/backup, widgets, notifications/reminders, accessibility audit, ProGuard tuning.
Product name “Neo Fit” is a placeholder. Built as a production-ready MVP foundation.