Theme
Get Moving Meals logo
Role Software Developer
Timeline June 2025 – Present
Built with C#, ASP.NET, Tailwind CSS, PostgreSQL
Status Live & Active

Live Metrics

84+
Active Users
Organic growth, no paid acquisition
168
Meal Plans Generated
~2 plans per user on average
17.3%
Completion Rate
29 plans fully completed by users

Data from production admin dashboard · Updated Feb 2026

The Problem

Meal planning is overwhelming. People struggle with what to cook, how to balance nutrition, and managing dietary restrictions — all while dealing with busy schedules. Existing solutions are often complicated or don't account for personal preferences.

The Approach

Engineered a production web application now serving 84+ users that generates personalized weekly meal plans in minutes. The system respects dietary restrictions, medication interactions, and calorie targets to create tailored recommendations. Users can swap meals with one tap and get auto-generated grocery lists — 168 plans generated and counting.

System Architecture

Three-tier architecture with a decoupled frontend, RESTful API layer, and relational database. Payment processing is isolated behind its own service boundary so a Stripe failure never blocks meal plan generation. Background workers handle grocery list aggregation and email delivery.

Client
Web Frontend
Responsive UI, preference forms, plan viewer, swap interface
↕ HTTPS
API
REST API Server
Auth, meal plan engine, recipe matching, grocery aggregation
Payments
Stripe Integration
Webhook listener, subscription management, invoice sync
Database
Relational DB
Users, plans, recipes, allergies, medication interactions
Workers
Background Jobs
Grocery list generation, email notifications, plan refresh

API Structure

RESTful API organized around resources. Each endpoint validates dietary constraints and medication conflicts before returning results. The swap endpoint re-runs the matching algorithm for a single slot without regenerating the full week.

Method Resource Purpose
POST plans / generate Generate personalized weekly meal plan based on user profile
PUT plans / swap Swap a single meal while respecting constraints
GET plans / grocery Auto-aggregated grocery list for the current plan
POST users / preferences Save dietary restrictions, allergies, medication data
GET recipes / detail Full recipe with nutrition facts and prep steps
POST payments / subscribe Create Stripe subscription via server-side checkout

Database Design

Designed around two core relationships: users → plans and plans → recipe slots. Allergies and medication interactions are stored as separate join tables so the plan generator can run exclusion queries without scanning recipe content. Recipes carry pre-computed nutrition data to avoid aggregation at read time.

Users
  • id UUID PK
  • email VARCHAR UNIQUE
  • dietary preference ENUM
  • calorie goal INT
  • payment ref VARCHAR
Meal Plans
  • id UUID PK
  • owner FK → Users
  • week start DATE
  • created TIMESTAMP
  • status ENUM
Recipes
  • id UUID PK
  • title VARCHAR
  • calories INT
  • protein FLOAT
  • prep time INT
  • ingredients JSON
Allergies
  • owner FK → Users
  • allergen VARCHAR
  • severity ENUM

Technical Decisions & Tradeoffs

Payment Isolation
Chose: Stripe webhooks behind a separate service boundary
Payment failures (network timeouts, card declines) must never break meal plan generation. Isolating Stripe behind its own service means the core app stays functional even during payment provider outages.
Alternative: Inline payment calls — simpler, but couples billing failures to UX.
Pre-computed Nutrition
Chose: Store nutrition per recipe, not per ingredient
Grocery lists and plan views both need calorie totals. Computing from ingredients on every request adds latency and complexity. Pre-computing at recipe creation means reads are instant.
Alternative: Compute on read — always accurate, but slower and more complex queries.
Medication Safety
Chose: Exclusion-based filtering, not AI recommendations
For medication-food interactions, false negatives are dangerous. Using a curated exclusion list (e.g., no grapefruit with statins) is deterministic and auditable — no ML black box for safety-critical data.
Alternative: LLM-powered suggestions — flexible, but not auditable for medical safety.
Swap vs Regenerate
Chose: Single-slot swap algorithm
When a user dislikes one meal, regenerating the entire week is wasteful and disorienting. The swap endpoint re-runs the matching algorithm for just that slot, respecting the same constraints, in under 200ms.
Alternative: Full regeneration — simpler logic, but destroys the user's existing plan.

Scaling & Performance

Designed for a growing user base with stateless API servers, connection pooling, and background job queues. Grocery list aggregation runs asynchronously so users don't wait for a slow reduce operation during plan generation.

<200ms
Meal Swap Response
Single-slot re-match without full plan regeneration
Async
Grocery Aggregation
Background worker deduplicates and groups ingredients
Stateless
API Layer
Horizontally scalable — no session state on server

What It Does

Weekly Plans
Smart Swaps
Auto Grocery Lists
Medication Safe
Secure Payments
Easy Recipes

What I Learned

Shipping a production system to 84+ real users changed how I think about engineering. Every decision — from isolating Stripe webhooks to pre-computing nutrition data — was driven by actual user behavior, not hypotheticals. Working directly with a client taught me that balancing requirements with technical constraints is where engineering maturity lives. The 17.3% completion rate is a metric I'm actively working to improve through UX refinements and smarter meal matching.

Next Project