Inspiration

I kept coming back to one specific frustration: every food app assumes the fix for "this meal won't hold me" is to log something, count something, or cut something out. None of that is actually the problem. The problem is usually just one missing thing — protein, fibre, or fat — and once you name it, the fix is obvious.

That additive framing is directly inspired by registered dietitian Abbey Sharp's "Hunger Crushing Combo" concept — the idea that a satisfying meal usually just needs one more compound added, not a subtraction or a rule. I'm not affiliated with her and don't use her trademarked name or framework directly; Staying Power is my own build of that same underlying idea, credited here because it's genuinely where the concept started for me.

What it does

You tell Staying Power what you're working with — by typing a food, picking a craving, picking a situation (gas station, airport, someone else's kitchen), or now, just taking a photo of it — and it gives you back:

  • A warm, judgment-free read of what's already there
  • What's missing in plain language — staying power, bulk, richness — never nutrient jargon
  • Exactly one or two things to add, each with a one-line reason and an effort tag (already have it / 30 seconds / needs a fridge)
  • A zero-prep fallback that always works
  • A reminder that eating it exactly as-is is completely fine too — that line is non-negotiable and appears on every result

It remembers dietary needs and allergies (so it never suggests something you can't eat) and the staples you keep on hand (so suggestions start from your actual kitchen). Save the combos that work — no dates, no streaks, just a shortlist.

What it will never do: show a calorie, a gram, a percentage, a score, or a streak. It only ever adds.

How we built it

  • Flutter, feature-first, with Riverpod for the small amount of state this app actually has.
  • combo_engine — a pure Dart package with zero Flutter dependency, runnable from the command line. It owns the prompt, the JSON response schema, and a banned-lexicon validator that every response is checked against twice (schema, then tone) before it ever reaches a screen — regardless of which LLM produced it.
  • RevenueCat (purchases_flutter + purchases_ui_flutter) gates the app: 3 free combos a day, then a remote-configured RevenueCat Paywall for the plus entitlement ($3.99/mo or $24.99/yr with a 7-day trial). The philosophy, the disclaimer, and allergy filtering are never paywalled — only the generation itself, past the free limit.
  • Firebase Cloud Functions front the LLM call so the real API key never ships inside the app binary — the client sends a system prompt and input, the function forwards it to OpenRouter (routing to Claude Haiku 4.5, which also handles the photo path natively as a vision model), and returns raw text. All validation happens client-side; the function is intentionally a thin, dumb proxy.
  • Hive for local-only storage — dietary needs, pantry staples, saved combos. Nothing is logged with a date or timestamp, on purpose: a log is exactly what this app refuses to be.

Challenges we ran into

The most unusual one: four days after opening public testing, a different app appeared on Google Play under the exact same name, with a suspiciously similar feature set (situational suggestions, pantry memory, a paid tier for saving combos). I initially assumed I had some trademark claim to lean on — turns out the legal reality was thinner than it felt: copyright protects specific text and code, not the underlying idea, and trademark priority runs on public use, which meant my few days of open testing didn't clearly outrank theirs. Rather than fight over the name, I renamed to Staying Power, pulled directly from the app's own copy rather than invented under pressure. It cost an afternoon and the app is better-named for it.

On the technical side, the harder problem was keeping the LLM's output from ever slipping into diet-culture language — "guilt-free," "clean," implied restriction — while still sounding warm instead of clinical. That's what the two-stage validator and its unit-tested banned-word list exist to catch, deterministically, every time, not just "usually."

Accomplishments that we're proud of

  • A validator suite with tests named for the exact rule they enforce (e.g. rejecting body-shaming language while still allowing "fat" as a legitimate nutrient term) — reviewable and demoable on its own, with no UI required.
  • A three-tier reliability pipeline (live generation → one retry → a precomputed fallback for common foods) so a network hiccup never surfaces as a dead end to the user.
  • Shipping photo input as a genuine second modality, not a gimmick — a picture goes straight to a vision-capable model through the same validated pipeline as typed text, with the photo never stored anywhere.

What we learned

That the hardest part of a "compassionate" nutrition app isn't the AI prompt — it's noticing every small design decision that could quietly reintroduce diet culture through the back door (a number here, a streak there, a "clean eating" adjective) and refusing all of them, consistently, under deadline pressure.

What's next for Staying Power

  • Expanding the precomputed common-foods cache toward its full target, so more requests resolve instantly and for free
  • A closer look at RevenueCat paywall A/B testing now that there's real usage data to test against

Built with

Flutter · Dart · RevenueCat · Firebase Cloud Functions · OpenRouter · Claude (Anthropic) · Hive · Riverpod

Built With

  • claude
  • dart
  • firebasecloudfunctions
  • flutter
  • hive
  • openrouter
  • revenuecat
  • riverpod
Share this project:

Updates

Submission history