Building Sorrel
2025-08-20
Sorrel is a pantry-aware cooking app, and the interesting engineering problem isn't generating recipes. It's the data model that connects ingredients, recipes, and a user's actual pantry into something useful. The core relationship is a three-way join: ingredients exist as canonical entities, recipes reference those ingredients with quantities, and a user's pantry tracks what they have on hand with approximate amounts. The matching algorithm has to balance what you have against what you need, and the answer is rarely a binary yes or no.
The matching logic scores recipes on a 0-1 scale based on pantry coverage. A recipe that needs 8 ingredients where you have 6 scores 0.75, but that number alone isn't enough. I weight by ingredient importance: missing salt is trivial, missing the protein is a dealbreaker. Each ingredient in a recipe has an importance flag, and the algorithm penalizes missing critical ingredients more heavily. A recipe scoring 0.6 with all critical ingredients present ranks higher than one scoring 0.8 that's missing the main component. This sorting feels natural when you browse results. The recipes that bubble up are the ones you can actually cook tonight with maybe one quick substitution.
The taste profile is the part I find most compelling. Rather than asking users to fill out preference surveys, Sorrel builds a profile implicitly from cooking history. Every recipe you cook, rate, or save contributes signal. If you consistently cook dishes with cumin, smoked paprika, and lime, the system learns that flavor cluster. Over time it weights recipe suggestions toward your demonstrated preferences, not your stated ones. People are terrible at articulating what they like to eat, but their cooking history doesn't lie. The profile is a vector of flavor affinities that evolves with every interaction.
Substitution handling rounds out the model. When a recipe calls for an ingredient you don't have, Sorrel suggests substitutions drawn from a compatibility matrix. This isn't just "use butter instead of margarine." It considers the role of the ingredient in the recipe: structural, flavor, textural. A binding agent substitution is different from a garnish substitution. The matrix is seeded from culinary knowledge and refined by user feedback when they report whether a substitution worked. It's a small feature that makes the difference between an app you check once and one you actually cook from.