Skip to content
Selected work

Case study

Meal42: an AI recipe product, shipped solo, live on both stores

Meal42 generates recipes from a photo or a list of what you have, in the language and cuisine you want. Taken from a one-page brief to the App Store and Google Play in five months by one engineer, with generative features that hold up in production.

Role
Product, design, engineering, release, operations
Platform
iOS + Android (React Native), web admin
Stack
React Native · Node/TypeScript · Cloud Functions · Firestore · Firebase Auth · Next.js · Gemini · RevenueCat
Period
5 months to both stores

Context

Home cooks wanted recipes that fit what they already had and how they like to eat, not a search box over a static database. Meal42 generates recipes, understands photos of ingredients, and guides the cook step by step.

There was no team. One person owned the product decisions, the apps, the backend, the admin tooling, the store listings and everything that happened after launch.

My role

  • Defined the first version worth shipping and what was cut.
  • Built the React Native apps for iOS and Android, the Node/TypeScript backend on Google Cloud Functions, the Next.js admin panel, and the automation around push and releases.
  • Designed the generative pipeline and the guardrails around it, then operated the product after launch.

Constraints

  • One engineer, part-time hours, a fixed personal budget for inference and infrastructure.
  • Generative output had to be safe to display without a human in the loop: no malformed recipes, no runaway costs, no silent failures.
  • Both stores from day one, with twelve languages, in-app purchases and the review requirements that come with them.

Key decisions

  1. Decision 1

    Structured output with validation, retries and a fallback path

    Every model response is parsed against a schema; invalid responses are retried with a corrective prompt, and a deterministic fallback serves a usable result if the model still fails. The cost is extra latency and prompt complexity on the unhappy path; the gain is that the UI never renders a broken recipe.

  2. Decision 2

    Cost caps, rate limiting and idempotency caching at the API edge

    Per-user rate limits, a daily spend cap and a cache keyed on request content mean a user tapping twice, or a retry storm, never doubles the bill. The trade-off is slightly stale results for identical requests, which is acceptable for recipe generation.

  3. Decision 3

    React Native with a thin native surface

    One codebase for both stores was the only way to ship in five months alone. Camera, purchases and notifications go through well-maintained native modules rather than custom bridges, which limited some polish in exchange for speed and stability.

What I built

  • React Native iOS and Android apps with Firebase Auth, a Firestore data model, and localisation in twelve languages.
  • Node/TypeScript backend on Google Cloud Functions: generation endpoints, image understanding, validation, retries, fallbacks, cost caps, rate limiting, idempotency caching and structured logging.
  • Next.js admin panel for content, users and moderation; automated push campaigns.
  • Firebase image-resize extension so the client never downloads originals, cutting storage and bandwidth.
  • In-app purchases through RevenueCat; Analytics and Crashlytics wired from the first build.
  • AI coding agents did the scaffolding, tests and refactors under skill files and hooks I wrote. I reviewed every change before it merged.
React Native appiOS + AndroidFirebase AuthidentityCloud Functions APINode/TypeScriptGuardrailsrate limit · cost cap · cacheGeminigeneration · visionSchema validationretry · fallbackFirestorerecipes · usersNext.js admincontent · pushStructured logsAnalytics · Crashlytics
Request path for a generation: the client never talks to the model directly, and every response passes validation before it reaches the UI.

Validation

  • Unit tests around the validation layer and the fallback path, run on every change.
  • A corpus of real ingredient photos and prompts replayed against the pipeline before each release to catch regressions in output quality and cost.
  • TestFlight and Play internal builds every week; store review passed on both platforms.

Release and operation

  • Phased rollout on both stores with Crashlytics watched for the first 48 hours of each release.
  • Daily cost and error dashboards from the structured logs; alerts on spend and failure rate.
  • Operated by one person: content updates through the admin panel, push campaigns automated, incidents handled from the logs.

What changed, and what I'd do next

  • Meal42 is live on the App Store and Google Play, five months from brief to both stores.observed
  • Operated end to end by one person after launch.observed
  • No malformed generation reaches the UI; failures degrade to a fallback result.design goal

Measured: a number from logs, analytics or a release pipeline. Observed: seen in production without a formal measurement. Design goal: what the system is built to guarantee.

What I'd do next

  • Move more of the validation corpus into automated evaluation so quality regressions are caught before a human notices.
  • Experiment with smaller models for the cheaper steps of the pipeline to reduce cost further.