DEV Community

forkcount
forkcount

Posted on

I Fixed 3 Bugs in My AI-Built Calorie Tracker Today. All Three Were "The AI Is Ignoring Me." None of Them Were the AI.

I'm 13. I built a free calorie tracker called ForkCount using Google AI Studio. It runs on React + Vite, deployed to GitHub Pages, database on Supabase. I can't write JavaScript from memory. I build by describing what I want and debugging what comes back.

Today I fixed three bugs that all felt like "the AI is ignoring my settings." Every one turned out to be a completely different problem. Here's what happened, and what I learned.

Bug 1: The plan said "vegetarian" but served turkey

I set my profile to vegetarian. Generated a 7-day meal plan. Day three: turkey breast.

The plan generator was calling the AI with a prompt that said "make a meal plan" and nothing else. It never read profile.dietary_preference. It never filtered the response. It asked for food and took what came back.

The fix was two layers. First, pass the diet into the generation prompt:


js
const prompt = `Generate a 7-day meal plan for a ${profile.dietary_preference} user. 
Do NOT include any meat, poultry, or fish if vegetarian.`
Second, verify the response before showing it:

js
const forbidden = ['turkey', 'chicken', 'beef', 'pork', 'lamb', 'fish']
if (profile.dietary_preference === 'vegetarian') {
  for (const meal of plan.meals) {
    for (const item of meal.ingredients) {
      if (forbidden.some(f => item.toLowerCase().includes(f))) {
        // regenerate this meal
      }
    }
  }
}
Asking the AI is not enough. You have to check the answer.

Bug 2: The plan used 2000 kcal, not my actual target
Same root cause, different field. The plan generator had a hardcoded default of 2000 calories. My profile target was 1400. The plan ignored it.

The bug was subtle: the generator did read profile.target_calories, but the read happened before the profile finished loading from Supabase. So it got undefined, fell back to 2000, and generated the plan around that number.

The fix was to await the profile load before generating:

js
const { data: profile } = await supabase
  .from('profiles')
  .select('target_calories, dietary_preference')
  .eq('id', user.id)
  .single()

if (!profile) throw new Error('Profile not loaded')
if (!profile.target_calories) throw new Error('No target set')
No fallback. If the target is missing, fail loudly instead of quietly using 2000. Silent fallbacks are how you end up with plans that don't match the user.

Bug 3: The Diary showed one target, the Edit screen showed another
This one took the longest. The Diary screen showed a calorie target of 1580. The Edit Daily Calorie Target screen showed 1396. Both were reading from "the profile." Both were wrong in different ways.

Turns out the Diary was reading a cached value from localStorage. The Edit screen was reading from Supabase. The cache was never invalidated when the target changed. Two sources of truth. One updated, one didn't. Refresh didn't help because the localStorage cache survived the refresh.

The fix was to delete the localStorage cache entirely and always read from Supabase on mount. One source of truth. Cache invalidation bugs are almost always fixed by removing the cache.

What I actually learned today
Three bugs, three patterns:

The AI does what you ask, not what you meant. "Make a plan" is not "make a vegetarian plan." You have to say the diet in the prompt, and then verify the answer. The AI will happily hand you turkey if you don't say no.

Silent fallbacks hide bugs. A ?? 2000 fallback looked harmless. It made the app silently wrong for months instead of loudly broken for 5 minutes. Fail loud. Fail early. A red error message is better than a wrong number.

Two sources of truth always disagree. If the Diary reads localStorage and the Edit screen reads Supabase, they will diverge. Not "might diverge." Will. The fix is one source. Always.

None of these were "the AI is broken" bugs. They were "the code is doing exactly what it says, and what it says is wrong" bugs. The AI wrote the code correctly. The code did the wrong thing correctly.

That's the part nobody warns you about with AI-assisted development. The AI doesn't make the same mistakes a human makes. It makes different mistakes — cleaner ones, more consistent ones, the kind that hide behind passing builds.

The fix is the same as with human-written code: read what it actually does, not what you think it does. Add a log. Check the value. Find the layer where the bug lives.

Three bugs down. No idea how many left.

ForkCount is a free calorie and macro tracker with no card, no trial, and no paywall. It calculates your BMR and TDEE from your own stats and shows you the maths. If you've ever wanted a tracker that doesn't hide the calorie math behind a subscription, try it at forkcount.github.io. It's two weeks old, so it's rough around the edges — but it works, and every bug gets fixed within a day.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)