{"id":50729093,"url":"https://github.com/anirudhtopiwala/macroshot","last_synced_at":"2026-06-10T07:01:25.977Z","repository":{"id":363473551,"uuid":"1240994793","full_name":"anirudhtopiwala/macroshot","owner":"anirudhtopiwala","description":"Open-source AI macro tracker - log meals by photo, text, or barcode. Built-in nutrition coach, self-hostable PWA.","archived":false,"fork":false,"pushed_at":"2026-06-09T04:22:29.000Z","size":11979,"stargazers_count":0,"open_issues_count":10,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-09T05:04:26.978Z","etag":null,"topics":["fastapi","gemini","meal-tracker","nutrition","pwa","react","self-hosted"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anirudhtopiwala.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"anirudhtopiwala","custom":["https://buy.stripe.com/5kQ3cu7rR9KI0Y34hN2go00"]}},"created_at":"2026-05-16T20:41:25.000Z","updated_at":"2026-06-09T04:13:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/anirudhtopiwala/macroshot","commit_stats":null,"previous_names":["anirudhtopiwala/macroshot"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/anirudhtopiwala/macroshot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anirudhtopiwala%2Fmacroshot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anirudhtopiwala%2Fmacroshot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anirudhtopiwala%2Fmacroshot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anirudhtopiwala%2Fmacroshot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anirudhtopiwala","download_url":"https://codeload.github.com/anirudhtopiwala/macroshot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anirudhtopiwala%2Fmacroshot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34140775,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastapi","gemini","meal-tracker","nutrition","pwa","react","self-hosted"],"created_at":"2026-06-10T07:01:00.155Z","updated_at":"2026-06-10T07:01:25.955Z","avatar_url":"https://github.com/anirudhtopiwala.png","language":"Python","funding_links":["https://github.com/sponsors/anirudhtopiwala","https://buy.stripe.com/5kQ3cu7rR9KI0Y34hN2go00"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./assets/logo.png\" alt=\"MacroShot\" width=\"120\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eMacroShot\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/anirudhtopiwala/macroshot/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/anirudhtopiwala/macroshot/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE.md\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-FSL--1.1--Apache--2.0-blue.svg\" alt=\"License: FSL-1.1-Apache-2.0\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/status-open%20beta-orange.svg\" alt=\"Status: open beta\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/python-3.10+-3776ab.svg\" alt=\"Python 3.10+\"\u003e\n  \u003ca href=\"https://github.com/sponsors/anirudhtopiwala\"\u003e\u003cimg src=\"https://img.shields.io/badge/sponsor-%E2%9D%A4-ff69b4.svg\" alt=\"Sponsor\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cem\u003eSnap a photo. Know your macros. Own your data.\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  The open-source AI macro tracker. Log meals by photo, text, or barcode.\u003cbr/\u003e\n  Chat with a nutrition coach that actually reads your data.\u003cbr/\u003e\n  Runs on every device you own - phone, tablet, laptop.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./web/public/marketing/hero-log.png\" alt=\"MacroShot analyzing a Buddha bowl with AI-identified ingredients\" width=\"800\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://macro.anirudhtopiwala.com/macro_app/\"\u003e\u003cstrong\u003e▶︎ Try the hosted version\u003c/strong\u003e\u003c/a\u003e\n  \u0026nbsp;·\u0026nbsp;\n  \u003ca href=\"#self-hosting\"\u003eSelf-host\u003c/a\u003e\n  \u0026nbsp;·\u0026nbsp;\n  \u003ca href=\"#screenshots\"\u003eScreenshots\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## What it does\n\n| | |\n|---|---|\n| 📸 **Log any way you want** | Snap a photo, type a sentence, or scan a barcode. AI handles portions. |\n| ✨ **AI Coach** | MCP-powered chat with 23 tools for meals, targets, weight, workouts, and long-term memory (allergies, restrictions, preferences). |\n| 📈 **Trends \u0026 Analytics** | 7/30/90-day charts for calories, macros, weight, and adherence. |\n| 🏃 **Strava + Fitbit + Oura** | Auto-sync workouts; targets adjust based on what you burned. |\n| ⚖️ **Weight Tracking** | Trend line shows progress against your goal, not just today's number. |\n| ⭐ **Saved Meals** | One-tap quick-log for your regulars. No re-typing. |\n| 🏆 **Streaks \u0026 Achievements** | 24 badges, Bronze→Diamond. Streak shields recover missed days. |\n| 📔 **Journal + Gallery** | Browse meals as a list or photo wall. Search, filter, swipe-to-delete. |\n| 📤 **Export \u0026 Share** | CSV download or PDF nutrition report for your doctor or coach. |\n| 🖥️ **Every device** | Same PWA on phone, tablet, laptop. Installable, offline-ready, push reminders. |\n\n## Screenshots\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\" width=\"50%\"\u003e\n      \u003cimg src=\"./web/public/marketing/chat-coach.png\" alt=\"Chat with the AI coach\" /\u003e\n      \u003cbr/\u003e\u003csub\u003e\u003cb\u003eAI coach reads your real data via MCP\u003c/b\u003e\u003c/sub\u003e\n    \u003c/td\u003e\n    \u003ctd align=\"center\" width=\"50%\"\u003e\n      \u003cimg src=\"./web/public/marketing/multi-image.png\" alt=\"Multi-image meal analysis\" /\u003e\n      \u003cbr/\u003e\u003csub\u003e\u003cb\u003eMulti-photo meals - analyze each plate together\u003c/b\u003e\u003c/sub\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\" width=\"50%\"\u003e\n      \u003cimg src=\"./web/public/marketing/trends.png\" alt=\"Trends and analytics\" /\u003e\n      \u003cbr/\u003e\u003csub\u003e\u003cb\u003e7/30/90-day trends with target reference lines\u003c/b\u003e\u003c/sub\u003e\n    \u003c/td\u003e\n    \u003ctd align=\"center\" width=\"50%\"\u003e\n      \u003cimg src=\"./web/public/marketing/achievements.png\" alt=\"Streaks and achievements\" /\u003e\n      \u003cbr/\u003e\u003csub\u003e\u003cb\u003e24 badges, Bronze to Diamond, with streak shields\u003c/b\u003e\u003c/sub\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Why MacroShot?\n\nThree things make MacroShot different:\n\n- **Log meals the way you actually eat.** Snap a photo of your plate, type \"two scrambled eggs and a banana,\" or scan the barcode on a protein bar. The AI handles portions and macros - no more giving up on tracking because typing every meal is exhausting.\n- **A coach that actually reads your data.** Not a chatbot that gives generic advice - an AI coach with structured access (via [MCP](https://modelcontextprotocol.io)) to your meals, targets, weight history, and connected workouts (Strava / Fitbit / Oura). Ask \"did I hit protein this week?\" and it answers from your real numbers.\n- **Open source. Your data, your call.** Use the hosted version for zero-setup convenience, or self-host for total control. Either way the code is open and the data model is yours to inspect.\n\n## Accuracy\n\nMacroShot's meal-reading prompt is benchmarked against the published baseline from Wang et al. 2026 on the public [Nutrition5K](https://arxiv.org/abs/2103.03375) dataset - measuring how closely it reads calories and macros from a photo.\n\n- **[Live results dashboard →](https://anirudhtopiwala.github.io/macroshot/macroshot_eval/)** - accuracy across models, plus a per-dish gallery of the meals the models nail and the ones they miss.\n- **[Reproducible eval harness](eval/nutrition5k/)** - the conditions, metrics, and dataset pipeline, runnable against any Gemini or Claude model.\n\n## Self-Hosting\n\n\u003e **Scope — personal or trusted-circle only.** MacroShot is built for\n\u003e personal use or a small trusted group (you, family, friends). Any\n\u003e email address can sign up and use the app once your instance is\n\u003e reachable. There is no per-user admin role beyond an `ADMIN_EMAIL`\n\u003e allowlist for the read-only metrics dashboard, no per-user quotas\n\u003e beyond the global free/Pro caps, and no tenant isolation beyond\n\u003e per-`user_id` row scoping. If you intend to run a public instance,\n\u003e put auth or IP allowlisting at the reverse proxy in front of it and\n\u003e read [`docs/self-hosting-legal.md`](docs/self-hosting-legal.md)\n\u003e first.\n\n### Prerequisites\n\n- Python 3.10+\n- Node.js 18+ and npm\n- A [Google Gemini API key](https://ai.google.dev/)\n- (Optional) A [Google OAuth client](https://console.cloud.google.com/apis/credentials) for Google sign-in\n- (Optional) A Stripe account for paid subscriptions\n- (Optional) VAPID keys for push notifications (`npx web-push generate-vapid-keys`)\n\n### Quick Start\n\n```bash\ngit clone https://github.com/anirudhtopiwala/macroshot.git\ncd macroshot\npython3 -m venv .venv\n.venv/bin/pip install -r requirements.txt\ncp .env.example .env\nchmod 600 .env         # restrict so other users on the box can't read your keys\n$EDITOR .env           # fill in your keys (see Environment variables below)\ncd web \u0026\u0026 npm install \u0026\u0026 npm run build \u0026\u0026 cd ..\n.venv/bin/uvicorn src.web.app:app --host 127.0.0.1 --port 8000\n```\n\n\u003e **Why `127.0.0.1`?** Binding to localhost keeps the dev server off\n\u003e your LAN and public IP. For production, use the systemd unit + reverse\n\u003e proxy in [docs/deploy.md](docs/deploy.md). To test on a phone over\n\u003e LAN, swap in `--host 0.0.0.0` **only** on a trusted network.\n\n\u003e **Production note:** before exposing the instance to anyone else,\n\u003e set `JWT_SECRET` to a strong random value (`openssl rand -hex 32`),\n\u003e set `APP_ENV=production`, set `OAUTH_TOKEN_KEY` if you enable any\n\u003e OAuth integrations, and put a TLS reverse proxy in front of uvicorn.\n\u003e See [SECURITY.md](SECURITY.md) for the full self-host hardening list.\n\nThe app will be available at `http://localhost:8000/macro_app/`.\n\n\u003e **Signing in locally:** the bundled `.env.example` sets `DEBUG_SHOW_PINS=1`,\n\u003e so when you sign up with an email address the 6-digit login PIN is printed\n\u003e to the uvicorn server log (the terminal where you ran the last command above)\n\u003e instead of being emailed. No Resend account needed to try the app. **Remove\n\u003e `DEBUG_SHOW_PINS` and configure `RESEND_API_KEY` + `RESEND_FROM_EMAIL`\n\u003e before exposing the instance to anyone else.**\n\nFor a production deployment with systemd + reverse proxy, see [docs/deploy.md](docs/deploy.md).\n\n### Environment variables\n\nThe only required ones are:\n\n| Variable | Description |\n|---|---|\n| `GEMINI_API_KEY` | Google Gemini API key for meal analysis |\n| `JWT_SECRET` | Secret key for signing auth tokens (`openssl rand -hex 32`) |\n\n\u003e ⚠️ **Auth-bypass risk if `JWT_SECRET` is unset.** The app falls back\n\u003e to a hard-coded dev key (`dev-secret-change-in-production`). Anyone\n\u003e who knows this string can mint valid session tokens for your\n\u003e instance. Generate a real value with `openssl rand -hex 32` and set\n\u003e `APP_ENV=production` so the server refuses to boot with the dev key.\n\nEverything else (Google OAuth, Stripe, push notifications, Strava / Fitbit / Oura, Sentry, instance branding strings) is optional and documented inline in [`.env.example`](.env.example). When `STRIPE_SECRET_KEY` is unset, the app runs in self-host mode - all features free, no billing gates.\n\n### Self-hosting legal responsibilities\n\nIf you operate a public instance (even for friends or family), you become the **data controller** under GDPR / CCPA / MHMDA / similar privacy laws, and you take on real responsibilities - replace the bundled Privacy Policy + ToS to name yourself as the data controller, age-gate per your jurisdiction, post AI-disclaimers, and more.\n\n\u003e ⚖️ **Read [`docs/self-hosting-legal.md`](docs/self-hosting-legal.md) before exposing your instance to anyone other than yourself.** The bundled Privacy Policy + Terms apply only to the official hosted instance - you must publish your own.\n\n## Tech Stack\n\n| Layer | Technology |\n|---|---|\n| Frontend | React 19, Vite 7, TypeScript, Tailwind CSS, Workbox (PWA) |\n| Backend | Python 3.10+, FastAPI, Uvicorn, Pydantic v2 |\n| Database | SQLite via aiosqlite (with connection pooling) |\n| AI | Gemini 2.5 Flash Lite (google-genai SDK), FastMCP for tool use |\n| Auth | Google OAuth 2.0, email PIN (Resend), JWT sessions |\n| Payments | Stripe (checkout, portal, webhooks) |\n| Fitness | Strava API, Fitbit Web API (OAuth + PKCE) |\n| Push | Web Push API via pywebpush (VAPID) |\n| Hosting | Any Linux server (1 vCPU / 1 GB RAM is enough) |\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for the full contributor guide. The short version:\n\n1. Open an issue first to discuss what you'd like to change.\n2. Fork the repo, create a feature branch.\n3. Run the tests: `pytest tests/ -x -q` and `cd web \u0026\u0026 npx tsc -b --noEmit \u0026\u0026 npx vite build`.\n4. Open a PR with a brief description and test plan.\n\nBy contributing, you agree to abide by the [Code of Conduct](CODE_OF_CONDUCT.md).\n\n## Support the project\n\nMacroShot is free to self-host. If it's useful to you and you'd like to support continued development:\n\n- [GitHub Sponsors](https://github.com/sponsors/anirudhtopiwala) - one-time or recurring, no platform fees\n- [Buy me a coffee](https://buy.stripe.com/5kQ3cu7rR9KI0Y34hN2go00) - one-time tip via Stripe\n\nSponsorship funds active development - new features, bug fixes, and time spent building in the open. Not tax-deductible.\n\n## Contact \u0026 Security\n\nQuestions or feedback? Email **macroshotapp@gmail.com**.\n\nFor security issues, please use GitHub's **Private Vulnerability Reporting** (Security tab → Report a vulnerability) - see [SECURITY.md](SECURITY.md).\n\n## License\n\n[FSL-1.1-Apache-2.0](LICENSE.md) - Functional Source License, converting to Apache 2.0 after 2 years.\n\n## Citation\n\n```bibtex\n@software{topiwala2026macroshot,\n  author = {Topiwala, Anirudh},\n  title  = {MacroShot: AI-Powered Meal Macro Tracker},\n  year   = {2026},\n  url    = {https://github.com/anirudhtopiwala/macroshot}\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanirudhtopiwala%2Fmacroshot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanirudhtopiwala%2Fmacroshot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanirudhtopiwala%2Fmacroshot/lists"}