Menuto
A full-stack AI dish recommendation app — solo-built end to end. Tell it your restaurants and taste preferences, it tells you what to order. Fully functional, deployed to TestFlight.
The Idea
Restaurant reviews tell you where to eat. Nothing tells you what to order — especially at a place you've never been. I wanted an app that knows your taste profile, browses the actual menu, and surfaces the right dishes for you specifically. So I built it, entirely solo: product vision, design, React Native frontend, FastAPI backend, database schema, LLM integration, and deployment.
I'm always indecisive about what to order at restaurants. So I solved my own problem.
The App
User Flow
Add up to 3 restaurants from Google Places (location-aware) → browse each restaurant's full menu, filtered by course (All / Starter / Main / Dessert), and save favorite dishes → open Choose Dish, confirm the restaurant and menu, then indicate preferences — how hungry you are, how much you want popular vs. personalized picks, and what you're craving (light, fresh, carb-heavy, protein-heavy, spicy, creamy, crispy, comforting) → AI loads your recommendations.
The AI Pipeline
Menu Parsing
The FastAPI backend accepts a menu image, URL, or raw text. Images go through Tesseract OCR; all inputs are structured by GPT-4o (vision) or GPT-4o-mini (text) into a typed JSON array: dish name, description, price, course category, ingredients, and dietary tags. The same `/upload-menu` endpoint handles all three input types via content-type detection. Low-confidence parses surface a user-correction flow rather than silently passing bad data downstream.
Cost Optimization
Initially used GPT-4 across all calls. After the first working build, I profiled the cost per request and systematically reduced it: switched text-based parsing to GPT-4o-mini, added max_tokens caps (300–1,500 depending on call type), and reduced the recommendation set from 8 to 5. Total cost reduction: 60–80% with no perceptible quality loss.
Engineering Decisions
Technical Highlights
- —Mixed navigation — state-machine for top-level transitions (sign-in → onboarding → main app), React Navigation tabs only for the inner My Restaurants / Choose Dish / Profile views.
- —Zustand state management — typed slices for user preferences, current menu session, and recommendation state; no prop-drilling across screens.
- —Location-aware restaurant search — debounced Google Places autocomplete (300ms) with GPS; graceful degradation to city-level if permission denied.
- —Supabase/PostgreSQL schema — user preference vectors, dish favorites per restaurant, and restaurant menu cache; structured so ratings and preferences update asynchronously.
- —Dual AI models — GPT-4o vision for photo menus (richer context needed), GPT-4o-mini for text/URL parsing (cost-efficient, output quality equivalent).