Nutrition calculation (recipe pages)
Aggregated recipe nutrition is computed by <RecipeNutrition /> from structured ingredients. Implementation: src/utils/recipeNutritionCalculate.mjs. Schema: system/recipe-ingredient-schema.md.
<RecipeNutrition /> is the only place a recipe publishes per-serving figures. <RecipeFoods /> lists the linked foods and their substances and calculates nothing.
Ingredients with no food page, or whose preparation state differs from the food page, resolve through composition_ref into src/data/recipeCompositionSnapshots.mjs — named USDA records generated by scripts/build-recipe-composition-snapshots.mjs.
Read-only helpers: scripts/recipe-nutrition-report.mjs (per-serving values for every recipe), scripts/usda-portion-lookup.mjs and scripts/usda-food-search.mjs (household measures and record selection).
Unvalidated Biological Target Matrices are suppressed by <RecipeMatrix /> (src/utils/recipeMatrixGate.mjs). Schema proposal: system/recipe-matrix-schema-proposal.md.
Rule
Never render a quantitative table unless every default-included ingredient has a composition record and a resolved edible weight in grams.
If not:
Detailed nutrition calculation pending ingredient-weight reconciliation.
There is no 100 g-per-linked-food fallback. Explanatory copy must not legitimise proxy totals.
Formula
contribution = per-100 g value × calculation_weight_g ÷ 100
per serving = sum(contributions) ÷ servings
Missing analytical keys are not reported (not zero). Qualitative, range, and formulation-specific values are not summed. Optional ingredients (included_in_default: false) are excluded from the default total.
Public table
Per serving: Nutrient | Amount per serving | Reference intake.
Reference intake percentages use the site adult values in system/nutrient-reference-values.md applied to the per-serving quantity. Protein is not shown as a g/kg body-weight range.
Recipe prose must not restate these figures. A hand-typed second copy drifts from the calculation, which is how a page came to publish two different carbohydrate and fat totals at once. Prose may cite a withdrawn estimate, an optional-ingredient delta or an alternative serving split, because none of those is what the table publishes.
Editorial YAML
Canonical: recipe_ingredients (see schema). Legacy recipe_nutrition with explicit grams remains valid until migrated. Omitting both yields the pending message, not a 100 g tag-sum.