"Your week of food, figured out."
FuelRx is a planning-first convenience app that takes the mental load out of eating well. We help CrossFit athletes answer one question each week: "What should I buy and cook to fuel my training?" — with AI-generated plans refined by a community of real athletes sharing what actually works.
Then, if you want to track, we make it stupidly easy. No manual entry, no searching databases — just confirm what you already planned to eat.
- FuelRx
- 📑 Table of Contents
- Core Philosophy
- The Core Loop
- The Pitch
- Overview
- Features
- Tech Stack
- Getting Started
- Developer Tips
- Native App
- Project Structure
- Deployment
- Features
- Feature Roadmap
- What We're NOT Building
- Success Metrics
- Contributing
- License
- Contact
- Plan first, track second — Weekly planning is the foundation; tracking is optional convenience
- Convenience over compliance — Make healthy eating the path of least resistance
- No manual entry hell — FuelRx already knows what you planned; one tap to confirm you ate it
- Community as cookbook — Other athletes' real meals make your planning easier
- Guilt-free defaults — Generate, shop, eat. Track only if it helps you.
Generate Plan → Shop → Prep → Eat → [Optional: One-Tap Track] → Repeat
Every feature should make this loop faster, easier, or more enjoyable.
FuelRx gives CrossFit athletes a meal plan, a grocery list, and a prep game plan — powered by AI and refined by a community of athletes who eat like you.
If you want to track your macros, we already know what you planned to eat. One tap confirms it. No manual entry, no friction, no guilt.
FuelRx helps CrossFit athletes take the guesswork out of nutrition. Answer a few questions about your macro targets and preferences, and get a full week of meal plans designed to fuel your training—complete with recipes, macro breakdowns, and grocery lists.
Built for athletes who know nutrition matters but struggle with meal planning and prep due to time constraints or decision fatigue.
- Personalized Macro Targeting: Input your specific protein, carb, fat, and calorie goals
- AI-Generated Meal Plans: Weekly meal plans created using Claude AI based on your preferences
- Dietary Flexibility: Support for various dietary preferences ("No restrictions", "Paleo", "Vegetarian", "Gluten-free" and "Dairy-free")
- Only Healthy Meals: Only recommends/generates healthy and non-processed or minimally processed foods for users
- Prep Time Optimization: Meals tailored to your available prep time (options: 5min, 15min, 30min, 45min, 60min)
- Auto-Generated Grocery Lists: Shop efficiently with categorized ingredient lists
- WOD-Aware Nutrition (planned): Adjust meals based on workout intensity
- Next.js - React framework with server-side rendering, routing, and optimized deployment
- React - Component-based UI library
- Tailwind CSS - Utility-first CSS framework for styling
- TypeScript - Type-safe JavaScript for better developer experience
- Supabase (Free Tier)
- PostgreSQL database (500MB storage)
- Built-in authentication
- Row Level Security (RLS) for data protection
- Real-time subscriptions
- 1GB file storage, 2GB bandwidth/month
- Claude API (Anthropic)
- Generates personalized meal plans
- Pay-as-you-go pricing (~$3 per million input tokens)
- Powered by Claude Sonnet for optimal cost/performance
- Vercel (Free Tier)
- Automatic deployments from Git
- Edge network for fast global delivery
- 100GB bandwidth/month
- Built-in CI/CD
- Node.js 18+ and npm/yarn
- Supabase account
- Anthropic API key for Claude
- Vercel account (for deployment)
Create a .env file in the root directory and add the following environment variables (except the INNGEST ones).
Add these environment variables in Vercel Project Settings > Environment Variables:
| Variable | Description | Where to Get It |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Supabase project URL | Supabase Dashboard > Settings > API |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Supabase anon/public key | Supabase Dashboard > Settings > API |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role key (server-only) | Supabase Dashboard > Settings > API |
ANTHROPIC_API_KEY |
Claude API key | https://console.anthropic.com |
INNGEST_EVENT_KEY |
Inngest event key | Inngest Dashboard > App Settings |
INNGEST_SIGNING_KEY |
Inngest signing key | Inngest Dashboard > App Settings |
# Clone the repository
git clone https://github.com/sarahdorich/fuel-rx.git
cd fuel-rx
# Install dependencies
npm install
# Run development server
npm run devOpen http://localhost:3000 to view the app.
Run the SQL migrations in your Supabase project (see /supabase/migrations folder).
For local development, we use the Supabase CLI.
Install the supabase cli:
brew install supabase/tap/supabase
brew upgrade supabaseInitialize supabase:
supabase initLogin to supabase:
supabase loginLink your project:
supabase link --project-ref <supabase_project_id>Install Docker Desktop.
Check migration status with:
supabase migration list --linkedPull existing schema from supabase:
supabase db pullIf you get errors from above, it's because you ran some migrations manually. To tell supabase these migrations have already been applied, just run the following for each migration file:
supabase migration repair --status applied 0001List migrations that have been applied:
supabase migration listStart you local supabase:
supabase startYou can always run the following to retrieve local supabase credentials:
supabase statusUse the keys that get outputted to update .env.development.local as well as .env.
Go to this URL to access your local supabase: http://127.0.0.1:54323
Run this to start the application using your local setup: npm run dev
You can view your local supabase instance here: http://127.0.0.1:54333/
To add a new migration file:
supabase migration new <description>To run new migrations locally:
supabase migration upTo totally reset (recreate) your local database, run this:
supabase db resetInngest handles background jobs (meal plan generation) in production:
- Create Inngest Account: Sign up at https://app.inngest.com
- Connect to Vercel:
- In Inngest dashboard, go to Settings > Integrations
- Click "Connect to Vercel" and authorize
- Select your FuelRx project
- Sync Your App:
- After deploying to Vercel, Inngest automatically discovers your
/api/inngestendpoint - Your functions appear in the Inngest dashboard
- After deploying to Vercel, Inngest automatically discovers your
- Get API Keys:
- Go to Inngest Dashboard > Your App > Settings
- Copy
Event KeyandSigning Key - Add them to Vercel environment variables (see table above)
- Redeploy: Trigger a new Vercel deployment to pick up the new env vars
You should just be able to start Next.js then in another terminal, start Inngest locally.
-
npm run dev -
npx inngest-cli@latest dev -u http://localhost:3000/api/inngest --no-discovery
FuelRx sends email notifications when meal plan generation completes, so users can close the browser and come back later. We use Resend for email delivery.
-
Create Resend Account: Sign up at https://resend.com (free tier: 3,000 emails/month)
-
Get API Key:
- Go to Resend Dashboard > API Keys
- Create a new API key
- Copy the key (starts with
re_)
-
Verify Sending Domain (for production):
- Go to Resend Dashboard > Domains
- Add your domain and follow DNS verification steps
- For development, you can use Resend's test domain (
onboarding@resend.dev)
-
Add Environment Variables:
# .env or .env.local RESEND_API_KEY=re_xxxxx RESEND_FROM_EMAIL=notifications@yourdomain.com NEXT_PUBLIC_APP_URL=https://your-app-url.com -
Add to Vercel (for production):
- Go to Vercel Project Settings > Environment Variables
- Add the same variables above
- When a meal plan finishes generating, the Inngest function sends an email via
src/lib/email/resend.ts - If
RESEND_API_KEYis not configured, emails are silently skipped (no errors) - Email includes a direct link to view the completed meal plan
Without Resend configured, you'll see this in the console:
[Email] Skipping email - RESEND_API_KEY not configured
To test actual email delivery locally, add your Resend API key to .env.local.
Sometimes Next.js dev server experiences cache issues. If you all of a sudden start encountering many errors, follow these steps:
- Stop the dev server
- Run
rm -rf .next - Run
npm run devagain
Make sure you install xcode from the Apple App Store.
Testing Guide: docs/MOBILE_TESTING.md
# 1. Build for mobile
npm run build:mobile
# 2. Open Xcode
npm run cap:open:ios
# OR npx cap open ios
# 3. In Xcode:
# - Select "iPhone 15 Pro" simulator
# - Press ⌘R to build and runRunning with local development server
Get your local ip address:
ipconfig getifaddr en0Then set the environment variable and sync:
CAPACITOR_SERVER_URL=http://<ip_address>:3000 npx cap sync ios
# Example: CAPACITOR_SERVER_URL=http://192.168.86.249:3000 npx cap sync iosNow, start your Next.js dev server and point Capacitor to it.
Build the Next.js app (creates the 'out' directory):
npm run buildStart the dev server:
npm run devSync to ios:
npx cap sync iosThen in Xcode:
- Clean the build (Product → Clean Build Folder, or ⌘+Shift+K)
- Rebuild and run the app (⌘+R)
Make sure you install Android Studio.
# 1. Build for mobile
npm run build:mobile android
# 2. Open Android Studio
npm run cap:open:android
# OR npx cap open android
# 3. In Android Studio:
# - Wait for Gradle sync to complete
# - Select a device/emulator
# - Press the Run buttonRunning with local development server
Get your local ip address:
# macOS
ipconfig getifaddr en0
# Linux
hostname -I | awk '{print $1}'Then set the environment variable and sync:
CAPACITOR_SERVER_URL=http://<ip_address>:3000 npx cap sync androidThen in Android Studio:
- Clean the build (Build > Clean Project)
- Rebuild and run the app
After generating the base icon, use Android Studio's Image Asset Studio:
- Right-click
android/app/src/main/res> New > Image Asset - Select your 1024x1024 source icon
- Configure foreground and background layers
- Generate all density variants automatically
We have a couple scripts to help generate app icons:
- scripts/generate-app-icons.sh: Generates all required icon sizes from a source image
- scripts/create-placeholder-icon.sh: Creates a simple placeholder icon for testing
To use:
Make sure you install ImageMagick: brew install imagemagick
# Option 1: Create a placeholder icon for testing
./scripts/create-placeholder-icon.sh
./scripts/generate-app-icons.sh scripts/assets/app-icon-source.png
# Option 2: Use your own 1024x1024 icon
./scripts/generate-app-icons.sh path/to/your-icon.pngapp-store/metadata.md contains:
- App name, subtitle, description
- Keywords for discoverability
- Categories and age rating
- Screenshot requirements
- Review notes for Apple
Required Screenshot Sizes for App Store
- 6.5" Display (1284 x 2778): iPhone 14 Plus, iPhone 13 Pro Max, iPhone 12 Pro Max, iPhone 11 Pro Max
- 6.5" Display (1242 x 2688): iPhone XS Max, iPhone 11 Pro Max
- 12.9" iPad Display (2048 x 2732): iPad Pro 12.9"
How to Take Screenshots in Xcode Simulator
- Open Xcode and go to Window → Devices and Simulators
- Launch iPhone 11 Pro Max or iPhone 14 Plus simulator for 6.5" screenshots
- Run your app in the simulator
- Take screenshot: Press
Cmd + Sin the Simulator, or go to File → Save Screen - Screenshots save to Desktop by default
Quick Simulator Commands
# List available simulators
xcrun simctl list devices
# Boot specific devices for App Store screenshots
xcrun simctl boot "iPhone 11 Pro Max"
xcrun simctl boot "iPad Pro (12.9-inch) (6th generation)"Tips
- Make sure the simulator is set to 100% scale (Window → Physical Size or
Cmd + 1) - Take screenshots in portrait orientation for the main set
- You need at least 3 screenshots per device size, up to 10
Privacy Policy: /privacy
Terms of Service: /terms
Support: /support
- Create your app icon (1024x1024 PNG, no transparency)
- Generate icon sizes:
./scripts/generate-app-icons.sh your-icon.png - Take screenshots on iPhone 15 Pro Max and iPad Pro
- Test on physical device (camera, haptics, push notifications)
- Beta test via TestFlight
- Submit for review via App Store Connect
- Build for mobile
npm run build:mobile- Open Xcode
npm run cap:open:ios- In Xcode:
- Select your target device as "Any iOS Device (arm64)"
- Increment the build number in your project settings (required for each TestFlight upload)
- Go to Product → Archive
- After archive completes:
- The Organizer window opens automatically
- Click Distribute App
- Select App Store Connect → Next
- Select Upload → Next
- Keep default options → Next
- Select your signing certificate → Upload
- In App Store Connect:
- Wait a few minutes for processing
- Go to your app → TestFlight tab
- The new build appears under "iOS Builds"
- Add it to your testing group(s) if not automatic
- Your testers will get notified of the new build once it's processed (usually 10-30 minutes).
To ensure my personal Anthropic bill doesn't get out of control, we've implemented a paywall. The following table outlines the different plans available to users.
| User Type | Free Plans Left | AI Features | Meal Plan Generation |
|---|---|---|---|
| Free user | 3, 2, or 1 | ✅ Yes | ✅ Yes |
| Free user | 0 | ❌ Paywall | ❌ Paywall |
| Basic subscriber | N/A | ✅ Yes | ❌ Paywall (uses free plans) |
| Pro subscriber | N/A | ✅ Unlimited | ✅ 3/week |
| Override (VIP) | N/A | ✅ Unlimited | ✅ 3/week |
AI Features include: Cooking Assistant, Snap-a-Meal photo analysis, Quick Cook meal generation, and Prep Mode generation. These are unlimited for Pro/VIP users.
Meal Plan Generation: Pro and VIP users can generate up to 3 meal plans per rolling 7-day window. See ADMIN_README.md for admin override options.
- App Store Connect (iOS)
- Go to App Store Connect → Your App → Subscriptions
- You can either:
- Edit existing price: Apple will notify existing subscribers and give them a chance to opt-out
- Create a new subscription tier: Existing subscribers keep their price, new subscribers pay more
- Apple requires you to notify users of price increases (they handle this automatically)
- Google Play Console (Android)
- Go to Google Play Console → Your App → Monetization → Subscriptions
- Edit the subscription price or create a new base plan
- Google also handles notifying existing subscribers
- RevenueCat
- RevenueCat pulls pricing from the app stores, so you don't need to change anything in RevenueCat itself
- Your products configuration references product IDs, not prices, so no code changes needed
- Prices will automatically reflect what's set in the app stores
- Important Considerations
- Existing subscribers: Both Apple and Google have policies about grandfathering existing subscribers or requiring consent for price increases
- Regional pricing: You may want to adjust prices across all regions
- Testing: After changing prices, test the purchase flow in sandbox/test mode
fuel-rx/
├── app/ # Next.js app directory
│ ├── page.tsx # Home page
│ ├── onboarding/ # User onboarding flow
│ ├── meal-plan/ # Meal plan display
│ └── grocery-list/ # Shopping list
├── components/ # Reusable React components
├── lib/ # Utility functions
│ ├── supabase.ts # Supabase client
│ ├── claude.ts # Claude API integration
│ └── types.ts # TypeScript types
├── public/ # Static assets
├── supabase/ # Database migrations
└── styles/ # Global styles
- Push your code to GitHub
- Import project in Vercel dashboard
- Add environment variables in Vercel project settings
- Deploy automatically on push to main branch
# Or use Vercel CLI
npm install -g vercel
vercelTo make FuelRx a one-stop shop, you can log what you actually eat in the app. There are a few ways to log.
- Add ingredients manually
- Barcode scanning
- Snap a picture
The barcode scanning feature allows users to quickly add food items by scanning product barcodes.
Scanner UI
Uses the ZXing library for real-time barcode detection via the device camera. Supports EAN-13, EAN-8, UPC-A, UPC-E, CODE-128, and CODE-39 formats. Includes a manual entry fallback when camera access is unavailable.
Lookup Process
Uses a tiered fallback strategy: Database lookup (fastest) → Open Food Facts API → FatSecret API → Not found. The database is checked first to avoid repeated external API calls for the same product.
Results Display
When a barcode is found, displays the product image, name, brand, and nutrition info (calories, protein, carbs, fat). Users can "Scan Again" or "Add & Log" the item.
Database Storage
When saved, creates an ingredient with is_user_added: true and stores nutrition with source: 'barcode_scan'. The barcode is persisted for future lookups.
The Snap a Picture feature lets users photograph their meals for AI-powered nutritional analysis.
How It Works
Users take a photo or select from their gallery. The image is compressed client-side (1200x1200 max, 80% quality JPEG) to reduce storage and bandwidth, then uploaded to a private Supabase Storage bucket. The API generates signed URLs for secure, time-limited access to photos.
AI Analysis
Photos are analyzed using Claude Sonnet 4 (claude-sonnet-4-20250514) with vision capabilities. The model identifies individual ingredients, estimates portion sizes based on visual cues (plate size, utensils), and calculates macros using USDA FoodData Central guidelines. Portion estimates are calibrated for CrossFit athletes (4-8oz protein servings, 1-2 cups vegetables). Each ingredient receives a confidence score (0-1) indicating how certain the model is about the identification.
Review and Save
After analysis, users review the AI-generated results and can edit meal names, adjust ingredient quantities, or add/remove items. The meal can be logged to daily consumption, saved to the My Meals library, or both.
Extended Meal Memory
- Track meal names from the last 3-4 weeks (not just 1 week)
- Pass to LLM as exclusion list to prevent repetition
- Solves: "FuelRx keeps suggesting the same meals"
Variety Anchors in Prompts
- Instruct LLM to use 3+ different protein sources per week
- Require 2+ cuisine styles (Mediterranean, Asian, Mexican, etc.)
- Add seasonal hints based on current month
Ingredient-Efficient Meal Generation
- New user preference: "Optimize for simpler shopping"
- When enabled, LLM designs meals around shared anchor ingredients:
- 2-3 core proteins (chicken breast, ground beef, salmon)
- 4-5 versatile vegetables (broccoli, bell peppers, spinach, sweet potatoes)
- Meals vary in preparation but share base ingredients
- Solves: "The grocery list is too long"
Leftover Intelligence
- LLM considers multi-serving meals when planning
- "Tuesday's grilled chicken makes Wednesday's lunch salad"
- Reduces cooking sessions and waste
WOD-Meal Pairing
- User inputs weekly training schedule (no gym app integration needed but could be cool to integrate with PushPress's API)
- For each day: workout type (rest, light, moderate, heavy, intense) and time (morning, midday, evening)
- LLM adjusts meals based on training:
- Rest days: Lower carbs, anti-inflammatory foods
- Heavy/strength days: Higher protein emphasis
- Intense days: Prioritize carbs, especially around workout
- Meal timing adapts to workout time:
- Morning WOD → lighter breakfast, substantial post-workout meal
- Evening WOD → lunch as pre-fuel, dinner focused on recovery
- Start with manual input; gym app integration (PushPress, etc.) possible later
- Differentiator: No other meal app does this well for CrossFit
Meal Prep Mode
- Transform 21 separate meals into a structured prep plan
- "Sunday Prep Session" view showing:
- What to batch cook
- Estimated total time
- Which meals each prep item feeds
- Daily view shows assembly only, not full cooking
- High-impact differentiator
Quick Swap
- One tap on any meal shows 3 alternatives with similar macros
- No regenerating the whole plan
- Keeps plans flexible when life changes
Ingredient Substitution
- "Out of salmon?" → "Swap for cod, chicken thigh, or canned tuna"
- Prevents missing ingredients from derailing the plan
- LLM-powered, feels like magic
Costco Mode
- Leverage your inventory scraper
- "Optimize my plan for what's available at Costco"
- Match meals to actual products at user's local warehouse
- Nobody else does this — genuine differentiator
One-Click Grocery Export
- Export to Instacart, Amazon Fresh, Walmart
- Or clean shareable list for texting
- Fewer steps between plan and groceries in kitchen
The Flow
- User takes photo of a meal they made
- Claude Vision analyzes and identifies:
- Suggested meal name
- Visible ingredients with estimated portions
- Estimated macros
- User reviews, tweaks if needed, saves
- Optional: Share with community
Smart Matching
- After analysis, search existing database for similar meals
- "This looks like Community Member's Teriyaki Bowl — use those verified macros?"
- Turns photo into search tool, not just estimation
Low-Friction Capture
- "Meal Memory" — snap without committing
- Review at week's end: "Add any of these to saved meals?"
- Builds personal cookbook over time with zero effort
One-Tap Logging
- FuelRx already knows what you planned to eat
- Meal card shows: "Did you eat this? ✓"
- One tap = logged with accurate macros
- No searching, no manual entry, no friction
Smart Adjustments
- "Ate this but only 75% of it" → Adjust portions
- "Swapped chicken for salmon" → Update protein source
- Still one tap, just with minor tweaks
Historical Trends
- Natural side effect of one-tap logging
- See weekly/monthly macro adherence
- "You hit your protein target 6/7 days this week"
- Charts show trends, not daily guilt
MyFitnessPal Migration
- One-time import of historical data
- Brings over past macro trends so you don't lose history
- Discontinue MFP entirely, track in FuelRx going forward
- Framing: "Stop manually logging. FuelRx already knows your meals."
Guiding Principle: Community as a smart recipe database, not a social network. Users benefit from collective wisdom without social pressure.
Passive Quality Signals
- Track when users keep vs. swap meals (no explicit rating needed)
- Powers "Most-kept meals" and "Fan favorites"
- Quality emerges from usage, not voting
Taste Twins
- Match users with similar macros, dietary prefs, and swap patterns
- "Athletes like you loved these meals"
- No following required — quiet algorithmic matching
Browse by Problem
- Replace endless feed with practical search:
- "I have 20 minutes"
- "I need to use chicken thighs"
- "Big batch Sunday prep"
- "Eating same lunch all week"
- "Something different"
- Community feels like organized cookbook
One-Tap Plan Integration
- "Add to Next Week" — slot community meal into your plan
- AI rebalances macros and updates grocery list automatically
- "Replace All My Breakfasts" — lock in a community meal as default
- "Steal This Week" — clone another athlete's full plan as starting point
Curated Collections
- "Coach Hill's Favorites" — permanent collection adding personality
- Guest collections from coaches or respected athletes
- "FuelRx Verified" badge for macro-accurate community favorites
Contribution Without Pressure
- "Your meal helped 43 athletes this week" — warm feedback
- Recipe remixes saved when users tweak community meals
- Contributing feels rewarding but is never required
| Phase | Features | Impact | Rationale |
|---|---|---|---|
| 1 | Extended meal memory, Ingredient-efficient generation | Fix current pain points | Quality must be solid before adding features |
| 2 | One-tap tracking, MFP migration | Reduce friction vs. competitors | Keep users from needing two apps |
| 3 | Meal Prep Mode | Major differentiator | CrossFit athletes batch cook on Sundays |
| 4 | Quick Swap, Ingredient Substitution | Daily convenience | Life happens, plans change |
| 5 | Snap a Meal (photo capture) | Frictionless meal saving | Build library passively |
| 6 | Browse by Problem, One-tap plan integration | Community becomes useful | Network effects kick in |
| 7 | Costco Mode, Grocery export | Shopping convenience | Final polish on the core loop |
| 8 | Passive quality signals, Taste Twins | Smart recommendations | Data-driven improvements |
We avoid features that create guilt, friction, or daily obligation:
- Mandatory daily logging — Tracking is optional convenience, not required
- Streak tracking or gamification — No guilt for missing days
- Manual calorie counting — If it's not one-tap easy, we don't do it
- Social feeds requiring engagement — Community without pressure
- Manual ingredient searches — FuelRx already knows what's in your meals
- Daily app opens as requirement — Open weekly to plan, optionally daily to track
The test: Does this feature make the "Generate → Shop → Prep → Eat → Repeat" loop easier? If no, we don't build it.
Planning metrics (primary):
- Weekly active plan generation — Users creating meal plans
- Grocery list exports — Plans converting to shopping
- Swap rate — Lower = better meal quality
- Community meal additions — Plans enriched by community
- Time to plan — Getting faster over time
Tracking metrics (secondary, only for users who opt in):
- One-tap log rate — % of planned meals confirmed with single tap
- Manual entry rate — Should be near zero (if high, we failed at convenience)
- Tracking adherence — Users who start tracking and keep doing it
- MFP churn — Users who discontinue MFP after migrating to FuelRx
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details
For questions or feedback, please open an issue on GitHub.
Built with ❤️ for athletes who'd rather lift than meal plan.