Every calorie app I tried had the same problem: it let you set a target of 1,200 calories or lower and called it a plan. Some went lower. That's how people end up in the binge-starve cycle — you eat 800, your body fights back, you eat 4,000, you hate yourself, repeat.
So I built one that refuses.
What it does
ForkCount asks your height, weight, age, gender, and activity level. Then it calculates your BMR, your TDEE, and a target that keeps you above the BMR floor. If you try to set a target below that line, it won't let you.
The rest is a food diary, water tracker, weight log, exercise log, weekly meal plan generator, and a community feed. You type "200g chicken and 150g rice" and it parses the food.
Free. No card. No trial. No paywall. Signup is a username and password — no email required.
Stack
- React + Vite + TypeScript
- Firebase Firestore
- Firebase Auth
- GitHub Pages
- No backend
The hardest part: Firestore rejects undefined
The error was: Function setDoc() called with invalid data. Unsupported field value: undefined
Firestore refuses any document that contains an undefined value anywhere inside it. When it fails, it doesn't tell you which field. So if you're saving a nested object with 40 fields, you're searching for a needle in a haystack.
The fix was a recursive cleaner routed through every write:
function cleanForFirestore(obj) { if (Array.isArray(obj)) return obj.map(cleanForFirestore); if (obj instanceof Date) return obj; if (obj && typeof obj === 'object') { const out = {}; for (const k in obj) { if (obj[k] !== undefined) out[k] = cleanForFirestore(obj[k]); } return out; } return obj; } Then I wrapped setDoc, updateDoc, and addDoc so every write cleans the data first.
The other lesson: deploy settings, not code
The site broke with: Failed to load module script: Expected a JavaScript-or-Wasm module script but the server responded with a MIME type of "application/octet-stream"
I was staring at the code. The problem was GitHub Pages settings. It was serving my repo root — which has /src/main.tsx — instead of my built dist/ folder. The fix was to copy dist/ into a docs/ folder and point Pages at /docs.
What I'd like feedback on
- Does the onboarding flow make sense the first time you see it?
- Is the calorie calculation right? Mifflin-St Jeor for BMR, activity multiplier for TDEE, 300–500 deficit, floor at BMR.
- Does it break on your phone?
forkcount.github.io
I'm 13 and I built this by directing Google AI Studio, not by writing code by hand. If something looks like a beginner mistake, it probably is. Tell me and I'll fix it.
![Why Object.keys(user) Returns string[], Not (keyof User)[]: TypeScript Means It](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2q4w48b9bzs43tynyhsf.png)
