DEV Community

bowen Tse
bowen Tse

Posted on Originally published at toolkitloop.blogspot.com

I Built a No-Signup Calorie Calculator: 5 TDEE Lessons

Most calorie calculators ask for your stats, show a confident number, and hide how they got it. I built one that does the opposite: it names its equation, shows its activity factor range, rounds to 10 kcal, and puts maintenance first. Disclosure up front: I built ToolkitLoop, and this calculator is one of its free browser tools. The code and formulas below are the interesting part, not the promotion.

Try it here: https://toolkitloop.com/calorie-calculator

Lesson 1: Name the equation or the number means nothing

The default equation is Mifflin-St Jeor. The tool also offers revised Harris-Benedict and, when body fat percentage is known, Katch-McArdle. That menu exists because switching equations moves the answer, and a user who cannot see which equation ran cannot reproduce the result.

In code, the Mifflin-St Jeor branch is deliberately boring:

function bmrMifflinStJeor({ sex, weightKg, heightCm, age }) {
  const base = 10 * weightKg + 6.25 * heightCm - 5 * age;
  return sex === "male" ? base + 5 : base - 161;
}
Enter fullscreen mode Exit fullscreen mode

Boring is the point. A calorie estimate should be a transparent formula with visible inputs, not a proprietary model. If a health-adjacent tool will not show its math, treat its output as marketing copy with a number attached.

Lesson 2: Activity factor is the biggest source of error

TDEE is BMR multiplied by an activity factor, here from 1.2 to 1.9:

function tdee(bmr, activityFactor) {
  return bmr * activityFactor;
}
Enter fullscreen mode Exit fullscreen mode

One line, huge consequences. Moving from 1.4 to 1.6 on a 1,600 kcal BMR adds 320 kcal, more than most equation switches. And users pick this factor badly, usually from gym days alone, while the honest inputs include occupation, steps, standing time, and training duration and intensity.

That is why the tool has an Activity Level Assistant: it suggests a band, shows an adjacent comparison, and labels confidence as low or medium, and the user can override it. The lesson for any developer building an estimator: when one input dominates the output, spend your UX budget there, not on a prettier result card.

Lesson 3: Round aggressively and say so

The tool rounds results to 10 kcal and presents a starting range. Early versions of estimators like this often print something like 2,347 kcal, which implies a measurement device that does not exist. Rounding is a user-interface decision about honesty:

function roundTo10(kcal) {
  return Math.round(kcal / 10) * 10;
}
Enter fullscreen mode Exit fullscreen mode

A rounded range invites testing: eat near the middle for two weeks, watch the trend, adjust. A fake-precise number invites arguing with the tool when the scale disagrees by 100 kcal, which it will, because equations are estimates and bodies are not spreadsheets.

Lesson 4: Caps are guardrails, not targets

Loss scenarios are capped at 20 percent or 500 kcal per day, whichever is smaller; gain is capped at 15 percent:

function lossScenario(maintenance) {
  const cut = Math.min(maintenance * 0.2, 500);
  return maintenance - cut;
}
Enter fullscreen mode Exit fullscreen mode

Writing the cap as Math.min matters. A percentage-only cap lets a large maintenance number justify a huge deficit; a fixed-only cap lets a small maintenance number justify a reckless percentage. Taking the smaller of the two keeps both failure modes in check. The same pattern shows up in rate limiters and budgets: when two limits protect different cases, apply both and take the stricter one.

Lesson 5: State who the tool is NOT for

The calculator is explicit: it is an estimate, not medical or nutrition advice, and it is not for minors, pregnancy or breastfeeding, medical nutrition therapy, eating-disorder treatment, or specialised endurance or competitive nutrition. Its supported self-guided range starts at 1,200 kcal, described as a product range, not a universal clinical safety line.

That paragraph is the most important feature in the whole tool, and it costs nothing to implement. Many developer-built health tools fail here: they ship the formula, skip the scope, and let users apply an estimator to cases it was never designed for. If you build anything health-adjacent, write the exclusion list before you write the formula.

Macros: anchor protein, then fill the rest

Standard mode splits calories by percentage: protein 4 kcal per gram, carbohydrate 4 kcal per gram, fat 9 kcal per gram, and a custom split must total 100 percent. The optional active mode sets protein by body weight first, then allocates fat and the remaining carbohydrate. Anchoring one macro before splitting the rest avoids the classic bug where percentages add up to 110 or 90 and nobody notices until the grams look wrong.

Everything runs in the browser with no signup, and entered values stay on the device. For a tool that asks for body measurements, that architecture is not a bonus feature; it is the minimum respectful design.

The question I keep coming back to

Here is the hook I would actually argue about: should a calorie calculator ever show a single number, or should it always show a range with its equation and activity assumption attached? A single number is easier to act on. A range with its assumptions is easier to trust and easier to correct. I chose the range, and I think the single-number design is why people calculator-hop until they find the answer they wanted.

What would change your mind: a tighter equation, a better activity input, or just a number that stops pretending to be exact? Tell me which one you would build first, and why.

Top comments (3)

Collapse
 
rushdeploy profile image
Rishabh Mishra •

I would always show a range, not a single number. A single figure reads as precise when the activity factor alone can swing it by hundreds of calories, so the range is the more honest answer.

Collapse
 
bowentse profile image
bowen Tse •

You're right, and I agree — a range is the more honest presentation. The activity multiplier is the biggest source of uncertainty in the whole calculation: as I noted in the article, moving from 1.4 to 1.6 on a 1,600 kcal BMR adds 320 kcal, so a single number implies a precision the estimate simply doesn't have.

I just re-checked the calculator, and it already shows a suggested starting range alongside the headline figure — for example, a sample calculation gave a ~2,560 kcal/day midpoint with a suggested starting range of 2,300–2,810 kcal/day, rounded to the nearest 10 kcal, plus a comparison with the adjacent activity level. That said, your point still stands: the headline number reads first, so I want to look again at whether the range should lead instead of sitting underneath it.

Thanks for pushing on this — it's exactly the kind of feedback that makes the tool better.

For context, ToolkitLoop is free, and the calculator runs entirely in your browser — nothing is uploaded and there's no sign-up.

Collapse
 
rushdeploy profile image
Rishabh Mishra •

Good to hear the range is already there — that 320 kcal swing from the multiplier alone makes the case better than any explanation could. If the range led instead of sitting under the headline number, it would set the right expectation before anyone reads a single figure.