cook.md

Nutrition FunctionsCook Pro

These functions are available in any report template when you're signed in with Cook Pro. They resolve your ingredients against a curated nutrition database (USDA and other reference sources) with unit and preparation conversion. Prefer to maintain your own numbers? The free local db() datastore works without a subscription.

FunctionReturns
nutrition_for(ingredient)macros — kcal, protein_g, fat_g, carb_g, fiber_g
nutrition_for_amount(name, amount, unit, prep)full item: macros + micronutrients + vitamins
aggregate_nutrition(ingredients)items, totals, confidence breakdown, allergen summary
total_calories(ingredients)number
macros(ingredients){kcal, protein_g, …}
vitamins(ingredients)vitamin totals
nutrient_total(ingredients, key)one nutrient, e.g. "iron_mg", "vit_d_iu"
is_in_category(ingredient, slug)true/false, category-tree aware
category_servings(plan, slug)meals containing the category (see plans)
convert(amount, from, to, ingredient?)unit conversion; pass the ingredient for volume/count units
compare(actual, target, op) / within_tol(actual, target, tol_pct)assertions (see checks)
record_check, all_checks(), failed_checks()pass/fail tracking (see checks)

Reading nutrition

nutrition_for(ingredient) uses the quantity, unit and preparation from the recipe itself:

{% set n = nutrition_for(ingredient) %}
{{ n.kcal }} kcal, {{ n.protein_g }} g protein

For micronutrients and vitamins, or when there's no ingredient object to hand, use the lower-level form:

{{ nutrition_for_amount("salmon", 150, "g", "cooked").protein_g }}

aggregate_nutrition(ingredients) sums a whole list in one call and is the workhorse for recipe and plan totals; total_calories, macros, vitamins and nutrient_total are shortcuts over it.

Allergens

Every resolved item carries an allergens block, and aggregate_nutrition adds an allergen_summary for the batch. The one rule that matters: check status before contains. An ingredient with status: "unverified" has an empty contains list that means "nothing known" — never "allergen-free".

You don't have to hand-write the logic — include the built-in "allergens" partial and it renders the standard, correctly guarded lines:

{% set alg = aggregate_nutrition(ingredients).allergen_summary %}
{% include "allergens" %}

When some ingredients are unverified, the summary reads "Contains at least …" — the list is a floor, not a ceiling.

Confidence & sources

Nutrition numbers are estimates, and the report can be honest about it. aggregate_nutrition returns a confidence_breakdown next to the totals:

{% set t = aggregate_nutrition(ingredients) %}
Overall: {{ t.totals.confidence }} (weighted: {{ t.totals.confidence_weighted }})
  • totals.confidence — worst-of across items (strict).
  • totals.confidence_weighted — mass-weighted, so one small estimated item doesn't tank the score.
  • confidence_breakdown.estimated_share_of_micronutrients — how much of the micronutrient totals comes from estimated entries.

Each item also carries its own source and confidence, so templates can flag individual rows.

Categories & conversion

is_in_category(ingredient, slug) is tree-aware — an oily fish counts as fish_and_shellfish too. convert(amount, from, to, ingredient?) converts units; pass the ingredient when converting volume or count units that need density or portion data.

Building reports outside the editor, with the API or CLI? See the developer guides.