Skip to content
Serhii Kuznetsov
All projects

09Mobile2026Solo — the app, and the backend it shares with the web

Cook Galaxy — Mobile App

The Expo app for Cook Galaxy: the same backend, the same account, in your hand at the stove.

Private repository

Cook Galaxy — Mobile App screenshot

The problem

Cook Galaxy is used in a kitchen, and nobody carries a laptop to the stove. But shipping a mobile app usually means a second product: a second API, a second set of business rules, and two codebases that drift apart until a feature exists in one and not the other. I wanted the app to be a second client, not a second product.

Decisions

  1. 01

    The backend did not get a mobile branch

    Every route accepts either the web session cookie or a mobile bearer token, resolved by the same helper. Nothing is implemented twice, and a feature shipped on the web is available in the app as soon as the screen exists — there is no 'mobile support' ticket per endpoint.

  2. 02

    The expensive work stays on the server

    Photo and link import send the image or URL to the API and get a parsed recipe back. The phone never talks to the AI provider, which keeps the key server-side, the cost gated by the same daily limits as the web, and the app small.

  3. 03

    Every screen has a state for when things go wrong

    All the list screens have a loading state, an empty state and an error state with a retry — plus pull-to-refresh. Half of them did not, and adding them was a deliberate pass rather than something bolted on after a bug report.

  4. 04

    The upload that broke on an SDK upgrade

    Expo SDK 57 routes global fetch through its own implementation, whose FormData converter rejects the classic React Native upload descriptor — the one every tutorial still shows. Photo upload broke silently on upgrade; the fix was to hand it a real file object from expo-file-system instead. The kind of failure you only find by running the thing on a device.

  5. 05

    Not every web interaction survives the port

    Reordering ingredients is drag-and-drop on the web. On a phone, inside a scrolling form, drag-and-drop fights the scroll and loses — so it became up and down buttons. The same feature, a different gesture, because the constraint is different.

What I measured

26

screens

every one with a test, including its error and retry states

743

tests

across 78 suites

1

backend

shared with the web app, route for route

0

duplicated business rules

limits, trials and subscriptions resolve server-side

Home: recipe of the day and categories
Recipe import from a link or a photo
Meal planner with a shopping list for the period
Recipe: AI nutrition estimate and a private note

Built with

  • Expo
  • React Native
  • TypeScript
  • RevenueCat
  • Jest