How I Redesigned a Meal Planning App UX: From Panel to Modern Food-First Design
Melio is an AI-powered meal planning app. It generates personalized nutrition plans, manages dietary profiles, builds shopping lists. Functionally it worked — but visually it looked like a back-office admin panel. Data tables, utilitarian headers, developer-facing layouts. Not the kind of interface you want open on your kitchen counter.
I decided to redesign the entire app UX using a research-driven approach. Here's how I did it across 47 routes without breaking a single feature.
Why Research-Driven UX Design Matters
Redesigning a product based on gut feeling leads to inconsistent results. Instead, I started with structured UX research before writing any code.
I studied competitor meal planning apps — Mealime, Eat This Much, and Whisk — to identify what design patterns work for food products. I documented findings with screenshots and stored everything in a research folder that became the foundation for every design decision.
How to Structure a Large-Scale App Redesign: The 9-Wave Approach
Redesigning a full-stack app with dozens of routes needs a deliberate sequence. I organized the work into 9 waves, each building on the previous — a method that keeps the codebase stable at every step.
Wave 1: Design Tokens and Color System
New design tokens set the visual direction — warm cream backgrounds (--background), deeper sage as the primary color, coral reserved exclusively for recommended actions.
Wave 2: Reusable UI Component Library
I built 13 reusable UI primitives using shadcn/ui: MealCard for visual meal display, MacroTile and MacroRing for nutrition data visualization.
Wave 3: App Shell and Navigation Redesign
The neon green header band became a minimal transparent 48px bar. Sidebar navigation consolidated from scattered links into 3 logical groups. This follows the UX principle of reducing navigation cognitive load — users shouldn't spend mental effort figuring out where things are.
Waves 4–5: Dashboard and Meal Plan Views
The dashboard shifted from a generic feature overview to a "Today's Meals" hero layout with an UpNext rail and library stats. This mirrors how Spotify surfaces "Made for You" content — lead with what's relevant right now.
Wave 6: Onboarding Wizard Simplification
The meal plan wizard was reduced from 4 steps to 3 with a dot progress indicator.
Wave 7: SaaS Pricing Page Design
Billing adopted a 3-tier pricing layout with the Pro tier visually emphasized using a coral badge and slightly larger card.
Results
145 files changed across the web-agent package. TypeScript type checker passes clean. Linter shows 2 minor warnings. Production build succeeds.
The app went from feeling like an internal tool to looking like a modern meal planning product. That transformation came from systematic research and established UX principles — studying what works in the industry and applying it methodically, wave by wave.

Oleksandr Yusypenko
Senior Full-Stack + AI Engineer. Building in public — AI agents, LangGraph, production systems.
Related Posts
Jul 5, 2026
Query-based CDC over WAL: keeping a CQRS Postgres → ClickHouse read model fresh
Query-based CDC vs log-based (WAL) for a CQRS Postgres→ClickHouse read model: watermark polling, ReplacingMergeTree, reconcile-by-key-diff, and freshness-lag alerts.
Jul 3, 2026
Two planes of quality: making meal-plan generation both evaluable and observable
How Melio's meal-plan pipeline splits quality into two planes — online validation and offline evaluation — plus the observability layer that makes them measure the same things, and the reasoning behind which metrics are allowed to block a deploy.
Jun 14, 2026
Hiding an Internal API the Right Way: Why a Proxy Isn't Security
Putting your API behind a proxy feels secure. It isn't — until the origin literally can't be reached any other way. A walk through the Cloudflare Tunnel + Access token + BFF pattern, and why "hiding the URL" is the part everyone gets wrong.
Building an AI Content Engine for a Gov Contracting Platform
NextThree boundaries, one source of truth: sharing types across Rust and TypeScript