Culinary Intelligence and Smart Home domain. Named after the Greek goddess of the hearth and home.
Hestia is the Oshun culinary intelligence platform: 14 feature libraries
under libs/hestia/ plus three applications — apps/hestia/api (Fastify REST +
GraphQL), apps/hestia/web (Next.js), and apps/hestia/mobile (Expo / React
Native). This document is the complete technical reference, grounded directly in
the source under libs/hestia/* and apps/hestia/*.
The 14 libraries share a single foundation (@hestia/core) that carries the
canonical domain types, the PostgreSQL schema, the event system, and the
authorization model — all with zero runtime dependencies, so they can be used in
any Node.js, browser, or edge context. Every other library declares
@hestia/core as a peer dependency and adds its own domain logic on top. No
feature library depends on another feature library; all coupling between
capabilities happens at the application layer.
This reference covers: the domain overview property table; the full library inventory; the core domain model (types, enumerations, database schema, events, authorization); the domain logic of each feature library; the API application's REST surface, GraphQL schema, and state machines; the web and mobile applications; and build/integration notes.
1. Domain Overview#
The table below summarizes the key runtime characteristics of the domain at a glance. All of these properties are derived from the source tree — they are not aspirational targets.
| Property | Value |
|---|---|
| Domain name | hestia |
| Scope | Culinary intelligence and smart home |
| Library count | 14 (libs/hestia/*) |
| Application count | 3 (apps/hestia/api, apps/hestia/web, apps/hestia/mobile) |
| Database | PostgreSQL via Drizzle ORM (schema defined in @hestia/core) |
| Primary language | TypeScript (ESM) |
| Library build | @nx/js:tsc |
| API stack | Fastify + GraphQL Yoga; PostgreSQL (pg) + Drizzle; Redis (ioredis) |
| Web stack | Next.js (App Router), React, TanStack Query, Zustand, Tailwind CSS |
| Mobile stack | Expo / React Native, React Navigation, TanStack Query, Zustand |
2. Library Inventory#
All 14 libraries live under libs/hestia/. Each declares
tags: ["scope:hestia", "layer:domain", "type:lib"], "type": "module", and
(except @hestia/core) a peerDependencies entry of
@hestia/core: workspace:*.
The table below maps each package to its filesystem path and lists the source
modules it contains. Every module has a co-located *.spec.ts test file and
each library has its own vitest.config.ts. The flat sibling structure means
there are no inter-library dependencies within the feature layer —
@hestia/core is the only shared dependency.
| Package | Path | Source modules (src/*.ts) |
|---|---|---|
@hestia/core |
libs/hestia/core |
schemas, db-schema, types, events, auth |
@hestia/ingredients |
libs/hestia/ingredients |
master-database, flavor-compounds, pairing, substitution, nutrition, seasonality |
@hestia/nutrition |
libs/hestia/nutrition |
analysis, bioavailability, dietary, allergen, medical-diet, goals |
@hestia/recipes |
libs/hestia/recipes |
recipe-model, parsing, import-export, scaling, versioning, search, collections |
@hestia/cooking |
libs/hestia/cooking |
guided-cooking, timers, voice, doneness, techniques, session-log |
@hestia/smart-kitchen |
libs/hestia/smart-kitchen |
devices, cooking-devices, sensors, smart-appliances, automation, orchestration |
@hestia/meal-planning |
libs/hestia/meal-planning |
calendar, household, suggestions, budget, batch-cooking, events |
@hestia/pantry |
libs/hestia/pantry |
inventory, scanning, expiration, shopping, grocery-store, equipment |
@hestia/heritage |
libs/hestia/heritage |
family-recipes, oral-history, regional-archive, food-history, community |
@hestia/sustainability |
libs/hestia/sustainability |
carbon-footprint, food-waste, ethical-sourcing, seasonal-local, composting |
@hestia/education |
libs/hestia/education |
techniques, progression, food-science, cuisine, certifications, interactive |
@hestia/professional |
libs/hestia/professional |
menu-costing, kitchen-workflow, inventory-management, food-safety, catering-events, recipe-development |
@hestia/social |
libs/hestia/social |
recipe-sharing, profiles-following, ratings-reviews, cook-alongs-events, family-cookbook, community-challenges |
@hestia/ai-ml |
libs/hestia/ai-ml |
recipe-generation, flavor-pairing, image-recognition, recommendations, nlp, predictive-analytics |
3. Core Domain Model (@hestia/core)#
@hestia/core carries the canonical domain types for the whole domain. It has
zero runtime dependencies — domain types are plain TypeScript interfaces
and enumerations are const objects with derived union types; validation is
done by explicit hand-written functions rather than Zod. This design keeps the
library suitable for browser and edge environments where Zod's bundle cost would
be unacceptable, and it ensures the domain model can be understood without any
build-time schema transformation.
Its barrel (src/index.ts) re-exports schemas, db-schema, types,
events, and auth. Each of those five modules is described in detail below.
3.1 Enumerations (schemas.ts)#
Each enumeration is a const object plus a derived type and a readonly array
of values (e.g. MEASUREMENT_UNITS, COOKING_METHODS). This pattern provides
both runtime value access (iterating the array for UI dropdowns) and
compile-time exhaustiveness checking in switch statements — with no Zod
overhead.
MeasurementUnit — 24 values across four groups:
- US volume:
tsp,tbsp,cup,fl_oz,pint,quart,gallon - Metric volume:
ml,liter - US weight:
oz,lb - Metric weight:
gram,kg - Informal:
pinch,dash,piece,whole,clove,sprig,bunch,can,package,slice,to_taste
CookingMethod — 35 values: bake, roast, broil, grill, saute,
fry, deep_fry, stir_fry, steam, boil, simmer, poach, braise,
stew, smoke, cure, ferment, pickle, dehydrate, sous_vide,
pressure_cook, slow_cook, microwave, blanch, caramelize, flambe,
reduce, marinate, brine, temper, toast, sear, char, confit,
emulsify.
DietaryRestriction — 20 values: vegan, vegetarian, pescatarian,
lacto_vegetarian, ovo_vegetarian, kosher, halal, gluten_free,
dairy_free, nut_free, soy_free, egg_free, low_sodium, low_carb,
keto, paleo, whole30, fodmap, diabetic_friendly, heart_healthy.
Allergen — 14 values aligned with EU + US allergen regulation: milk,
eggs, fish, shellfish, tree_nuts, peanuts, wheat, soy, sesame,
mustard, celery, lupin, mollusks, sulfites.
MealType — 10 values: breakfast, brunch, lunch, dinner, snack,
appetizer, side_dish, dessert, beverage, cocktail.
IngredientCategory — 9 values: produce, dairy, meat, seafood,
grain, spice, condiment, baking, other.
Preparation — 24 values describing ingredient cuts/treatments: diced,
minced, sliced, chopped, julienned, grated, shredded, crushed,
pureed, mashed, peeled, deveined, deboned, halved, quartered,
cubed, torn, chiffonade, brunoise, sifted, melted, softened,
toasted, blanched, whole.
3.2 Difficulty and cuisine taxonomy#
DifficultyLevel is an interface — level (1 | 2 | 3 | 4 | 5), name,
description, criteria (string array). DIFFICULTY_LEVELS ships five
calibrated entries: 1 Beginner, 2 Easy, 3 Intermediate, 4 Advanced, 5 Expert,
each with five criteria strings (equipment, knife skills, ingredient count,
cooking-method count, precision). getDifficultyLevel(level) looks one up.
The cuisine taxonomy is a recursive tree rather than a flat list, reflecting the real-world nesting of culinary traditions. French cuisine contains Provençal and Lyonnaise sub-cuisines; Chinese cuisine contains Cantonese, Sichuan, and many others. This nesting is encoded in the type system and the data at the same time.
CuisineType is { id, name, region, subCuisines? } (recursively nested).
CUISINE_TAXONOMY is a fixed tree of named world cuisines grouped by region
(Europe, Asia, Middle East, Africa, Americas, Oceania, Global). Top-level
cuisines such as italian, french, chinese, japanese, indian, mexican
carry nested subCuisines (Tuscan, Sichuan, North Indian, Oaxacan, etc.).
flattenCuisines() returns the full flattened list including sub-cuisines;
findCuisineById(id) searches the tree.
3.3 Nutrition value objects#
The nutrition types form a hierarchy: a NutritionInfo object carries the main
macros (required) plus optional micronutrient groups, each with their own typed
interface. This structure maps directly to both USDA FoodData Central data and
the FDA/EU nutrition label format.
NutritionInfo — calories (kcal), protein, carbs, fat (grams,
required); optional fiber, sugar (g), sodium, cholesterol (mg),
saturatedFat, transFat (g), vitamins (VitaminProfile), minerals
(MineralProfile).
VitaminProfile — all optional: vitaminA (mcg), vitaminC (mg),
vitaminD (mcg), vitaminE (mg), vitaminK (mcg), vitaminB1/B2/B3/B5
(mg), vitaminB6 (mg), vitaminB7 (mcg, biotin), vitaminB9 (mcg, folate),
vitaminB12 (mcg).
MineralProfile — all optional: calcium, iron, potassium,
magnesium, zinc, phosphorus (all mg).
3.4 Flavor and texture profiles#
Flavor and texture profiles are normalized numeric or boolean objects rather
than free-text strings. This normalization is what enables the flavor pairing
engine in @hestia/ingredients to compute compatibility scores across
ingredients programmatically.
FlavorProfile — six required numeric intensities 0–10: sweet, salty,
sour, bitter, umami, spicy; optional booleans aromatic, rich,
light; optional descriptors string array.
TextureProfile — 11 optional boolean attributes (crispy, crunchy,
tender, chewy, creamy, silky, flaky, crumbly, firm, soft,
juicy) plus an optional descriptors string array.
3.5 Ingredient and Recipe entities#
These are the two most important domain objects. Ingredient is the master
database entry; RecipeIngredient is how an ingredient appears within a
specific recipe (with quantity, unit, and preparation). The decoupling is
intentional — a single master ingredient entry can appear across thousands of
recipes, each with different quantities and preparations, with only one place to
update when nutritional data changes.
Ingredient — id, name, category (IngredientCategory); optional
description, shelfLife (e.g. "7 days"), storageMethod, substitutes
(string array), allergens (Allergen[]), nutritionPer100g
(NutritionInfo).
RecipeIngredient — ingredientId, name, quantity (number), unit
(MeasurementUnit), optional (boolean, required); optional preparation
(Preparation | string), substituteNote.
Instruction — step (positive integer), text; optional duration
(minutes), method (CookingMethod), temperature (number), temperatureUnit
('F' | 'C'), tips (string array).
Recipe — the canonical recipe object. All fields with constraints listed
below:
| Field | Type | Notes |
|---|---|---|
id |
string |
required, non-empty |
title |
string |
required, non-empty |
description |
string |
required |
servings |
number |
≥ 1 |
prepTime |
number |
minutes, ≥ 0 |
cookTime |
number |
minutes, ≥ 0 |
totalTime |
number |
minutes, ≥ 0 |
difficulty |
1 | 2 | 3 | 4 | 5 |
validated 1–5 |
cuisine |
string? |
cuisine id |
mealType |
MealType? |
|
dietaryTags |
DietaryRestriction[] |
each validated |
allergens |
Allergen[] |
each validated |
ingredients |
RecipeIngredient[] |
at least one required |
instructions |
Instruction[] |
at least one required |
nutrition |
NutritionInfo? |
|
photos |
string[]? |
image URLs |
author |
string |
required |
createdAt |
Date |
must be a valid Date |
updatedAt |
Date |
must be a valid Date |
version |
number |
≥ 1 |
isPublic |
boolean |
|
rating |
number? |
0–5 when present |
ratingCount |
number |
≥ 0 |
flavorProfile |
FlavorProfile? |
|
textureProfile |
TextureProfile? |
3.6 Validation functions#
schemas.ts exposes a complete set of validation functions — one per type that
can arrive from user input or external sources. Each returns a
ValidationResult ({ valid, errors }, where each ValidationError is
{ field, message, value? }). validateRecipe is the most comprehensive: it
recursively validates every nested ingredient, instruction, nutrition, flavor,
and texture object.
The full validator set: validateMeasurementUnit, validateCookingMethod,
validateDietaryRestriction, validateAllergen, validateMealType,
validateIngredientCategory, validateFlavorIntensity (0–10),
validateDifficulty (integer 1–5), validateNutritionInfo (non-negative
numerics), validateFlavorProfile, validateTextureProfile,
validateIngredient, validateRecipeIngredient, validateInstruction, and
validateRecipe.
3.7 Unit, temperature, equipment, and user types (types.ts)#
types.ts provides the measurement conversion system, temperature utilities,
equipment catalog, and user/household model that are used across all feature
libraries.
Measurement conversion. ML_PER (volume anchored on ml) and GRAM_PER
(weight anchored on grams) drive conversions. VOLUME_UNITS, WEIGHT_UNITS,
and INFORMAL_UNITS are Sets; areUnitsConvertible(from, to) and
getUnitCategory(unit) classify a unit. buildVolumeConversionTable() and
buildWeightConversionTable() produce all ConversionFactor
({ from, to, factor }) pairs. convert(amount, from, to) returns a
ConversionResult ({ success, value?, from, to, error? }); cross-category,
informal, and unknown-unit conversions fail with an explanatory error. The
UnitConverter class wraps convert and adds
convertWithDensity(amount, from, to, gramsPerMl) for volume↔weight conversion,
plus getSupportedUnits().
Temperature. TemperatureUnit is 'F' | 'C' | 'K'. Pairwise converters
(fahrenheitToCelsius, celsiusToFahrenheit, celsiusToKelvin,
kelvinToCelsius, fahrenheitToKelvin, kelvinToFahrenheit) plus
convertTemperature(value, from, to) returning a TemperatureResult.
OVEN_TEMPERATURES lists 11 reference oven settings (name, fahrenheit, celsius,
gas mark) from Very Cool (250 °F) to Extremely Hot (500 °F).
Equipment. EquipmentCategory is
'cookware' | 'bakeware' | 'appliance' | 'utensil' | 'cutlery'.
CookingEquipment is
{ id, name, category, essential, alternativeEquipment, description?, careInstructions? }.
ESSENTIAL_EQUIPMENT ships 18 standard items (chef's knife, cutting board,
skillet, saucepan, stock pot, sheet pan, mixing bowls, wooden spoon, spatula,
measuring cups/spoons, colander, tongs, whisk, can opener, paring knife, oven,
stovetop). validateEquipment(eq) checks structure.
User and household. SkillLevel is
'beginner' | 'easy' | 'intermediate' | 'advanced' | 'expert' (SKILL_LEVELS
array). UserProfile carries id, name, email, dietaryRestrictions,
allergens, skillLevel, householdSize, favoriteCuisines,
dislikedIngredients, kitchenEquipment, and optional timestamps.
HouseholdMember is { userId, name, role, joinedAt } where role is
'owner' | 'admin' | 'member'. Household is
{ id, name, members, sharedPantry, sharedMealPlan, sharedShoppingList, createdAt?, updatedAt? }.
validateUserProfile and validateHousehold enforce structure; a household
must have at least one member and at least one owner.
4. Database Schema (@hestia/core/db-schema.ts)#
@hestia/core exports Drizzle ORM PostgreSQL definitions: 20 tables and
10 pgEnum enum types, all prefixed hestia_. The prefix prevents name
collisions with tables from other Oshun domains that share the same PostgreSQL
instance. Tables, enums, and Drizzle relations are all exported; ALL_TABLES
and ALL_ENUMS constants enumerate them for introspection and test setup.
4.1 Enum types#
PostgreSQL pgEnum types mirror the TypeScript enumerations in schemas.ts.
The following table lists the ten enum types and their allowed values.
pgEnum name |
Values |
|---|---|
hestia_difficulty |
beginner, easy, intermediate, advanced, expert |
hestia_meal_type |
the 10 MealType values |
hestia_ingredient_category |
the 9 IngredientCategory values |
hestia_recipe_status |
draft, published, archived, under_review |
hestia_visibility |
private, household, public |
hestia_equipment_category |
cookware, bakeware, appliance, utensil, cutlery |
hestia_session_status |
planned, in_progress, completed, cancelled |
hestia_inventory_status |
in_stock, low, out_of_stock, expired |
hestia_shopping_item_status |
pending, purchased, skipped |
hestia_technique_type |
dry_heat, wet_heat, combination, chemical, mechanical, preservation |
4.2 Tables#
All tables use a uuid primary key with defaultRandom() and timezone-aware
timestamps. The 20 tables, with their key columns and indexes, are:
hestia_recipes—title,slug(unique index),description,servings,prepTime,cookTime,totalTime,difficulty,cuisine,mealType,status,visibility,authorId,version,isPublic,dietaryTags/allergens/photos(JSONB string arrays),flavorProfile/textureProfile(JSONB),sourceUrl. Indexed on slug, author, cuisine, meal type, status, created-at.hestia_ingredients—name(unique index),category,description,shelfLife,storageMethod,substitutes/allergens(JSONB). Indexed on name and category.hestia_recipe_ingredients(junction) —recipeId(FK → recipes, cascade),ingredientId(FK → ingredients, restrict),name,quantity(decimal(10,3)),unit,preparation,optional,substituteNote,sortOrder.hestia_nutritional_data— optionalingredientId/recipeIdFKs;calories/protein/carbs/fat(real, default 0); optionalfiber,sugar,sodium,cholesterol,saturatedFat,transFat;vitamins/minerals(JSONB);servingSize,servingUnit.hestia_flavor_compounds—name(unique index),casNumber,category,description,flavorNotes/foundIn(JSONB string arrays),threshold(real).hestia_ingredient_pairings—ingredientAId/ingredientBId(FKs → ingredients, cascade; pair unique index),compatibilityScore(real),sharedCompounds(integer),notes.hestia_user_preferences—userId(unique index),skillLevel(difficulty enum),householdSize,favoriteCuisines/dislikedIngredients/preferredMealTypes/cookingEquipment(JSONB string arrays),maxPrepTime,maxCookTime.hestia_dietary_restrictions—userId,restriction,severity(defaultstrict),notes; unique on (userId,restriction).hestia_allergen_profiles—userId,allergen,severity(defaultsevere),reaction,diagnosedDate; unique on (userId,allergen).hestia_meal_plans—userId,name,startDate,endDate,meals(JSONB array of{ date, mealType, recipeId, servings }),notes.hestia_pantry_inventory—userId,ingredientId(FK → ingredients, cascade),quantity(decimal(10,3)),unit,status(inventory enum),purchaseDate,expirationDate,location,notes. Indexed on user, ingredient, status, expiration.hestia_shopping_lists—userId,name,items(JSONB array of{ ingredientId, name, quantity, unit, status, category }),mealPlanId(FK → meal plans, set null),completed.hestia_equipment_registry—name(unique index),category(equipment enum),description,essential,alternativeEquipment(JSONB),brand,careInstructions.hestia_cooking_sessions—userId,recipeId(FK → recipes, cascade),status(session enum),startedAt,completedAt,currentStep,notes,servingsCooked,rating(real),feedback,photosUrls(JSONB).hestia_recipe_versions—recipeId(FK → recipes, cascade),version,title,description,changes,snapshot(JSONB, not null),authorId; unique on (recipeId,version).hestia_recipe_ratings—recipeId(FK → recipes, cascade),userId,rating(real),review,wouldMakeAgain,difficultyFeedback(difficulty enum); unique on (recipeId,userId).hestia_recipe_comments—recipeId(FK → recipes, cascade),userId,parentId(self-reference for threads),content,likes,edited.hestia_recipe_collections—userId,name,description,visibility(visibility enum),coverImage,recipeIds(JSONB),followerCount,tags(JSONB).hestia_cooking_techniques—name(unique index),type(technique enum),description,difficulty(difficulty enum),requiredEquipment/tips/relatedTechniques(JSONB),videoUrl.hestia_cuisines—code(unique index),name,region,parentId(self-reference),description,keyIngredients/keyTechniques(JSONB),flavorProfile(JSONB).
4.3 Relations#
Drizzle relations() declarations enable type-safe eager loading across table
boundaries. The relations declared are:
- Recipes resolve their
ingredients,versions,ratings,comments,sessions, andnutritionalData. - Ingredients resolve
recipeIngredients,nutritionalData,pantryItems, and both directions ofingredientPairings(relation namesingredientA/ingredientB). - Meal plans resolve
shoppingLists.
5. Domain Events (@hestia/core/events.ts)#
@hestia/core ships a complete in-process event-sourcing toolkit — not just
event type constants, but a full infrastructure for building, storing,
subscribing to, and projecting domain events. This enables decoupled
communication between modules (e.g., the social module reacting to a recipe
being rated without directly calling the recipes module) and provides an audit
trail of all significant actions in the domain.
5.1 Event envelope#
Every domain event is wrapped in a DomainEvent<T> envelope: id, type,
timestamp (Date), aggregateId, aggregateType, payload: T, version
(number), optional metadata. The factory
createEvent(type, aggregateId, aggregateType, payload, version=1, metadata?)
builds one; generateEventId() returns evt-NNNNNN and resetEventIdCounter()
resets the counter for test isolation.
5.2 Event types and payloads#
EventTypes defines 10 event name constants. Each event has a typed payload
interface and a DomainEvent<...> alias. The following table lists all ten:
EventTypes constant |
Event name | Payload interface (fields) |
|---|---|---|
RECIPE_CREATED |
recipe.created |
RecipeCreatedPayload — title, authorId, difficulty, cuisine?, mealType? |
RECIPE_UPDATED |
recipe.updated |
RecipeUpdatedPayload — fields[], previousVersion, newVersion, updatedBy |
RECIPE_COOKED |
recipe.cooked |
RecipeCookedPayload — userId, recipeId, servingsCooked, duration, rating?, notes? |
INGREDIENT_ADDED |
ingredient.added |
IngredientAddedPayload — name, category, addedBy |
MEAL_PLANNED |
meal.planned |
MealPlannedPayload — userId, date, mealType, recipeId, servings |
SHOPPING_LIST_GENERATED |
shopping_list.generated |
ShoppingListGeneratedPayload — userId, mealPlanId, itemCount, estimatedCost? |
PANTRY_UPDATED |
pantry.updated |
PantryUpdatedPayload — userId, ingredientId, action (added/removed/updated), quantity, unit |
COOKING_SESSION_STARTED |
cooking_session.started |
CookingSessionStartedPayload — userId, recipeId, sessionId, plannedServings |
COOKING_SESSION_COMPLETED |
cooking_session.completed |
CookingSessionCompletedPayload — userId, recipeId, sessionId, actualDuration, servingsCooked, success |
RECIPE_RATED |
recipe.rated |
RecipeRatedPayload — userId, recipeId, rating, review?, wouldMakeAgain? |
5.3 Event infrastructure#
The event infrastructure beyond the envelope itself provides an append-only store, a synchronous pub/sub bus, projection utilities for building read models, and a version migration chain for evolving payloads forward.
EventStore— in-memory append-only store:append,appendBatch,getByAggregateId,getByType,getByAggregateType,getAfter(timestamp),getAll,count,replay(handler),replayAggregate,clear.EventBus— synchronous pub/sub:subscribe(type, handler)andsubscribeAll(handler)(each returns an unsubscribe function),publish,unsubscribe,clearHandlers,clearAll,handlerCount.projectEvents(initialState, events, reducer)and theEventProjectionclass (apply,applyBatch,getState,getProcessedCount,reset) build read models from event streams.- Event versioning —
EventUpcaster(eventType,fromVersion,toVersion,upcast) and theUpcasterChainclass (register,upcast,upcastBatch) migrate old event versions forward (100-iteration safety cap). generateNotification(event, recipientId)maps an event to aDomainNotification(id,type,title,message,recipientId,sourceEventId,createdAt,read); it has a template for every event type and returnsnullfor unrecognised types.
6. Authorization Model (@hestia/core/auth.ts)#
auth.ts defines a complete recipe/collection authorization model used by both
the API and the libraries. The design centralizes all access rules in
@hestia/core so that the same permissions logic applies whether a request
comes through REST, GraphQL, or a direct library call.
The authorization system has three layers: visibility determines who can see a recipe at all; roles determine what a user can do once they can see it; and API key scopes gate programmatic access by capability rather than by user identity.
RecipeVisibility—private,household,public(VISIBILITY_LEVELS).Role—owner,admin,contributor,viewer(ROLES), ordered by a numericROLE_HIERARCHY(viewer0 →owner3).hasEqualOrHigherRolecompares two roles.Action—view,edit,delete,share,rate,comment,cook,fork(ACTIONS). APERMISSION_MATRIXmaps each role to its allowed actions: owner has all 8; admin has all exceptdelete; contributor hasview/edit/rate/comment/cook/fork; viewer hasview/rate/comment/cook/fork.roleHasPermission(role, action)andgetPermissionsForRole(role)query it.RecipeOwnership(recipeId,creatorId,contributors[],visibility,householdId?) plusHouseholdMembership(householdId,memberIds[],adminIds[]) feedgetUserRole(userId, ownership, householdMembership?)— creator → owner, listed contributor → contributor, household admin → admin, household member → viewer, public → viewer.checkPermission(userId, ownership, action, householdMembership?)first enforces visibility, then the permission matrix, returning aPermissionCheckResult(allowed,reason,role).- Household sharing —
HouseholdSharingConfig(sharedRecipes,sharedMealPlans,sharedShoppingLists,sharedPantry);isSharedInHouseholdandcanAccessHouseholdResourcegate the four resource types. - Collection permissions —
CollectionVisibility(private,public);CollectionPermissions(collectionId,ownerId,visibility,followers[],collaborators[]);canViewCollection,canEditCollection,canDeleteCollection,isFollowingCollection. - API key scopes —
APIKeyScopehas 7 values:recipe_read,recipe_write,meal_plan,pantry,shopping_list,user_profile,admin(API_KEY_SCOPES).APIKeyis{ id, userId, name, scopes[], createdAt, expiresAt?, lastUsedAt?, active }.apiKeyHasScope(admin scope grants all; expired/inactive keys deny),apiKeyHasAllScopes,validateAPIKey, andgetScopesForAction(resourceType, action)complete the model.
7. Feature Library Domain Logic#
The 13 feature libraries are pure-domain TypeScript with extensive built-in
reference data. Each library follows the same pattern: types and interfaces for
its domain objects, factory functions and classes implementing the domain logic,
and seed data so the system is functional out of the box. The subsections below
summarize the types and entry points that consumers depend on, grounded in each
library's src/*.ts exports.
7.1 @hestia/recipes — recipe management#
This library covers the full lifecycle of a recipe: creation and validation,
parsing from external formats, scaling to different serving sizes, version
history, and collection management. The recipe-model.ts module is the entry
point for creating and computing on recipes; the other modules add
import/export, scaling, versioning, and search on top.
recipe-model.ts—createRecipe(params)factory and the fluentRecipeBuilder;computeDifficulty(recipe)scores 1–5 from ingredient count, instruction count, technique complexity (ADVANCED_TECHNIQUES/INTERMEDIATE_TECHNIQUESsets), total time, and method count;estimateCost(recipe, priceMap)returns{ totalCost, perServing, missingPrices };detectAllergens(recipe, ingredientDb)uses the database then a keyword heuristic table;checkDietaryCompliance(recipe, restriction, ingredientDb?)checks excluded categories/allergens/keyword lists;RecipePhotoGallery(cover photo, reorder);computeTimings(recipe)splits prep/cook/rest from instructions;RecipeEquipment(required vs optional,checkAvailability).parsing.ts— natural-language recipe parsing:parseQuantity(ParsedQuantity),normalizeUnit,parsePreparation,parseIngredientLine(ParsedIngredient),extractTimeFromText(ExtractedTime[]),extractTemperature(ExtractedTemperature[]),extractEquipment,extractTechnique,detectVisualCue,detectDonenessCue,parseInstructionStep(ParsedInstruction).import-export.ts—ImportFormatis'jsonld' | 'markdown' | 'plaintext' | 'schemaorg';ExportFormatis'jsonld' | 'markdown' | 'plaintext'.importJsonLd/exportJsonLd(Schema.orgJsonLdRecipe),importSchemaOrg(html),importMarkdown/exportMarkdown,importPlainText/exportPlainText; classesRecipeImporter(withImportProgress) andRecipeExporter;generateRecipeCard(recipe)→RecipeCard;compileCookbook(recipes, metadata)→CookbookofCookbookChapters.scaling.ts— typed per-ingredient scaling rules (ScalingRule):linearScale,spiceScale,leaveningScale,yeastScale,eggScale,gelatinScale,sauceReductionScale;adjustCookingTime,adjustTemperature,adjustPanSize(PanSize);detectMinimumBatchanddetectMaximumBatch(BatchLimits);BUILT_IN_SCALING_RULES; the top-levelscaleRecipe(...).versioning.ts— Git-like recipe history:RecipeVersion,FieldChange(FieldChangeType=added/removed/modified),RecipeDiff;diffRecipes(a, b); theRecipeHistoryclass; three-way merge viamergeRecipes(base, theirs, mine)returningMergeResultwithMergeConflicts;forkRecipe(ForkInfo);RecipeLineage(LineageNode);generateChangelog(history)→ChangelogEntry[].search.ts—SearchFilters,SearchResult,NutritionConstraints;buildSearchTokens,calculateSimilarity(a, b),seasonalRecipes(recipes, month),personalizeResults(UserSearchProfile), and theRecipeIndexfull-text index class.collections.ts—CollectionManager,SmartCollection(SmartCollectionRule/SmartCollectionConfig),TagManager(Tag),FolderOrganizer(Folder),RecentlyCooked(CookingRecord),FavoritesManager(FavoriteEntry).
7.2 @hestia/cooking — guided cooking#
This library drives the active cooking experience. The GuidedCookingSession
class is the central stateful object — it holds the current step, tracks paused
time, and computes percentage progress. The TimerManager, VoiceSession, and
DonenessLibrary classes handle the supporting concerns that make a cooking
session workable without a free hand.
guided-cooking.ts—CookingStep(stepNumber,text,ingredients,equipment,technique?,duration?,temperature?,tips?,completed),GuidedCookingState,RecipeInput; theStepParserclass extracts equipment/technique/timing/temperature from instruction text; theGuidedCookingSessionclass drives a session —start(recipe),getCurrentStep,getProgress(0–100 % from completed steps), step navigation, and pause/resume tracking (paused,pausedAt,totalPausedMs).timers.ts—TimerState(idle/running/paused/completed),TimerAlert(none/sound/vibrate/both),CookingTimer(with optionalcascadeTimerIdfor chained timers),TimerPreset,TimerHistoryEntry; theTimerManager,TimerPresets, andTimerHistoryclasses.voice.ts—VoiceCommandTypeunion,VoiceCommand,SupportedLanguage(en/es/fr/de/it/ja/zh/ko); theVoiceCommandParser,TextToSpeechFormatter,VoiceSession, andMultiLanguageSupportclasses.doneness.ts—DonenessLevel(name,description,internalTemp?with min/max + unit,visualCues,touchTest?,timeGuide?),DonenessCategory(meat/bread/egg/vegetable/sauce/caramel/dough/emulsion),DonenessGuide; theDonenessLibraryclass with built-in USDA-referenced doneness guides (e.g. beef-steak rare → well-done).techniques.ts—TechniqueGuide,TechniqueProgress,Achievement; theTechniqueLibraryandTechniqueTrackerclasses.session-log.ts—SessionStatus(in_progress/completed/abandoned),CookingSession,SessionStep,SubstitutionLog; theSessionLoggerandSessionAnalyticsclasses.
7.3 @hestia/ingredients — ingredient intelligence#
The ingredient library is the scientific foundation of the platform. Its most
distinctive modules are flavor-compounds.ts and pairing.ts, which implement
the volatile compound overlap analysis that powers Hestia's non-obvious pairing
suggestions. The seasonality.ts module ties sourcing data to geographic region
and calendar month, enabling the meal planning layer to prioritize in-season
recommendations.
master-database.ts—IngredientDatabase,IngredientHierarchy(CategoryNode),AliasManager,StorageGuide(StorageInfo),SelectionGuide(SelectionCriteria),WasteCalculator;SEED_INGREDIENTSseed data.flavor-compounds.ts—CompoundCategory(volatile/taste/aroma),FlavorCompound,CompoundProfile,CompoundInteraction,MaillardProduct,FermentationProduct,SynergyPair; theFlavorCompoundDBclass plusSEED_COMPOUNDSandSEED_COMPOUND_PROFILES.pairing.ts—PairingBasis(compound/tradition/novel),PairingScore,TraditionalPairing,BeverageSuggestion,IngredientColor; thePairingEngineclass plusSEED_TRADITIONAL_PAIRINGS.substitution.ts—Substitution,MultiIngredientSubstitution,EmergencySubstitutionResult; theSubstitutionEngineclass.nutrition.ts— detailedNutrientProfilewithAminoAcidProfile,FattyAcidProfile,FiberDetail, andFodmapCategory/HistamineLevel/OxalateLevel/PurineLevelclassifications; theNutrientDatabaseclass plusSEED_NUTRIENT_PROFILES.seasonality.ts—SeasonalQuality(peak/good/fair),SeasonalData,FarmersMarket,CSABox,SustainabilityScore,CertificationInfo,FairTradeInfo,ForagingEntry; theSeasonalityDBandSourcingTrackerclasses.
7.4 @hestia/nutrition — nutritional analysis#
This library goes beyond label math. The key differentiator is
bioavailability.ts, which models the difference between what a food contains
on paper and what the body actually absorbs — accounting for nutrient
interactions, cooking method effects, and individual physiology. The
medical-diet.ts module covers eight clinically-named diet plans, and
goals.ts handles BMR/TDEE calculation and life-stage-specific nutrition
targets.
analysis.ts—calculateRecipeNutrition,perServingBreakdown,dailyValuePercent(against theFDA_DAILY_VALUESconstant),generateFDALabel(FDALabelData) andgenerateEULabel(EULabelData),nutrientDensityScore; theDailyIntakeTrackerandNutritionReportGeneratorclasses (MealEntry,DailyTotals,NutritionGoals,DayRecord,PeriodReport,TrendPoint).bioavailability.ts—ABSORPTION_FACTORStable;cookingImpact,nutrientInteraction,ironAbsorptionOptimizer,calciumAbsorptionFactors,vitaminCEnhancement,fatSolubleVitaminPairing,phytateOxalateImpact,personalizedBioavailability(PersonalFactors) — all returning typed absorption-score results.dietary.ts—DietaryProfile,DietRule,ComplianceResult; predicate functionsisVegetarian,isVegan,isPescatarian,isKosher,isHalal,isHinduCompliant,isJainCompliant,isBuddhistVegetarian,isRawFood,isPaleo,isKeto,isWhole30,isDASH,isMediterranean;checkCompliance,createCustomDiet,filterRecipes.allergen.ts—AllergenEntry,AllergenProfile,AllergenDetectionResult,SubstitutionSuggestion,AllergenCardData,ConflictInfo; theAllergenDetector,AllergenFilter, andAllergenMatrixclasses;generateAllergenCard(...).medical-diet.ts—MedicalDietPlanand eight built-in plans (DIABETIC_PLAN,RENAL_PLAN,CARDIAC_PLAN,GERD_PLAN,IBS_PLAN,CELIAC_PLAN,GOUT_PLAN,PKU_PLAN, indexed byMEDICAL_DIET_PLANS); theCarbCounterclass (CarbEntry,InsulinEstimate); IDDSI dysphagia levels (IDDSILevel,DysphagiaLevels,getIDDSILevel); theMedicationInteractionChecker;checkMedicalDietCompliance.goals.ts—NutritionGoal,ActivityLevel,UserPhysicalProfile; theGoalCalculator(BMR/TDEE/macro-ratio/weight-goal),GoalTracker,IntermittentFastingTracker, andSupplementRecommenderclasses; life-stage goal presets (PREGNANCY_GOALS,BREASTFEEDING_GOALS,PEDIATRIC_GOALS(age),SENIOR_GOALS,ATHLETE_GOALS,MUSCLE_BUILDING_GOALS).
7.5 @hestia/smart-kitchen — IoT orchestration#
The smart kitchen library abstracts over the fragmented kitchen device
ecosystem. Rather than integrating brand by brand, it defines capability-based
adapter interfaces — OvenAdapter, SousVideAdapter, ThermometerAdapter,
etc. — that any device can implement. The WorkflowEngine and
CookingOrchestrator classes sit on top of these adapters, enabling
event-driven automation and multi-device coordination.
devices.ts—DeviceCapability/DeviceTypeunions,DeviceStatus(online/offline/error/updating),SmartDevice,DeviceCommand,CommandStatus(queued/sent/acknowledged/completed/failed),FirmwareUpdateInfo; theDeviceRegistryclass.cooking-devices.ts— adapter interfaces + mock adapters + controllers for smart ovens (OvenAdapter/MockOvenAdapter/SmartOvenController,OvenCookingMode,OvenCookingProgram), sous-vide (SousVideAdapter/SousVideController,MultiBagSchedule), and pressure cookers (PressureCookerAdapter/PressureCookerController,PressureLevel,PressureCookingProgram,PressureReleaseType).sensors.ts—ThermometerAdapter/MockThermometerAdapterand theTemperatureMonitor(DonenessPrediction);ScaleAdapter/MockScaleAdapterand theSmartScaleController(BakersPercentResult,NutritionEstimate).smart-appliances.ts—RefrigeratorAdapter+SmartFridgeController(FridgeZone,ExpirationAlert,RecipeSuggestion);CoffeeMachineAdapterCoffeeController(CoffeeType,GrindLevel);CooktopAdapter+CooktopController(SafetyCheckResult).
automation.ts—TriggerType/ActionType(send_command/notify/start_timer/log/chain_workflow) unions;Workflow,WorkflowTrigger,WorkflowAction,WorkflowStep; theWorkflowEngineclass withWorkflowExecutionResultandWorkflowDebugResultdebug logging;WorkflowTemplates;SmartHomeIntegrationforSmartHomePlatformecosystems.orchestration.ts— multi-device meal coordination:ExecutionPlan/ExecutionPlanStep,CookingProgress,TimelineEntry; theCookingOrchestrator,DeviceScheduler(ScheduleConflict), andKitchenDashboard(DeviceOverview,ActiveOperation,DashboardAlert,EnergyUsage) classes.
7.6 @hestia/meal-planning — meal planning#
Meal planning connects the pantry (what you have), the budget (what you can
spend), the household (who you are cooking for), and the calendar (when you are
cooking). The suggestions.ts module is where these concerns meet — it uses
NutritionBalancer, IngredientOptimizer, and VarietyTracker together to
produce meal suggestions that are simultaneously nutritious, budget-conscious,
waste-reducing, and varied.
calendar.ts—MealSlot,RecurringMeal,SpecialOccasion,MealPrepSession; theMealCalendarandWeeklyViewclasses.household.ts—HouseholdMember,GuestInfo,DietaryException,ComponentMealPlan,KidFriendlyCriteria; theHousehold,ComponentMealPlanner,DietaryExceptionHandler, andKidFriendlyFilterclasses.suggestions.ts—MealRecord,VarietyScoreResult,NutritionAnalysis,NutritionGap,LeftoverPlan,WasteAnalysis; theVarietyTracker,NutritionBalancer,IngredientOptimizer, andContextualSuggesterclasses.budget.ts—FoodBudget,MealCostEstimate,SpendingRecord,BudgetComparison,Coupon,BulkBuyOpportunity; theBudgetManager,BulkBuyOptimizer,CouponManager, andBudgetSubstituterclasses.batch-cooking.ts—PrepTask,PrepSession,FreezerMeal,ThawEntry,BatchSauce,MarinadeSchedule; theBatchCookingPlanner,FreezerMealPlanner, andComponentPrepPlannerclasses.events.ts—EventCourse,EventMeal,BuffetPlan,PotluckPlan,CocktailPartyPlan,HolidayTemplate,GuestDietarySummary; theEventPlanner,HolidayTemplates, andEquipmentRentalAdviserclasses.
7.7 @hestia/pantry — pantry and inventory#
The pantry library manages physical food inventory from purchase through
consumption or disposal. A notable feature is grocery-store.ts, which ships
concrete adapters for Kroger, Target/Shipt, Whole Foods, and a generic fallback,
enabling one-click ordering directly from the shopping list. The equipment.ts
module tracks kitchen tools and maintenance schedules, feeding the feasibility
checker in @hestia/recipes.
inventory.ts—PantryLocation(pantry/fridge/freezer/counter/spice_rack,PANTRY_LOCATIONSarray),PantryItem; thePantryInventoryandBrandPreference(BrandRating) classes.scanning.ts—BarcodeType(UPC-A/UPC-E/EAN-13/EAN-8/QR),BarcodeResult,ProductInfo,ReceiptItem,ReceiptResult,ScanSession;calculateUPCCheckDigit,calculateEANCheckDigit,detectBarcodeType,validateBarcode; theProductDatabase,ReceiptParser,ManualEntryHelper, andBulkScannerclasses.expiration.ts—AlertLevel(info/warning/urgent/expired),WasteReason(expired/spoiled/excess/damaged),ExpirationAlert,WasteEntry/WasteReport,FreezingSuggestion,DonationSuggestion,CompostSuggestion; theExpirationManager,FIFOAdvisor, andWasteTrackerclasses.shopping.ts—ShoppingItem,AisleDefinition,StoreLayoutConfig,RecurringItem(RecurringFrequency=weekly/biweekly/monthly),SharedListInfo; theShoppingList,ShoppingListGenerator,StoreLayout,SharedList, andRecurringItemsclasses.grocery-store.ts—GroceryStoreAdapterinterface +BaseStoreAdapterabstract class, with concrete adaptersKrogerAdapter,TargetShiptAdapter,WholeFoodsAdapter,GenericStoreAdapter;Order/OrderStatus,CartItem/CartSummary,PriceComparison; thePriceComparator/EnhancedPriceComparator,OrderManager,OneClickOrderService, andDeliverySchedulerclasses.equipment.ts—EquipmentCategoryTypeunion,EquipmentEntry,MaintenanceTask/MaintenanceLog,UsageAnalysis,UpgradeRecommendation; theEquipmentRegistry,EquipmentMatcher,MaintenanceScheduler, andEquipmentRecommenderclasses.
7.8 @hestia/heritage — culinary heritage#
The heritage library digitizes and preserves culinary cultural memory. Its scope
is unusually broad: OCR-driven handwritten recipe capture, audio/video oral
history recording with transcription, a geographic archive of regional cuisines,
food history research with trade route data, and a full community moderation
workflow for community-submitted content. The community.ts module is
particularly detailed, covering expert verification, translation volunteers, and
reward catalogues for contributors.
family-recipes.ts— OCR-driven family-recipe digitisation:ScanSettings,OCRConfig/OCRResult/OCRBlock,RecipeStory,RecipePhoto/PhotoAlbum,AudioRecording/VideoRecording,FamilyMember/FamilyTree,Occasion(OccasionType),LegacyPreservationConfig(PreservationFormat),FamilyRecipeRecord; built-inOCR_CONFIGS,COMMON_OCCASIONS,PRESERVATION_PRESETS, and sample family data.oral-history.ts—AudioConfig/AudioSession,TranscriptionConfig/TranscriptionResult/TranscriptionSegment(TranscriptionEngine),VideoInterview,InterviewGuide/InterviewQuestion(QuestionCategory),Timeline/TimelineEvent,RecipeOriginMap/GeoLocation,MigrationStory,LanguageGlossary/CulinaryTerm,SharingConfig(SharingPermission).regional-archive.ts—RegionalCuisineRecord(CuisineRegionType),GeoRecipePin,HistoricalRecipe(HistoricalEra),TraditionalTechnique,IndigenousIngredient,SeasonalTradition,FestivalFood,ReligiousFoodPractice(ReligiousTradition),StreetFoodItem,EndangeredRecipe(EndangermentLevel); extensive seed databases plus region/era/city query helpers.food-history.ts—HistoricalCookbook,RecipeEvolution,IngredientHistoryEntry,CookingTechnology,TradeRoute,ColonialFoodImpact,ImmigrationFoodStory,FoodEtymology,HistoricalMenu,ResearchTopic(ResearchMethodology); large reference datasets with country/era/word query helpers.community.ts—SubmissionType/SubmissionStatus,CommunitySubmission,ReviewWorkflow/ReviewStage,Attribution/CreditPolicy,CommunityVote(VoteType)/VotingConfig,ExpertBadge/ExpertVerifier,CulturalConsultant,TranslationRequest/TranslationVolunteer,Moderator(ModeratorRole),Reward/RewardTier(RewardType),PartnerOrganization; preset workflows, policies, badges, and reward catalogues.
7.9 @hestia/sustainability — sustainability#
This library makes environmental impact measurable and actionable. It is organized around five interconnected concerns: carbon calculation, waste tracking, ethical sourcing scoring, seasonal/local sourcing, and composting guidance. Each module has substantial built-in reference data — the carbon database, transport emission factors, seafood sustainability ratings, and a Dirty Dozen/Clean Fifteen produce list are all embedded.
carbon-footprint.ts— enumsFoodCategory,TransportMode,SourcingDistance,PackagingMaterial,CookingMethodCarbon,WasteDisposalMethod,EnergySource,TimePeriod,OffsetCategory;IngredientCarbonEntry/RecipeCarbonResult,CarbonRating(A–F),CarbonBudget/CarbonBudgetProgress,CarbonOffsetProvider; theINGREDIENT_CARBON_DATABASE,TRANSPORT_EMISSION_FACTORS,COOKING_EMISSION_FACTORS,CARBON_OFFSET_PROVIDERSdatasets;calculateRecipeCarbon,calculateTransportCarbon,calculateCookingCarbon,calculateFoodWasteCarbon,calculateDailyCarbon/calculateWeeklyCarbon,generateCarbonReductionSuggestions,compareCookingMethods,findLowerCarbonSubstitutes,estimateAnnualFootprint.food-waste.ts— enumsWasteCategory,WasteReason,StorageLocation,WasteSeverity,WasteUnit,FoodGroup,AgeGroup,ActivityLevel,AnalyticsPeriod,ContainerType;WasteEvent,WasteReductionGoal/GoalProgress,UseItUpSuggestion,PortionRecommendation,RootToStemRecipe,NoseToTailRecipe,WasteDashboard; constantsCO2_PER_KG_WASTE,WATER_LITERS_PER_KG_WASTE;classifyWasteSeverity,createWasteEvent,calculateGoalProgress,estimatePotentialSavings,prioritizeByExpiration,computePeriodAnalytics,buildWasteDashboard,computeEnvironmentalImpact.ethical-sourcing.ts— enumsSeafoodRating,StockStatus,ImpactLevel,BycatchLevel,WelfareTier,TrustLevel,PalmOilSupplyChain,DeforestationRisk,HealthRisk,PesticideRanking,LaborProductCategory;SeafoodEntry,FishingMethod,WelfareRating,FarmCertification,FairTradeProgram,LaborPracticeInfo,PalmOilEntry,WaterFootprint,PesticideData,EthicalSourcingScore; seed databases pluslookupSeafood,getCertificationsForProduct,getDirtyDozen/getCleanFifteen,calculateEthicalSourcingScore,evaluateRecipeDeforestationRisk,calculateRecipeWaterFootprint.seasonal-local.ts— enums includingUSRegion,Month,ProduceCategory,FarmingPractice,CSAShareType,FoodTransportMode,PreservationMethod,BadgeTier;SeasonalIngredient,LocalFarm,FarmersMarket,CSAProgram,FoodMileResult,SeasonalRecipe,PreservationTechnique,LocalFoodChallenge,AchievementBadge; databases andgetInSeasonIngredients,findFarmersMarkets,calculateFoodMiles,compareLocalVsImported,suggestLocalSubstitutions,generateMonthlyGuide.composting.ts— enums includingCompostBinType,CompostabilityRating,CompostMaterialType,RecyclingMaterial,WormSpecies,BokashiPhase,MunicipalProgramType,ZeroWasteTipCategory;CompostBinGuide,CompostabilityItem,CompostProblem,VermicompostingGuide,MunicipalCompostingProgram,ZeroWasteTip; databases plusdiagnoseCompostProblem,calculateCompostMixRatio(carbon:nitrogen),recommendCompostingMethod,getWasteDisposalRecommendation.
7.10 @hestia/education — culinary education#
The education library provides structured culinary learning from beginner
techniques through food science to professional certifications. The progression
system uses XP points and skill trees to sequence learning logically. The
interactive.ts module is the most forward-looking, covering AR technique
overlays, virtual kitchen simulations, spaced-repetition flashcards, and an
expert critique marketplace.
techniques.ts—TechniqueCategoryunion;Techniqueand the specialisedKnifeSkill,HeatTechnique,BakingTechnique,SauceTechniqueinterfaces; built-in curriculaKNIFE_SKILLS_CURRICULUM,HEAT_TECHNIQUES_CURRICULUM,BAKING_FUNDAMENTALS,SAUCE_MASTERS,FERMENTATION_TECHNIQUES,PRESERVATION_TECHNIQUES;getPrerequisiteChain,suggestNextTechnique.progression.ts—SkillLevel(novice/apprentice/journeyman/expert/master),Badge,Challenge/ChallengeCriterion,SkillTree/SkillNode,LearnerProfile,Assessment,LearningPath; XP math (calculateLevel,xpToNextLevel,getLevelProgress,awardXp);ALL_BADGES;buildSkillTree,evaluateChallenge, four built-in paths (BEGINNER_PATH,INTERMEDIATE_PATH,ADVANCED_PATH,PROFESSIONAL_PATH).food-science.ts—ScienceTopicunion,ScienceLesson(withLessonSection,Experiment,FoodScienceQuestion,Diagram,TemperatureDataPoint); 15 built-in courses includingMAILLARD_REACTION_COURSE,CARAMELIZATION_COURSE,PROTEIN_DENATURATION_COURSE,EMULSION_SCIENCE_COURSE,FERMENTATION_BIOLOGY_COURSE,STARCH_GELATINIZATION_COURSE;generateQuiz.cuisine.ts—CuisineRegionunion,CuisineModule(KeyIngredient,SignatureDish,FlavorProfile); 20 built-in cuisine modules (FRENCH_CUISINE,ITALIAN_CUISINE,JAPANESE_CUISINE,INDIAN_CUISINE, etc.);getSimilarCuisines,getByFlavorProfile.certifications.ts—CertificationCategory/CertificationLevel(entry/intermediate/advanced/expert),CertificationProgram(ExamSection,PracticeQuestion,StudyPlan); built-in programsFOOD_HANDLER_CERT,SERVSAFE_CERT,HACCP_CERT,SOMMELIER_CERT,CICERONE_CERT,BARISTA_CERT,CHEESE_PROFESSIONAL_CERT,NUTRITION_CERT,PERSONAL_CHEF_CERT,CULINARY_COMPETITION_PREP;generatePracticeExam.interactive.ts—VideoLesson,RecipeWalkthrough(WalkthroughStep,WalkthroughStepType),ARTechniqueOverlay(AROverlayType,ARMarker),VirtualKitchenConfig(KitchenStationType,SimulationScenario),QuizConfig(QuizQuestion,AssessmentResult),SpacedRepetitionDeck(FlashCard,ReviewSchedulewithcalculateNextReview),PracticeAssignment(GradingRubric),ExpertCritiqueMarketplace(ExpertProfile,CritiqueRequest); built-inVIDEO_LESSONS,RECIPE_WALKTHROUGHS,AR_OVERLAYS,VIRTUAL_KITCHENS,QUIZ_BANK.
7.11 @hestia/professional — professional kitchen tools#
Each module in this library exports an extensive prefixed type set and a flat
function API backed by in-memory stores (with reset*Stores() and
load*SampleData() helpers for test isolation). The prefixed naming convention
(MC*, KW*, INV*, FS*, CT*, RD*) prevents type name collisions across
what is otherwise a very large surface area covering six distinct professional
domains.
menu-costing.ts—MCIngredientCost,MCRecipeCost,MCFoodCostMetrics,MCPricingSuggestion,MCProfitAnalysis,MCCostTrend,MCLaborCost,MCMenuItem(MCMenuCategory=star/plow-horse/puzzle/dog),MCMenuEngineeringReport;calculateRecipeCost,calculateFoodCostPercentage,getOptimalSellingPrice,suggestPricing,analyzeProfitMargin,classifyMenuItems,generateMenuEngineeringReport.kitchen-workflow.ts—KWKitchenStation(KWStationType),KWPrepItem(KWPrepType),KWMiseEnPlace,KWServiceOrder(KWOrderStatus),KWKitchenTicket(KWTicketPriority/KWTicketStatus),KWKDSConfig/KWKDSScreen,KWExpoView,KWCookTimeBenchmark,KWShift;optimizeAssignments,generatePrepList,generateMiseEnPlace,coordinateCourses, KDS/expo views,identifyBottlenecks,generateShiftReport.inventory-management.ts—INVInventoryItem(INVStorageLocation,INVItemCategory),INVParLevel,INVAutoOrderRule/INVAutoOrderEvent,INVSupplier/INVSupplierPerformance,INVPurchaseOrder(INVPOStatus),INVReceivingRecord,INVInventoryCount(INVCountType),INVVarianceReport,INVFIFOBatch,INVWasteLog(INVWasteType); par-level checks, auto-ordering, PO lifecycle, receiving, variance counts, FIFO batches, waste/shrinkage analysis.food-safety.ts—FSHACCPPlan(FSPlanStatus),FSCriticalControlPoint(FSHazardType,FSCCPStatus,FSCCPReading),FSTempLog/FSTempZone,FSCorrectiveAction,FSCleaningTask/FSCleaningRecord,FSSanitizationTest,FSAllergenProfile,FSSupplierVerification,FSAuditEntry,FSInspectionReport(FSFindingSeverity,FSInspectionStatus); CCP monitoring, temperature logging, corrective actions, cleaning/sanitation compliance, allergen matrix, supplier verification, audit trail,calculateComplianceScore.catering-events.ts—CTCateringQuote(CTQuoteStatus),CTEventMenu/CTCourse,CTScalingResult,CTDietaryProfile/CTAccommodationReport,CTEquipmentRental(CTRentalStatus),CTStaffingPlan,CTEventTimeline,CTVenueInfo,CTTransportPlan,CTEventInvoice(CTInvoiceStatus),CTRevenueReport; quote lifecycle, menu scaling per service style, dietary accommodation, rentals, staffing, timelines, invoicing, revenue reporting.recipe-development.ts—RDProject(RDProjectStatus),RDTestBatch(RDTestBatchOutcome),RDIteration,RDTastingPanel/RDTastingScores,RDCostOptimization,RDShelfLifeTest,RDNutritionAnalysis,RDScaleTest,RDProductionDoc,RDApprovalRequest(RDApprovalStatus); project status machine, test-batch logging, iteration diffing, tasting panels, cost/shelf- life/nutrition/scale testing, production docs, multi-reviewer approval.
7.12 @hestia/social — social cooking#
The social library covers the full spectrum of community cooking — from recipe
publishing with an attribution chain (tracking forks and remixes back to the
original author) through live cook-along events with synchronized timers and
chat, to family cookbook management and community challenges with a state
machine from draft → open → closed → judging → completed.
recipe-sharing.ts—RecipeStatus(draft/in_review/published/unpublished/scheduled),DraftRecipe/PublishedRecipe,RecipeProfile,FeedItem/FeedConfig/PaginatedFeed(FeedSortMode),AttributionChain/AttributionNode,RemixRecord(RemixType),RecipeLicense(LicenseType),FeaturedCollection,TrendingScore,RecipeCategory,Hashtag; the draft→review→publish workflow,forkRecipe/createRemix, attribution chains, trending scores, category tree, hashtags.profiles-following.ts—UserProfile(SkillLevel),FollowRelationship,ActivityItem(ActivityType),ProfileTheme,CookingStats/HeatmapEntry,Achievement(AchievementCategory/AchievementRarity),Badge(BadgeCategory/BadgeTier),VerificationApplication(VerificationStatus),CreatorSubscription/TierConfig(MonetizationTier),PrivacySettings(PrivacyLevel); follow graph, activity feeds, cooking stats/heatmap, achievements/badges, chef verification, creator monetization, privacy and blocking.ratings-reviews.ts—RecipeRating(RatingSubScores),RecipeReview,ReviewPhoto(ReviewPhotoType),HelpfulVote,ReviewModerationRecord(ReviewModerationStatus,ReviewContentFlag),ReviewResponse,AggregatedRating,CookPhoto,ModificationNote(ModificationCategory),VerifiedCook(CookVerificationMethod); 1–5★ ratings with sub-scores, reviews with photos, helpful voting, moderation (autoModerate), responses, rating aggregation, cook verification.cook-alongs-events.ts—CookAlongEvent(CookAlongEventStatus=scheduled/live/completed/cancelled),EventCalendar/CalendarEntry,StreamSession(StreamQuality,StreamStatus),ChatMessage(ChatMessageType),EventParticipant(ParticipantRole/ParticipantStatus),EventRecording/RecordingChapter,EventReminder(ReminderType),IngredientKit/KitOrder,TimezoneInfo,EventAnalytics/HostDashboard; event lifecycle, calendars, live streams, chat, participants, recordings, reminders, ingredient kits, cross-timezone scheduling.family-cookbook.ts—FamilyGroup/FamilyMember(FamilyMemberRole,FamilyRelationship),FamilyCookbook(FamilyCookbookSection),ContributionRequest(FamilyContributionStatus),FamilyPermission,FamilyComment,CookingHistoryEntry(FamilyCookingOccasion),PrintedCookbook(PrintLayout),FamilyTreeNode,RecipeInheritance(InheritanceRule/InheritanceCondition),FamilyCookingChallenge; family groups with invite codes, shared cookbooks, contribution review, comments, cooking history, print export, recipe inheritance, family challenges.community-challenges.ts—CommunityChallenge(ChallengeType,ChallengeStatus),ChallengeTemplate/ChallengeThemedTemplate,ChallengeSubmission(ChallengeSubmissionStatus),ChallengeVotingConfig/CommunityVote(ChallengeVotingMethod),ChallengeLeaderboardEntry,ChallengePrize(ChallengePrizePlace/ChallengePrizeType),CommunityBadge(ChallengeBadgeRarity),ChallengeAnalytics,CommunitySponsor/CommunitySponsorDeal; the challenge lifecycle state machine (draft → open → closed → judging → completed, pluscancelled), templates/themes, submissions, voting + judge panels, leaderboards, prizes, badges, analytics, sponsorships.
7.13 @hestia/ai-ml — AI / ML intelligence#
The AI/ML library sits at the top of the dependency graph because it relies on
the data and types from every other library. Recipe generation is not free-form
LLM output — it is constrained by real IngredientProfile data, real
ConstraintSet objects from the domain model, and domain-specific critique
logic. The recommendations module implements three exploration strategies
(epsilon-greedy, UCB1, Thompson sampling) for the multi-armed-bandit component
of personalization. The predictive analytics module includes a full set of
statistical primitives implemented from scratch in TypeScript.
recipe-generation.ts—GeneratedRecipe(GeneratedIngredient,GeneratedStep),GenerationConfig,PromptTemplate,CuisineProfile,RecipeTemplate,ConstraintSet,RecipeCritique/CritiqueResult,FusionResult,VariationResult,SeasonalOptimizationResult,BudgetOptimizationResult,TimeOptimizationResult;generateFromIngredients,generateWithConstraints,generateByStyle,generateFusion,generateHealthierVersion,optimizeForBudget/Time/Season,generateVariation,completePartialRecipe,critiqueRecipe,transformRecipeCuisine,suggestCompleteMeal,scoreIngredientMatch,estimateRecipeNutrition.flavor-pairing.ts—FlavorCategory,CompoundClass,PairingStrength(strong/moderate/weak/clash) unions;VolatileCompound,IngredientProfile,PairingScore,PairingExplanation,CulturalPairingRule,AntiPairing,BridgeSuggestion,ContextPairing,PairingGraph(PairingNode/PairingEdge),UserFeedback,NovelPairingResult;computePairingScore,topPairingsFor,discoverNovelPairings,findBridgeIngredients,checkAntiPairing,buildPairingGraph,findClusters,shortestFlavorPath, theFeedbackStoreclass.image-recognition.ts—DishCategory,DonenessLevel,PortionSize,PlatingStyle,FreshnessLevel,BarcodeFormat,IngredientStateunions;DishRecognitionResult,IngredientDetectionResult,PortionEstimate,PlatingAnalysis,DonenessResult,QualityAssessment,NutritionFromImage,BarcodeData,NutritionLabel,HandwrittenRecipeOCR,MenuParseResult;recognizeDish,identifyIngredients,estimatePortionSize,analyzePlating,detectDoneness,assessFoodQuality,estimateNutritionFromImage,parseBarcode,parseNutritionLabel,processHandwrittenRecipeOCR,parseMenuImage,detectMultipleDishes.recommendations.ts—RecipeFeatures,UserProfile,TasteProfile,RecommendationResult,ScoringWeights,ContextSignal,HouseholdPreferences,ExplorationConfig,RecommendationPipeline;RecommendationMethodandExplorationStrategy(epsilon-greedy/ucb1/thompson-sampling) unions; collaborative filtering (getCollaborativeRecommendations), content-based (getContentBasedRecommendations),getHybridRecommendations,buildTasteProfile, multi-armed-bandit exploration (epsilonGreedySelect,applyUCB1Exploration), context/health/skill-aware recommendations,getHouseholdRecommendations,runRecommendationPipeline,diversifyResults.nlp.ts—ChatIntent,Sentiment,SupportedLanguage,CutStyleunions;RecipeSearchFilter,CookingQAPair,ParsedIngredient,TechniqueExplanation,SubstitutionEntry,MultilingualTerm,RecipeSummary,SentimentResult,ChatResponse,TokenizedText;tokenize,computeRelevanceScore,parseRecipeSearchQuery,answerCookingQuestion,clarifyRecipeInstructions,parseIngredient,explainTechnique,handleSubstitutionQuery,translateCookingTerm,summarizeRecipe,analyzeReviewSentiment,processChatMessage.predictive-analytics.ts—MealLogEntry,GroceryPurchase,CookingSession,RecipeAttempt,IngredientStorage,HouseholdDemand,SkillRecord,FeatureUsageLoginput types andMealPrediction,GroceryPrediction,CookingTimePrediction,RecipeSuccessPrediction,SpoilagePrediction,DemandForecast,NutritionGoalPrediction,BudgetPrediction,SkillProgressionPrediction,FeatureEngagementPredictionoutput types; statistical primitives (mean,variance,standardDeviation,simpleMovingAverage,exponentialMovingAverage,linearRegression,bayesianBetaUpdate,holtLinearSmoothing,sigmoid,percentile); predictorspredictMealPreference,predictGroceryNeeds,predictCookingTime,predictRecipeSuccess,predictIngredientSpoilage,forecastMealDemand,predictNutritionGoalAchievement,predictBudgetAdherence,predictSkillDevelopment,predictFeatureEngagement,generatePredictiveDashboard.
8. API Application (apps/hestia/api)#
@hestia/api is a Fastify service that exposes both a versioned REST API and a
GraphQL API. Project tags are ["scope:hestia", "type:app", "layer:service"].
It depends on @hestia/core, @oshun/errors, @oshun/logging, fastify,
graphql + graphql-yoga, drizzle-orm, pg, ioredis, zod, nanoid, and
bcryptjs.
8.1 Server composition#
The server is assembled in a fixed plugin registration order that ensures each
concern is in place before the next one needs it. The buildServer / entry
point separation keeps server.inject() testing simple — the factory function
never binds a port.
buildServer({ config }) (src/app.ts) creates a Fastify instance and
registers plugins in a fixed order: request-context, cors, error-handler,
swagger, auth (JWT), database (PostgreSQL + Drizzle), redis,
rate-limit, graphql, then routes. It installs SIGINT/SIGTERM graceful
shutdown. server.ts calls .listen(); buildServer itself does not bind a
port, which keeps server.inject() testing simple.
8.2 Configuration (config.ts)#
loadConfig(env) parses process.env with a Zod schema and fails fast on
mis-configuration. The key variables and their defaults are:
PORT (3040), HOST (127.0.0.1), NODE_ENV (development), JWT_SECRET,
JWT_ISSUER (hestia-api), JWT_ACCESS_TOKEN_TTL (900 s),
JWT_REFRESH_TOKEN_TTL (604800 s), DATABASE_URL, DB_POOL_MIN (2),
DB_POOL_MAX (10), REDIS_URL, RATE_LIMIT_MAX (100), RATE_LIMIT_WINDOW_MS
(60000), LOG_LEVEL (info), METRICS_PORT (9094), CORS_ORIGIN (*),
AI_API_KEY, AI_MODEL (gpt-4), SESSION_MAX_PER_USER (10). Cross-field
rules: in production the default JWT_SECRET is rejected, and DB_POOL_MIN
must not exceed DB_POOL_MAX. The result is the typed AppConfig
(src/types.ts).
8.3 Shared API types (types.ts)#
The types file augments Fastify's request/server instances and defines the
shared shapes that every route handler and plugin uses. The HestiaPermission
union is the complete list of fine-grained permissions enforced throughout the
API.
AuthenticatedUser (id, email, roles[], permissions[]),
RequestContext (requestId, correlationId, startTime), CacheHelper
(typed JSON cache over Redis), HealthCheckResponse (HealthStatus =
ok/degraded/unhealthy), ApiErrorResponse
({ error: { code, message, details?, requestId? } }), ApiInfoResponse,
PaginatedResponse<T>, Session, ApiKey, RefreshTokenRecord. HestiaRole
is owner | admin | contributor | viewer; HestiaPermission is a 19-value
union (recipe:read/write/delete/publish, ingredient:read/write,
meal_plan:read/write, shopping:read/write, pantry:read/write,
nutrition:read, cooking:read/write, social:read/write, ai:use,
admin:manage). Fastify is augmented with request.ctx, fastify.db,
fastify.dbPool, fastify.redis, fastify.cache, and fastify.authenticate.
8.4 REST surface#
registerRoutes (src/routes/index.ts) mounts health probes unprefixed and
everything else under /v1. GET /v1/info (authenticated) returns API metadata
listing the 10 functional domains.
Health (/health*, no auth) — GET /health (liveness), GET /health/ready
(readiness), GET /health/startup (startup probe).
Auth (/v1/auth) — POST /register, POST /login, POST /refresh
(refresh-token rotation, RefreshTokenRecord family tracking), POST /logout,
GET /sessions (list active sessions), POST /api-keys, GET /api-keys,
DELETE /api-keys/:id. Passwords are hashed with bcryptjs; access/refresh
JWTs use the configured TTLs.
Recipes (/v1/recipes) — GET / (list own recipes, paginated, filterable
by cuisine/mealType/difficulty/status), POST / (create), GET /search (text +
cuisine/mealType/maxCookTime/dietary/ingredients), GET /:id, PUT /:id
(author only; bumps version), DELETE /:id (author only), POST /import
(from url or text), POST /:id/scale (linear ingredient scaling),
GET /:id/nutrition (category-keyword nutrition estimate). Request bodies are
validated by Zod schemas; the RecipeRecord shape mirrors the hestia_recipes
columns. Errors use ApiErrorResponse codes such as RECIPE_NOT_FOUND,
FORBIDDEN, IMPORT_SOURCE_REQUIRED.
Ingredients (/v1/ingredients) — GET /search, GET /seasonal,
GET /:id, GET /:id/substitutions.
Meal plans (/v1/meal-plans) — GET /, POST /, POST /generate (weekly
plan), GET /current-week, GET /:id, PUT /:id, DELETE /:id,
GET /:id/shopping-list.
Shopping (/v1/shopping) — GET /, POST /, POST /generate (from a meal
plan), GET /:id, DELETE /:id, PATCH /:id/items/... (toggle purchased),
POST /:id/share.
Pantry (/v1/pantry) — GET / (inventory), POST / (add item),
PATCH /:id (update quantity), DELETE /:id, GET /expiring,
GET /recipe-suggestions.
Nutrition (/v1/nutrition) — POST /calculate (nutrition for an ingredient
list), GET /daily (daily summary), POST /log (log a meal), GET /goals,
PUT /goals.
Cooking (/v1/cooking) — POST /sessions (start a session),
GET /sessions (list), GET /sessions/:id (status), PATCH /sessions/:id/step
(advance step), POST /sessions/:id/timer (add timer, ≤ 24 h),
PATCH /sessions/:id/complete (rating 1–5 + feedback).
Preferences (/v1/preferences) — GET/PUT / (food preferences),
GET/PUT /allergies, GET/PUT /dietary-restrictions.
Social (/v1/social) — POST /recipes/:id/rate,
POST /recipes/:id/review, GET /recipes/:id/reviews, POST /collections,
GET /collections, GET /collections/:id, POST /collections/:id/recipes,
DELETE /collections/:id/recipes/:recipeId, DELETE /collections/:id.
AI (/v1/ai) — POST /generate-recipe (from ingredients),
POST /substitutions, POST /meal-plan (AI meal plan), POST /chat (culinary
assistant chat).
8.5 Cooking-session state machine (REST)#
The cooking-session routes drive a four-state lifecycle. The state transitions are:
POST /sessions— creates a session directly inin_progress, materialises one step record per recipe step, and starts step 1.PATCH /sessions/:id/step— requiresstatus === 'in_progress', marks the current stepcompleted, advancescurrentStep, and stamps the next step'sstartedAt.PATCH /sessions/:id/complete— records the final rating (1–5) and feedback, then transitions tocompleted.- Any step or timer mutation on a non-active session returns
SESSION_NOT_ACTIVE.
The full state machine on CookingSessionRecord.status: planned →
in_progress → completed / cancelled.
8.6 GraphQL API#
The GraphQL plugin (src/graphql/index.ts) serves a GraphQL Yoga endpoint at a
single URL alongside the REST API. The schema is defined in
src/graphql/schema.ts with resolvers organized by domain under
src/graphql/resolvers/ (recipe, ingredient, meal-plan, pantry,
nutrition, cooking-session).
Scalars — DateTime, JSON.
Enums — MealType, Difficulty, CookingMethod (35 values),
MeasurementUnit (24 values), DietaryRestriction (20 values), Allergen (14
values), RecipeStatus, Visibility, IngredientCategory, InventoryStatus,
SessionStatus, ShoppingItemStatus.
Object types — Recipe (with RecipeIngredient, RecipeStep),
Ingredient (with FlavorProfile, NutritionalData), NutritionAnalysis
(with NutritionPerServing, IngredientNutrition, DailyValuePercentages),
MealPlan / MealPlanMeal, PantryItem, ShoppingList / ShoppingItem,
CookingSession, UserPreferences, FlavorCompound, IngredientPairing.
Pagination — Relay-style PageInfo, RecipeConnection/RecipeEdge,
IngredientConnection/IngredientEdge. Result helper types DeleteResult,
BatchResult/BatchError, GeneratedShoppingList.
Input types — RecipeFilter, IngredientFilter, PantryFilter,
PaginationInput, CreateRecipeInput/UpdateRecipeInput,
RecipeIngredientInput/RecipeStepInput, CreateMealPlanInput/
UpdateMealPlanInput/MealPlanMealInput, AddPantryItemInput/
UpdatePantryItemInput, CreateShoppingListInput/ShoppingItemInput,
BatchDeleteInput.
Query — recipe, recipes, searchRecipes, ingredient, ingredients,
mealPlan, mealPlans, pantryItems, shoppingLists, shoppingList,
cookingSession, activeCookingSessions, nutritionAnalysis,
ingredientPairings, flavorCompounds, userPreferences.
Mutation — recipe CRUD + batchDeleteRecipes; meal-plan CRUD +
generateShoppingListFromMealPlan; pantry addToPantry/updatePantryItem/
removePantryItem; shopping createShoppingList/checkShoppingItem/
uncheckShoppingItem/deleteShoppingList; cooking-session
startCookingSession/advanceCookingStep/completeCookingSession/
cancelCookingSession.
Subscription — cookingSessionUpdated(sessionId) →
CookingSessionUpdate; pantryItemExpiring(userId) → PantryExpirationAlert.
8.7 GraphQL authorization (graphql/permissions.ts)#
The GraphQL authorization layer enforces the same domain rules as
@hestia/core/auth.ts but at the resolver level, translating them into
GraphQL-specific patterns. Public recipe visibility is an important special
case: published-public recipes are visible to unauthenticated users, which is
intentional for SEO and sharing.
A PERMISSIONS constant defines 16 permission strings (recipe:read/write/
delete/publish, ingredient:read/write, meal_plan:read/write,
shopping:read/write, pantry:read/write, nutrition:read,
cooking:read/write, admin:manage). canViewRecipe makes published-public
recipes visible to everyone, requires authentication otherwise, grants admins
and authors full visibility, and exposes published-household recipes to any
authenticated user. assertCanModifyRecipe, assertCanDeleteRecipe,
assertCanPublishRecipe enforce author-or-admin ownership;
assertCanModifyIngredient restricts shared-ingredient writes to admins;
assertCanAccessMealPlan / …PantryItem / …ShoppingList / …CookingSession
enforce owner-or-admin access on user-owned resources via requireOwnership.
9. Web Application (apps/hestia/web)#
@hestia/web is a Next.js (App Router) application; project tags
["scope:hestia", "type:app", "platform:web"]. It runs on port 3011 and depends
on @hestia/core, @tanstack/react-query, zustand, next, react,
lucide-react, tailwind-merge, and date-fns.
The web application uses Next.js route groups to cleanly separate unauthenticated pages (login, register) from the authenticated application, which spans recipe management, meal planning, cooking, and a full admin console.
- Route groups —
(auth)holdsloginandregister;(app)holds the authenticated application. App routes coverrecipes(list,new,import,bulk,collections,analytics, and per-recipeview/edit/print/versions),meal-plans(calendar plusauto-plan,budget,events,household,nutrition,prep,slots,templates),pantry(alerts,budget,bulk,equipment,expiration,reports),shopping(compare,history),cooking,nutrition,learn(courses, lessons, quizzes,skills,progress,certificates,bookmarks,discussions,instructor),community(challenges,connections,events,messages,moderation,notifications,reviews,report, per-user profiles), anadminconsole (analytics,api-keys,audit,config,features,health,ingredients,moderation,nutrition,users), andsettings. - Data layer —
src/lib/api-client.ts,src/lib/query-client.ts, and feature hooks undersrc/hooks/(useAuth,useCooking,useMealPlans,useNutrition,usePantry,useRecipes,useShopping). Client state lives in Zustand stores (app-store,auth-store,cooking-store). - Testing — Vitest component/integration tests under
src/__tests__/and Playwright end-to-end specs undere2e/(auth,community,cooking,meal-plans,navigation,recipes,search,shopping).
10. Mobile Application (apps/hestia/mobile)#
@hestia/mobile is an Expo / React Native application named "Hestia — Culinary
Intelligence Mobile App". It depends on expo, react-native, React Navigation
(native-stack + bottom-tabs), @tanstack/react-query, zustand,
expo-notifications, expo-secure-store, and
@react-native-async-storage/ async-storage.
The mobile app covers all the same functional areas as the web app, organized
into native screens. A notable mobile-specific feature is the offline layer
(OfflineManager + OfflineIndicator), which is essential given that mobile
cooks may be in kitchens with poor connectivity.
- Screens —
auth(Login, Register);recipes(List, Detail, Editor, Search, Collections);cooking(CookingSession, StepByStep, Timer);camera(IngredientIdentify, RecipeScan);meal-plan(Week, Day, Generate);nutrition(Dashboard, Daily, Goals);shopping(ShoppingList, Pantry, ExpiringItems);iot(SmartKitchen);social(SocialFeed, Reviews, SharedCollections);settings(Settings, Preferences, Allergies, About). - Data layer —
src/api/client.ts,src/api/queryClient.ts, and hooks undersrc/api/hooks/(useAuth,useCooking,useMealPlans,useNutrition,usePantry,useRecipes,useShopping). Zustand stores (appStore,authStore). An offline layer (src/services/offline/,OfflineManager+OfflineIndicator) supports disconnected use. - Navigation and theme —
AppNavigatorplus deep-linklinkingconfiguration; a shared UI component set (Button,Card,Input,Modal,BottomSheet, etc.) and atheme/(colors, spacing, typography).
11. Build and Tooling#
The build configuration is consistent across all Hestia components. Libraries
use tsc directly (no bundler) and ship ESM. The API uses tsx watch for
development and node dist/server.js in production. The web app uses Next.js
dev/build scripts via Nx run-commands wrappers on port 3011.
- Libraries —
@nx/js:tscbuild,@nx/eslint:lintlint,@nx/vite:test(Vitest) test;"type": "module"ESM; tags["scope:hestia", "layer:domain", "type:lib"]. - API — Nx
nx:run-commandstargets:build(tsc),dev(tsx watch src/server.ts),start(node dist/server.js, depends on build),lint,test(vitest run),typecheck(tsc --noEmit). - Web — Nx
nx:run-commandstargets wrappingnext dev/next build(port 3011), plus Vitest and Playwright. - Mobile — Expo scripts (
expo startand platform variants),jest/jest-expofor tests.
12. Integration Points#
12.1 Internal dependencies#
The web and mobile clients do not import feature libraries directly — they consume the API over HTTP. This keeps client bundles lean, centralizes authorization in the API, and lets the mobile offline layer cache API responses rather than managing library state directly.
| Component | Depends on |
|---|---|
| All feature libraries | @hestia/core (peer) |
@hestia/api |
@hestia/core, @oshun/errors, @oshun/logging |
@hestia/web |
@hestia/core |
@hestia/web tests |
@oshun/testing |
12.2 Infrastructure and external systems#
| System | Use |
|---|---|
| PostgreSQL | Primary store via Drizzle ORM; pool sized by DB_POOL_MIN/MAX |
| Redis (ioredis) | Caching layer and rate-limit backing store for the API |
| Recipe Schema.org JSON-LD | Recipe import/export format (@hestia/recipes import-export.ts) |
| USDA FoodData Central | Nutritional reference data model (@hestia/ingredients/nutrition) |
| Grocery store integrations | Kroger, Target/Shipt, Whole Foods, and generic adapters in @hestia/pantry |
| Smart-home ecosystems | SmartHomeIntegration targets in @hestia/smart-kitchen |
13. V2 Cross-Domain Contract#
13.1 V2 Recipe-As-Mini-Game-Script Embedding Surface#
The V2 Recipe-As-Mini-Game-Script Embedding Surface lets the separate V2
(fighting-game) program embed Hestia recipe intelligence as a cooking mini-game
without duplicating any recipe, ingredient, or pantry logic. The adapter is
published as @v2/hestia-cooking-minigame-bridge
(apps/v2/hestia-cooking-minigame-bridge) and composes six Hestia libraries at
workspace:*: @hestia/ai-ml (recipe generation via
generateFromIngredients), @hestia/cooking (GuidedCookingSession and
getWalkthroughByDifficulty), @hestia/education, @hestia/ingredients (the
IngredientDatabase), @hestia/pantry (the PantryInventory and
getKitchenByType), and @hestia/core.
The bridge emits a hestia.recipe-as-mini-game-script manifest — a recipe
compiled into the script a V2 cooking mini-game runs — targeting the
V2Mode_Cooking runtime and surfacing in the V2Mode_BattleHub cabinet. The
manifest is built from real ingredient match ratios and pantry sourcing; recipe
generation with no candidates, a poor ingredient match ratio, or incomplete
pantry sourcing produce explicit manifest failures rather than fabricated
scripts.
This surface is off rollback. Hestia remains the source of truth for recipe,
ingredient, and pantry data, and the bridge guards every call with a
calledFromLiveCookingFrame check (rejectsLiveCookingFrameRpc: true,
mayInfluenceRollback: false): it must never run inside a deterministic combat
or cooking simulation frame, and it must never feed rollback inputs. The
integration contract is specified in full at
V2/docs/integration/hestia-cooking-minigame-bridge.md.