Skip to content

Latest commit

Β 

History

1,326 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

OpenNutriTracker

Free. Open. Cited.
Open-source calorie, macro, and micronutrient logging for Android and iOS.

License Release Build Platform Translation status Stars Issues Pull requests

simonoppowa/OpenNutriTracker | Trendshift Β  #2 Dart Repository Of The Day | Trendshift

Getting started Β· Contributing Β· Translate

OpenNutriTracker logs what you eat and drink against a calorie and macro target it works out from your height, weight, age, and activity level, and keeps the record on your phone. It is for anyone who wants the numbers without handing their eating history to a company, whether that is losing weight, gaining it, managing a condition, or simply knowing.

Install

Download on the App Store Β Β  Get it on Google Play

Screenshots

Home screen showing calories left on a progress ring, carbs, fat and protein against their targets, and the day's logged activity Adding food to lunch, with recently logged items ready to re-add in one tap and a barcode scanner in the search field Food detail showing the full nutrition table with saturated fat, sugar and fibre, plus an expanded micronutrient panel
Home
where the day stands
Add food
re-log in one tap
Food detail
down to the micronutrient
Diary showing a month calendar with each day marked by how it went, and the selected day's calories and macro rings below Trends showing a seven-day streak, calories charted against the goal line, and daily macro averages Profile screen showing BMI, activity level, weight goal and weekly rate
Diary
every day you've logged
Trends
calories against your goal
You
goals and body metrics

Screenshots show a demo profile with generated data.

Why OpenNutriTracker

Cited Calorie targets follow IOM 2005, BMI follows WHO, macros follow WHO TRS 916, activity burn follows the 2024 Compendium. The in-app Sources & References screen links every paper (sources_screen.dart).
Careful The fasting timer opens with a content warning linking BEAT and NEDA, and "Not for me" is a first-class answer (fasting_warning_dialog.dart). No streak guilt, and no notification you didn't ask for. The daily reminder is off until you enable it.
Free No paid tier and no ads, with zero advertising or analytics SDKs in pubspec.yaml to add them with. That includes the micronutrient panel the big-name trackers put behind a subscription. No investors, and GPLv3 leaves no exit that could paywall it later.
Private No account to create. Your diary lives in AES-256-encrypted storage with the key held in the Android Keystore / iOS Keychain, every destination that receives a request is listed under Privacy with what it's sent, and the release signing fingerprint is published so you can verify your download.
Portable Export your diary, activities, recipes, custom meals and weight history as JSON or CSV, re-import it, or share an entry by QR. The export format documents the schema and what it leaves out.
Open Open Food Facts, USDA FoodData Central (CC0) and the German BLS (CC BY 4.0). The backend is its own open repository you can self-host.
Community driven Over 30 developers have already contributed code, and most merged pull requests come from someone other than the maintainer. Features and fixes arrive as user issues and PRs, across the app and its food backend, and every translation is contributed on Weblate, which needs no Dart and no local setup.
Inclusive Non-binary calorie estimation grounded in published trans-health research, nine languages, kcal or kJ, and screen-reader support treated as a bug when it breaks.

Key features

