Inspiration
Two things kept bothering me about recipe apps.
The first is that the interesting constraint is almost always money, and no app treats it as a first-class input. You can filter by cuisine, diet and cooking time, but not by "under eight euros for two people". Apps show you ingredients and steps. Almost none of them tell you what dinner actually costs.
The second is that they want an account, put your recipes in their cloud, and pay for the free tier with advertising.
I wanted the opposite of both.
What it does
You describe a meal in one plain sentence: what you feel like eating, what is already in the fridge, how many people you are cooking for, what you want to spend. No filters, no wizard.
What comes back is a complete recipe where every ingredient carries an estimated price, adding up to a total and a cost per person, shown before you go shopping. Paid plans add per-serving calories and macronutrients.
Recipes are saved in SwiftData on the device. Analytics only start after an explicit opt-in, and prompts, recipes and email addresses are excluded from them entirely. No plan contains advertising, including the free one.
It is localised into eight languages, and not only the interface. The app passes its preferred language to the backend, which instructs the model to return the recipe itself in that language, so a German user gets German ingredients and German steps.
How I built it
- SwiftUI and SwiftData, local-first, iOS 18.6 and up
- A Supabase Edge Function as the authenticated gateway, so the app never holds a provider key
- OpenRouter with a pinned model, identical for every plan. There is no deliberately worse model for free users; plans differ in quota and features
- RevenueCat for subscriptions, entitlements, restore and webhook reconciliation, with server-side entitlement checks before quota reservation
- Sign in with Apple, Google, or a six-digit email code
- Home and Lock Screen widgets, voice input via Apple's Speech framework, an offline generation queue, and cooking reminders as local notifications rather than push
Challenges I ran into
The nutrition numbers were quietly wrong.
If you ask a language model how many calories a recipe has, the answer comes back systematically low. Measured against USDA reference data, a single-step estimate ran roughly 30% under. That is not a rounding error. That is a number you should not show anyone.
So MealWise never asks for a recipe total or a per-serving total. It asks the model to fill grams, calories, protein, carbohydrates and fat for each individual ingredient. The server sums those and divides by the serving count. Same recipe, same model: within 3%.
Each ingredient then passes physical checks. Its macronutrients cannot outweigh the ingredient itself. Its energy cannot exceed the 9.2 kcal/g ceiling of pure fat. A calorie figure that contradicts its own macronutrients by more than 15% plus 25 kcal is replaced by the Atwater value. If any single ingredient lacks usable values, the whole estimate is dropped rather than quietly understating the dish. A failed estimate never fails the generation, so it can never cost a quota unit or break a working recipe.
Trusting the client would have been expensive.
Refinement and regeneration are Pro features. Gating them in the UI is not enough: the Edge Function independently verifies the RevenueCat-derived entitlement before reserving quota or calling the provider, so a modified client receives 403 without consuming provider cost.
A paywall shown too early costs trust.
The subscription offer only appears after someone has completed their first real recipe and been shown how to refine it, and it has a visible close control. A free user can dismiss it and keep using the app.
Accomplishments that I'm proud of
Getting the estimates honest rather than impressive. It would have been easier to print whatever the model returned. Dropping an entire nutrition estimate because one ingredient lacks usable values feels wrong right up until you realise the alternative is telling someone their dinner has 30% fewer calories than it does.
Also: eight languages as one person, including the generated content and not just the chrome.
What I learned
That the interesting engineering in an AI app is rarely the prompt. It is everything around it: what you refuse to display, what you verify server-side, and what you do when the model returns something plausible but wrong.
And that the differentiator was never "AI recipes" — that category is full. It was the price.
What's next for MealWise
Meal planning and shopping lists are the obvious next step, since the cost data already exists per ingredient. Opt-in cloud sync for Pro is built but deliberately limited to closed testing until its retention lifecycle and privacy notice pass review.
Honest limitations
Prices are planning estimates, not live supermarket data. Nutrition figures are estimates and not dietary, allergy or medical advice. AI-generated recipes need checking before you cook them, especially for allergens and food safety. All three are stated in the app rather than buried in a settings screen.
Built With
- aptabase
- avfoundation
- cloudflare-turnstile
- deepseek
- edge-functions
- google-sign-in
- ios
- netlify
- openrouter
- postgresql
- posthog
- resend
- revenuecat
- sign-in-with-apple
- speech-framework
- storekit
- supabase
- swift
- swiftdata
- swiftui
- turso
- widgetkit
Log in or sign up for Devpost to join the conversation.