DEV Community

forkcount
forkcount

Posted on

I built a free calorie tracker with a metabolic safety floor. No card, no email, no paywall.

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;
}
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.