Gumiplan
In ProgressAI-powered nutrition with an agentic coach.
The Problem
Generic meal plans ignore your preferences, schedule, budget, and dietary needs. People give up on nutrition plans because they feel like they were made for someone else. Because they were.
The Solution
A personalized nutrition platform that calculates real nutritional requirements (TDEE = BMR x activity multiplier, macro splits) and generates weekly meal plans using AI. But the real feature is the coach.
The Agentic Coach
Most nutrition apps have a chatbot that answers questions. Gumiplan has an agent that takes action. Built on LangGraph, the coach is a state machine that reasons about user intent, decides which tools to invoke (modify meal plans, suggest ingredient swaps, log meals, send notifications), and streams responses in real-time over WebSocket. It maintains conversation history and action logs, so it knows what it already changed and why.
Meal Plan Generation Pipeline
The system calculates personalized requirements based on user profile data: age, weight, height, activity level, goals. It generates structured JSON prompts for Google Gemini, normalizes the response into meals with macros, stores everything in PostgreSQL, and auto-generates shopping lists grouped by category. Partner meal planning lets couples share plans and shopping lists.
Architecture
Monorepo (pnpm + Turborepo) with three workspaces: a React Native mobile app (Expo 55, NativeWind, TanStack Query, Zustand), an Express API (TypeScript, Drizzle ORM), and a shared package with all types, enums, and Zod schemas. Zero contract drift between mobile and API because they share the same source of truth.
Preview
Screenshots coming soon
Screenshots coming soon
Key Technical Decisions
LangGraph over simple prompt chains
The coach needs to decide between multiple tools based on context, maintain state across turns, and handle failures gracefully. A linear prompt chain can't do that. LangGraph gives us a proper state machine with branching, tool dispatch, and retry logic.
WebSocket for coach streaming
HTTP polling or SSE would work for text, but the coach needs to stream text while simultaneously executing tool calls (modifying the database). WebSocket lets us interleave streamed response chunks with action confirmations in the same connection.
Shared Zod schemas in monorepo
API validation and mobile type safety come from the same Zod schemas. When a field changes in the shared package, TypeScript catches every consumer that needs updating at build time, not in production.
Zustand with AsyncStorage hydration
React Native apps crash (EXC_BAD_ACCESS) when stores try to rehydrate after long background periods. We use JIT rehydration: stores only hydrate when the app resumes, not eagerly on mount.