Nutrition
Overview
Vanilla Cookbook stores nutrition as raw text in Recipe.nutritional_info.
At runtime, the app parses this text into a structured object for display and scaling behavior. No schema migration is required in v1.
Data Flow
- Nutrition text is imported/scraped into
Recipe.nutritional_info. - Recipe view calls
parseNutritionInfo(text, language). - Parsed entries render in
RecipeViewNutrition.svelteusing shared table components. - If parser confidence is low, the raw text block is rendered as a safe fallback.
- When AI cleanup is used,
/api/recipe/cleanupwithtype: "nutrition"returns normalized nutrition. - Normalized text is serialized back into
Recipe.nutritional_info.
Parsing and Display
Core parser utilities are in src/lib/utils/nutrition.js:
parseNutritionInfo(text, language = 'eng')scaleNutrition(parsed, scale)
Localization dictionaries are in src/lib/utils/nutritionI18n.js and provide:
nutrientAliasesperServingPhrasesignoreTokens
Parser behavior is language-first with fallback to English lexicons.
Parsed Structure
{
perServing: true,
format: 'line' | 'pipe' | 'sentence' | 'nutrition_facts' | 'unknown',
confidence: 0.0,
rawText: '...',
entries: [
{
name: 'Calories',
canonicalName: 'calories',
quantity: 471,
unit: 'kcal',
raw: 'Calories: 471 kcal',
note: ''
}
]
}
Notes:
noteis optional metadata extracted from row text when present.- Scaling is applied only when
perServing === false. perServing === truevalues are intentionally not scaled.
Cleanup Serialization
Cleanup route: src/routes/api/recipe/cleanup/+server.js (type: "nutrition").
Normalized text output uses a predictable newline format:
- Optional localized per-serving prefix (first locale phrase).
- Two newline characters.
- One nutrient per line in
Name: quantity unitform.
This format keeps human readability while improving parser consistency.
UI Integration
- Recipe view component:
src/lib/components/recipe/RecipeViewNutrition.svelte - Recipe edit form:
src/lib/components/recipe/RecipeForm.svelte
View behavior:
- Renders a strict 2-column table (
Nutrient,Amount). - Shows
Per servingorPer recipe (scaled)status. - Falls back to raw text when parse confidence is low.
Discovery and Coverage
Data discovery tooling:
- Audit script:
scripts/nutrition/audit-nutrition.mjs - Fixture export:
scripts/nutrition/export-fixture.mjs
Current fixture-based benchmark uses local sample records from the app database and is validated in:
src/tests/nutrition.coverage.test.js
Coverage target for parsed rows is >= 80% for the sample fixture.
Research Notes (Future)
Future research may estimate nutrition directly from parsed ingredients using ingredient-density and nutrient datasets.
This is roadmap-only in the current phase and not implemented.