Feature
🍎 Food logging Search, scan a barcode, or quick-add kcal, backed by Open Food Facts, USDA, and German BLS.
πŸ““ Food diary Breakfast, Lunch, Dinner, and Snack on a calendar, with per-meal kcal targets.
πŸ“ˆ Trends Streaks, calories against your goal line, macro averages, water, and weight over time.
πŸ₯• Micronutrients Day and week views for ten nutrients, with optional reference-intake bars.
🍽️ Meals and recipes Reusable recipes with photo, brand, and barcode.
πŸƒ Activities and weight Workout catalogue or custom activities; weight trend against a target.
πŸ’§ Water and fasting A home-screen water chip and an optional intermittent-fasting timer.
🎨 Themes and units Material You accent on Android 12+, sixteen built-in themes, kcal or kJ.
πŸ“€ Export and import JSON and CSV export, JSON import, and QR sharing.
More detail on each feature
  • 🍎 Nutritional tracking: Log meals and snacks against a large food database: Open Food Facts plus a multi-source reference backend covering USDA FoodData Central and the German BundeslebensmittelschlΓΌssel (BLS), with the sources selectable in Settings β†’ Food databases. Each entry can be searched, scanned, or added straight as a number when you already know the calorie cost.
  • πŸ““ Food diary: A calendar-driven diary that breaks the day into Breakfast, Lunch, Dinner, and Snack, with per-meal kcal targets (Standard, OMAD, Five-small, Mediterranean, Two-meal, or a custom share), drag-to-rearrange between meals, and sort by time or by macro contribution.
  • πŸ“ˆ Trends: A current and best day-streak card, calories charted against your goal line, daily macro averages, water intake, and weight against target with an estimate of the weeks left to reach it. Switch the window between 7, 30 and 90 days or your whole history.
  • πŸ₯• Micronutrient panel: Day and week views for fibre, sodium, saturated fat, sugar, calcium, iron, potassium, vitamin D, vitamin B12, and magnesium, with optional Dietary Reference Intake bars from the IOM tables so you can see where you sit against the reference range.
  • 🍽️ Custom meals + recipes: Build a one-off custom meal or save a reusable recipe with photo, brand, and barcode. The recipe builder has its own ingredient picker with barcode scanning so you can compose meals from real products without leaving the screen.
  • ⚑ Quick add: When you already know roughly how much you ate, skip the search flow entirely. Quick add takes a title plus kcal (and optional macros) and logs it straight to the meal section.
  • πŸ“· Barcode scanner: Scan packaged items for instant lookup, paste a barcode manually when the camera struggles, or attach a barcode to a custom meal so future scans recognise your own foods.
  • πŸƒ Activities: Log workouts from a categorised activity catalogue or define your own custom activities with direct kcal entry and reusable templates.
  • πŸ’§ Water tracker: A water chip on the home screen with quick-add increments, an editable goal, and undo for the last entry.
  • ⏱️ Fasting timer: Optional intermittent-fasting timer with content-warning gate, a home chip showing time remaining, and a completion notification when you reach your window.
  • βš–οΈ Weight history: Capture weight during onboarding and on demand, see the trend on a chart with a dashed line at your target weight, and optionally taper the calorie goal as you approach it.
  • 🎨 Material You + theme picker: Adopt the system accent colour on Android 12+, or pick from sixteen built-in presets. The app icon adapts to iOS dark and tinted appearances and to Android themed icons.
  • πŸ”’ kcal or kJ: Switch the energy unit globally; every diary entry, target, and chart reflects the choice.
  • πŸ“€ Export and import: Export your diary entries, activities, tracked days, and recipes to a JSON zip, with flat CSV companions for the first three so a spreadsheet can read them (bundle format). Paste a JSON blob to import meals, and share a single meal or activity as a QR code another phone can scan. Your profile, weight log, custom-meal catalogue, activity templates, water and fasting history stay out of the bundle.

Privacy

No account, no sign-in, no analytics, no ads. Your profile, diary, activities, weight, water and fasting history, custom meals, and recipes live in local Hive boxes encrypted with AES-256. The key is generated on first launch, kept in the Android Keystore / iOS Keychain, and never transmitted (source). Settings β†’ Delete all my data wipes the active profile. Formal policy: Data Protection.

What leaves your device. These destinations, nothing else, and the last four only if you turn them on β€” plus one more, set out below, if you point the app at a server of your own:

Destination When What is sent
Open Food Facts Food search or barcode scan The search term or barcode. A word search also sends your device's language code to rank results; the fallback search and the barcode lookup send no locale at all. Your country is never sent β€” the country boost is applied on your device, to the results that come back
Supabase reference backend Food search The search term
Anthropic Only if you save your own API key and pick Anthropic The meal line you type on the multi-item add screen, or a meal photo you choose to read there, and your app language
OpenAI Only if you save your own API key and pick OpenAI As the Anthropic row, plus the model you chose
OpenRouter Only if you save your own API key and pick OpenRouter As the Anthropic row, plus the model you chose
β”” the vendor serving it Named in Settings; pinned, so it is the vendor the model names
Sentry Only if you opt in Crash traces, app and OS version, device model

And one destination this project cannot name. Every row above is a company with a published policy you can hold it to. If you point the app at a server you run, the destination is a machine of your choosing β€” so this row states a rule rather than a party. It is set apart deliberately: an open-ended entry in the list above would weaken the closed-list promise the list exists to make. It earns a place anyway, because burying the most privacy-relevant destination in prose would read as evasive.

Destination When What is sent
The address you entered, and nothing else Only if you save a server address in Settings β€” when you press Load models, and each time a meal line or photo is read The meal line or the photo, your app language, and the model name you typed

This is the one row you can falsify yourself: your own server's access log settles it, where no user can ever settle a claim about a vendor's retention. No third party receives anything on this path β€” which is not the same as the data staying put. It does leave the device, to the address you named, and the app will not send it in the clear to anything that is not a private address.

AI meal assistance is marked Experimental, and that is a claim about stability rather than accuracy: the feature may change or be removed, and the providers and models offered may change with it. It stops being experimental when two things hold β€” a model has been screened against a real corpus of photographs containing no food (#719 ran on five images, only one of them a photograph), and one release cycle passes with no provider or model dropped from the curated list. Until both are true the label stays, so that removing it is something you can check rather than something that felt right.

Neither test can be run against a server you run yourself, so the exit condition above is about the three hosted providers and does not cover that path. The project has never seen the model on your machine and there is no curated list for it to be dropped from. What stands in for a screen there is the setup check in Settings: it asks your server to read one meal line and one sample photograph, and reports what came back β€” so the camera is offered only after a photograph has actually been read once, and stops being offered when your server says it cannot.

AI meal assistance is off until you supply your own API key, or the address of a server you run, in Settings β†’ AI meal assistance β€” a server of your own needs an address and a model name, not a key. It can be paused without removing the credential. Where there is a key, it is held in the Android Keystore / iOS Keychain and never leaves the device except as the request header it authenticates; a server of your own has an address there instead, held the same way. The project never sees either and does not pay for a provider's use. Only the line you type, or a photo you explicitly pick, is sent β€” never your diary, profile, or history.

Three providers, and they differ along two axes that do not line up. Anthropic and OpenAI are reached directly; OpenRouter is a broker, so a request touches OpenRouter and the vendor serving your chosen model β€” two destinations, not one. Every curated OpenRouter model is pinned to the vendor named beside it in Settings, with fallbacks off, so that vendor is the one that answered; without a pin a request for a Claude model is routinely served by someone else, which is why the pin exists. The OpenRouter list reaches two vendors β€” Anthropic and OpenAI β€” so on that path the vendor is a per-model choice rather than a property of the provider. A key is stored per provider, so switching back does not mean finding a credential again.

Retention cuts the other way. Anthropic states images are not stored beyond the request β€” with one exception, below. OpenRouter keeps content only to route it, except as required for abuse detection, security, billing or legal compliance. And OpenAI keeps API inputs and outputs for up to 30 days by default, longer where law requires it or where reasonably necessary to protect its services or a third party from harm. Being reached directly is not the same as keeping less.

On the broker path the two stack, because a request lands at both destinations: OpenRouter's promise covers OpenRouter's own handling, and the vendor serving your model then keeps what it receives under its own policy. So choosing an OpenAI model through OpenRouter gets OpenRouter's routing promise and OpenAI's 30 days β€” and choosing an Anthropic one gets the ephemerality below, exception included. The serving vendor is named in Settings on every row precisely because it decides this.

One thing is still unique to the OpenRouter path. An account-level identity is forwarded to the serving vendor on every request and cannot be switched off β€” because you hold one key, it works as a stable per-user handle at that vendor. Neither direct path forwards one: OpenAI's safety_identifier is documented optional and the app does not send it.

Reading a meal photo is the same feature with a camera instead of a keyboard, and is offered once a key or address is enabled β€” for a server you run, only after the setup check above has read a photograph successfully. The photo is encoded in memory, sent for that one request, and then unreachable β€” it is never written to the app's documents directory, so it is not in your exports and cannot be shown again. The system photo picker does hand the app a temporary copy in its cache; the app attempts to delete that as soon as the photo is encoded, whether or not the request succeeded β€” best effort, so on the rare occasion the delete fails the copy stays in the cache until the OS clears it. On the Anthropic-direct path, Anthropic's vision documentation states images are "ephemeral and not stored beyond the duration of the API request" and are not used to train models. That default has one exception, stated by Anthropic itself, and it is about retention, not training: its retention documentation states that content flagged by its automated trust-and-safety systems may be retained for up to two years regardless of the ephemeral promise, to enforce its Usage Policy. That sentence β€” ephemeral, with this exception β€” is Anthropic's and does not travel: via OpenRouter or OpenAI the applicable promise is the weaker one above, and the two are weaker in different ways.

The model reads language, not nutrition: it returns a food name and, when you stated one, an amount. Every calorie and macro still comes from the food databases below, so "every number is cited" holds whether or not you enable this. The request carries a tool schema with no nutrition fields (#633), so the model has nowhere to put an estimated calorie count, and whatever it returns is held to the same bounds the offline parser enforces.

From a photo the rule is tighter still: it may count what it can see (two eggs, three sausages) but never measure. Nothing in a photograph states a weight, so a gram figure read off a picture would be a guess arriving with the same confidence as a number you typed. Any amount that comes back carrying a unit is discarded along with its number, and the row falls to the ordinary default for you to set.

How it is built is documented separately. The AI implementation walks a typed meal and a photo end to end, maps the request paths, and shows where each rule above is enforced β€” the nutrition rule, for one, is a single schema constant with no such field in it, re-checked in Dart against a reply that ignored the schema entirely. This section states what the app promises; that page states how it is made to hold, and defers back here wherever the two touch.

USDA FoodData Central, the German BLS, INDB and TBCA are where the food data comes from, not places your device talks to. Those datasets are ingested into the Supabase backend ahead of time (self-hosting guide), so a search reaches that backend and stops there. Settings β†’ Food databases chooses which datasets a search covers. Five are selectable today, with INDB and TBCA in the schema but not yet carrying data (sp_const.dart).

Requests to Open Food Facts carry a User-Agent naming the app, platform, and version; requests to the Supabase backend carry the Supabase SDK's own client headers instead. The app generates no user or device identifier and sends none β€” but a request still arrives from somewhere, and the Supabase gateway logs the address it came from along with a coarse location and a fingerprint of the TLS connection, kept for 24 hours. Search results are cached locally and pruned after 90 days.

Crash reporting is off until you enable it, and initializes only in release builds (main.dart:119). sendDefaultPii stays false, so no username, email, or IP-derived identity is attached. Disabling it, or deleting your data, closes the SDK immediately.

Permissions: camera (barcode scanning, meal photos), photo library (meal photos, exports), notifications (daily reminder, fasting timer), internet (food lookups), and receive-boot-completed (re-registering the reminder after a reboot). Health data β€” workouts and body fat percentage β€” is read only if you turn on workout import under Settings β†’ Health sync, which is off by default; the access is read-only, nothing is ever written back to Health Connect or Apple Health, and the imported workouts stay on your device. No location, contacts, or microphone access.

Not collected: no account, email, or phone number. The backend is read with an anonymous key and there is no sign-in path. No advertising ID and no cross-app tracking: NSPrivacyTracking is false with an empty tracking-domains list, and crash and performance data are declared not linked to the user (PrivacyInfo.xcprivacy).

Verifying APK signatures

If you are side-loading an OpenNutriTracker APK from GitHub Releases, or from F-Droid once the app is published there, you may want to confirm that the file you downloaded was signed by the same key used for every official release, rather than by someone who intercepted the download or repackaged the app.

The official SHA256 fingerprint of the Android release signing certificate is:

SHA256: 84:E8:60:74:EC:7E:DA:BB:10:F2:01:79:86:DD:F0:9E:53:1C:AF:7A:73:08:0A:C1:17:2B:80:C4:9C:62:08:27

To verify a downloaded APK against that fingerprint, run:

apksigner verify --print-certs /path/to/opennutritracker.apk

The SHA-256 line in the output should match the value above exactly.

Translations

OpenNutriTracker is translated on Hosted Weblate. Translating needs no local setup and no Dart. Pick a language, edit the strings in the browser, and Weblate syncs the result back to this repository.

Translation status per language

To start a language that isn't listed yet, request it from the Weblate project page. If you would rather work in the repository directly, the source strings live in lib/l10n/intl_en.arb. See CONTRIBUTING.md for the conventions.

What people say

This app has a user-friendly interface and is unburdened by the ridiculous (and constant) cash-grabbing that is chronic across health and wellness apps. As someone suffering from extreme subscription fatigue β€” I'm not a walking wallet! β€” this nutrition tracker is a breath of fresh air.

β€” Ai C., Google Play β˜…β˜…β˜…β˜…β˜…

No ads, no paywalls, no bloat, no bs. You can export your data at any moment, or import some from somewhere else, no questions asked. I have experienced no bugs in these last few months. Developers are still active on the repo, so I'm expecting it to get even better.

β€” App Store review β˜…β˜…β˜…β˜…β˜…

The most recent version puts this open source nutrition tracker among the best resources out there β€” all while respecting your privacy through free and open source software. If you care about your fitness and care about having control of your data, look no further!

β€” App Store review β˜…β˜…β˜…β˜…β˜…

Excellent simple app without ads that gets the job done. I have legit lost over 10 kg using this app.

β€” Esko E., Google Play β˜…β˜…β˜…β˜…β˜…

Simple, fast and very functional. Finally I don't have to sell my soul to MyFitnessPal ;)

β€” Frederic-Leon C., Google Play β˜…β˜…β˜…β˜…β˜…

Reviews are lightly trimmed for length; the full text is on the App Store and Google Play listings. Bug reports and feature requests belong in the issue tracker, which gets read faster than a review does.

Mentions

I've got my OpenNutriTracker here, my open-source calorie counter. Support open-source apps. No ads, no subscriptions, and I don't send my data to anyone β€” everything stays here.

β€” CadΓͺ a Chave?, Ep. 1773 (at 8:18), the vlog channel run by the team behind Coisa de Nerd, one of Brazil's largest tech channels at 11M+ subscribers. Translated from the Portuguese by a contributor in #375.

Where What
Trendshift Ranked #2 Dart Repository of the Day
It's All Widgets! Featured in the Flutter app showcase
AlternativeTo Currently the top-ranked open-source MyFitnessPal alternative

If you have written or talked about OpenNutriTracker somewhere, open an issue or a pull request and it can go on this list.

Contributing

Issues and pull requests are welcome. See CONTRIBUTING.md for the project's conventions, including the requirement to target the develop branch and the steps for adding localized strings.

Built with Flutter and Dart, following a clean-architecture split (data / domain / presentation) with flutter_bloc for state, get_it for dependency injection, and encrypted hive_ce boxes for local storage. AGENTS.md is the full architecture and conventions reference.

Getting started: see GettingStarted.md for setting up a local build.

Data export format: the export bundle (Settings β†’ Export / Import App Data β†’ Export) is documented at docs/export-format.md, covering both the JSON schema and the CSV companion the import / export round-trip uses.

Food database backend: the multi-source food database lives in its own repository, OpenNutriTracker-Backend, which holds the schema, import pipeline, and translation tooling. Self-hosting it and pointing a local build at your own Supabase project is documented at docs/supabase-self-hosting.md.

Thanks to all the contributors:

Disclaimer

Warning

OpenNutriTracker is not a medical application. All data provided is not validated and should be used with caution. Please maintain a healthy lifestyle and consult a professional if you have any problems. Use during illness, pregnancy or lactation is not recommended.

Note

The application is still under construction. Errors, bugs and crashes might occur.

Acknowledgments

The food database used in OpenNutriTracker is powered by Open Food Facts together with a multi-source reference backend hosted in Supabase: USDA FoodData Central (CC0) and the BundeslebensmittelschlΓΌssel 4.0 (CC BY 4.0, Β© Max Rubner-Institut), with the Anuvaad INDB (CC BY 4.0) and TBCA Brazil (USP/FoRC) prepared as future sources. The schema and import pipeline live in the OpenNutriTracker-Backend repository; self-hosting is documented in docs/supabase-self-hosting.md.

Dietary Reference Intake values for the micronutrient panel come from the U.S. National Academies' Institute of Medicine tables. The in-app Sources & References screen (one tap from the home calorie ring or the profile BMI card) lists the peer-reviewed sources used for energy needs, BMI classification, macro distribution, MET activity calories, and non-binary calorie estimation.

License

This project is licensed under the GNU General Public License v3.0. See the LICENSE file for more information.

Contact

For questions, suggestions, or collaborations, contact the maintainer:

Simon Oppowa

About

🍴 OpenNutriTracker is a free and open source calorie tracker with a focus on simplicity and privacy.

Topics

Resources

Code of conduct

Contributing

Stars

2.5k stars

Watchers

15 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages