Where you start with a list of all the nodes (ingredients)
Have a n:1 relationship with the next series of nodes (steps)
until you finish at a single node (the dish you're trying to make)
So instead of having a separate chunk of "here's my ingredients" and "let me repeat the ingredients and one by one instruction until the end" I figure you can display the upside-down tree to convey more information with less words.
An example being https://cookbook.cstebbins.com/recipe/bul-koki
With the underlying tree structure looking like https://assets.cstebbins.com/cookbook/images/bulkokiTree.png
(And it's not even necessarily acyclic, because eg sourdough or master stock is perhaps best modelled as a cycle.)
In any case, looking at a recipe as a tree or a graph is a very limited view:
A great recipe isn't a list of steps to produce 'something'. A great recipe has a dish in mind with a specific taste (or a specific family of tastes with knobs you can turn), and the author has worked out what parts of the recipe you need to adapt in what ways to compensate or take advantage of current local conditions.
Eg some days it's warmer than others, so you need to adjust your fermentation times. Or some parts of the world have harder water than others. Or your available veggies might have different amounts of moisture etc.
If you have a recipe that uses 150g flour in step 1, then later uses 350g flour in step 4, then you actually have two separate ingredients:
1. 150g plain flour
2. 350g plain flour
It may useful to present an ingredient summary for the purposes of shopping which collects that to 500g flour, but from when trying to represent the recipe, it's actually two different ingredients, and it'd be a false re-use to try to re-use the node or try to treat those ingredients as a single ingredient of greater quantity.
Just because two things appear otherwise identical, doesn't mean they are.
I sometimes see a similar issue in software development and re-use of classes or functions. Two different cases happen to need identical handling, so get put through the same code paths. Then later it turns out one case needs to be treated slightly differently, so that path ends up with special casing, and you get a mess of special handling with case statements or "bool treatDifferently" parameters.
If things are conceptually different, then treat them differently, don't assume false commonality.
So what you are saying is that cooking instructions need phi nodes?
I wonder if they got it from Cooking for Engineers
Microdata doesn't need to _fully_ describe something. It's not describing to a machine how to perform the recipe, it's just annotating the text with useful metadata. It's metadata, doesn't need to be full data.
I guess superficially you can join them together with a final node that is like "serve all the dishes".
And for more complex meals, time planning becomes more important so that everything is ready to serve together.
E.g. taking the pan juices and turning that into a sauce. It's a separate process/dish, yet wholly dependant on the other process completing a critical step.
Practically I just have it listed twice if it's important like butter.
https://cookbook.cstebbins.com/recipe/the-best-swedish-meatb...
otherwise if it's a staple like salt I just say something like "stir in and season with additional salt and pepper to taste"
like in https://cookbook.cstebbins.com/recipe/sloppy-sophisto-joes
some recipes can produce multiple related dishes, and some ingredients can have multi-step substitutions. So Graph would be a better representation.
you could join multiple dishes into final 'abstract' dish to force it into tree-esque shape with some shuffling hopefully, but i think that's unnecessary limitation - especially if you consider that some recipes give you some compound ingredients(stocks for example) as side-output that you might want to use in future!
This is a great case for using that information for planning future dishes you could cook for free.
under the hood I have it more like a graph with levels. The traversal is from all of the "leaves" to a single node rather than from the head node towards the leaves as in a traditional tree. The upside-down tree is more for a visual for the reader.
At the moment I don't have a recipe that outputs 2 end states but entirely possible since it's more of a graph under the hood.
We noticed one of our partner websites had an unusual number of unique ingredients. It turned out every ingredient was a link to another recipe to make that ingredient, along the lines of your idea.
However for some reason (presumably SEO) they took this to the extreme and everything was a recipe. Including apples.
The recipe for “apple” is
1. Take 1 Apple
2. Eat and enjoy
But since Apple is a prerequisite for this recipe, infinite looping is a risk in the kitchen now
You can have the best of both world, though, if the branches in your tree had some kind of timing associated.
Like when you make lasagnas, the bolognese takes 1 hour to cook, while the bechamel takes less than 10 minutes. You need to have a way to say: "while the bolognese is reducing, make the bechamel"
Unfortunately they all seem to assume that chopping, cleaning and moving stuff around is all done in 0 time. I wish the recipes would take this into account more.
Because of this I actually would prefer the plain tree organisation more.
In fact, going through a project management basics training at work recently reminded me that cooking recipes are isomorphic to project plans. Which makes DAGs an obvious natural representation for a recipe, and incidentally, makes the Gantt chart one of the best ways of looking at it.
A recent example: I really like the Hainanese chicken recipe at https://www.google.com/amp/s/amp.theguardian.com/food/articl... ... But I find it very hard to follow in this format.
Using o1-preview to restructure it, I get something that I find much easier to follow during my cooking workflow: https://chatgpt.com/share/6733e594-df28-8009-ac80-d5dabd1ae0...
But getting from a well-written recipe to structured data is now pretty straightforward... if/when you need structure data.
Have been doing something exactly like yourself to split it into functionally two parts, there is the shopping list and for me the optimal steps of prep/cooking which includes the quantity for each item.
Column 1 is the quantity. This doesn't really belong in the first column but it matches traditional ways of writing things and doesn't cause any actual trouble to do it that way, so whatever, we can do it that way. Column 2 is the ingredient. And column 3 is the cooking instructions. The rows are then grouped (shaded) by which ingredients go into which cooking instructions.
You can scan down columns 1 and 2 to get a prep / mise en place list, or just column 2 to get a shopping list (possibly involving deduplication if an ingredient is called for more than once), then execution is just running down column 3. The only real problem with execution is when it gets nonlinear (you want to overlap steps 3 and 4 in that recipe, for example) but that's a problem with any format I know of.
It's not perfect, but it works really, really well, and better than any other format I've ever seen.
...also now I want chili since it's cold and wet here in Seattle. And I should probably revise that recipe to reflect what I really do, but it's just chili, it's pretty tolerant of whatever you have lying around....
I found good success using this model for recipes, specially complex baking recipes like breads with multiple repeat ingredients.
For an example, here's a gantt chart for Beef Bourguignon:
Note that when I print it on a (physical) recipe card, I have the 'prose' instructions underneath.
I still think this is a pretty good idea, and I still use the cards for this recipe, and Beef Wellington.
I use a vertical grid format, top to bottom, with rows bucketed into 10 minute increments. Columns are different cooking implements, so I can ensure I am not over allocating space in the oven/microwave/whatever nor my ability to manipulate the next dish.
Makes it trivial to assess where I am in preparing everything on game day. Also, it gives me a historical artifact for the meal. Which is unexpectedly neat to reference.
Here's an example. You'll need to scroll down to see the actual recipe format. https://www.cookingforengineers.com/recipe/194/Cream-of-Mush...
It has some really nice properties, but trades off a key feature of the gantt format: your hands can only be doing one thing at a time. With the gantt format it’s very clear what you are supposed to be doing at any time and it preserves the order of operations. It doesn’t express how things are combined, however, which the tree format accomplishes.
My motivation for the gantt format was to prevent getting “meanwhiled” by a recipe. You are chugging along, and think you are in good shape, and come across that dastardly word in a recipe: Meanwhile. Turns out you should have beaten the eggs to a stiff whip 15 minutes ago.
The format is pretty well demonstrated at https://git.sr.ht/~martijnbraam/fathub-data/tree/master/item... which renders to https://fathub.org/en/recipe/indonesian/main/mie-goreng.html
Some notable features is a mini DSL to refer to ingredients in the instruction text and also have parse-able times and temperatures so on the frontend it's easy to switch units with javascript. This is combined with a simple database of ingredient IDs which contains (translated) names and for some of them the density so you can swap the recipe between volume and weight measurements.
I don't see very many people here who seem to really have done a lot of cooking, consider it a serious hobby or profession, etc.
None of these proposals pass the smell test as being able to capture anything beyond the most basic of recipes.
Though I'm a software engineer, my main user is my mother-in-law who was a nurse all her life and now likes to bake. Check out for example, this multi-component recipe for Brazilian empadas: https://letscooktime.com/Recipes/Details?id=bc786a2f-50ec-4f...
If anything, these formats capture way too much information. For example, you can't really measure cooking times reliably unless you do sous-vide, if you want to be precise, measure temperature.
My critique should be amended to emphasize that it's about naively constructing a model that picks and chooses elements to include based on availability, convenience, etc rather than one built by studying actual chefs and cooks and learning how they think about recipes.
I can say for myself at least that for many classes of dish I barely pay any attention to the specific details in the recipe. I've made thousands of braises, I just need to know the key elements and the rest just sort of fills in (perhaps there's a comparison to musical proficiency here). I'm less concerned with "brown the meat for X minutes on each side" than "brown to mahogany". I don't find it useful when a recipe says how long to reduce a sauce, but when it says what kind of reduction in volume I should be looking for, that can be helpful. In practice I just have an image of the final product and can taste to tell if I've cooked out the acidity and water sufficiently for how I want the dish to taste.
To put a finer point on it, knowing which elements of a recipe are standard procedure and which are distinct and important to the character of the dish is an acquired skill and not something any system that describes recipes as strict assembly instructions can quantify or even qualify.
to your point, add structure/features/"coding standards" as you need for automatic processing, but otherwise you have a perfectly written recipe to whatever standards you hold.
rather than unix, what I see up and down this page is Dave Cutler slicing and dicing of data to the point of incomprehensibility. You know how you guys all loved markdown so much that you've embraced it and are now adding so many features that make it as unreadable as html? don't do that again and again, learn not to do it.
(btw I have cooked extensively and at somewhat high levels of precision (tricky sauces, souffles etc)
In particular, the cooking time is completely useless without the heat power and the kind of pan, and conversions between pans
Think search engines for example. This "cooking time" is often displayed as metadata when you search for recipes. You're just annotating a field for the search engine to display in the results.
Schema.org exists for that. Indexing larger granules of metadata. It is built on RDF so if you need something more specialized, you can use the standards to extend it.
This is actually a fun ontology to think about. You'll need to model pans, ovens and all sorts of cooking hardware. I don't see that knowledge often displayed in recipe websites, so microdata probably isn't the best for a specialized system like that. It would probably use the extended schema/ontology just internally, then publish simplified cooking times for indexing.
For example, think of all the decisions required to specify a curry dish:
How do you cut/mash your garlic and ginger and onions? (If you even add all of those ingredients)
Do you use whole or ground spices? What about for each spice? Cardamom pods or ground cardamom?
Do you toast each spice?
How long do you cook your onions?
And so on. Eventually you get to an absolutely gigantic amount of options that all generate a somewhat similar dish, but with key sensory differences. They may all be ‘chicken tikka masala’ but I’d argue you’d have a very different eating experience across that decision spectrum.
I think this may also play (specifically for Indians) into the idea that moms is best. It’s probably because mom’s is universally unique and you crave that nostalgia.
Do any of the recipes you've seen online or elsewhere every bother to talk about what sort of kitchen is needed? Granted, 99% of the time it's just the standard western kitchen (stove/oven/fridge/mixer), but some recipes require less common appliances. A brick pizza oven, or maybe a sous vide machine.
The data might benefit from being in a different format than the file format itself... even that might need to be different than the presentation software. Do I want to be chained to the software, or does this need to be some open format like epub? How would I search through 500 recipes, or 500,000? Do I want to search through that many, do I want to keep that many or purge the not-so-great ones? Earlier in the thread, someone was complaining that they don't want the ingredient list and numbered list instructions at the top... so is this something like html plus optional stylesheets? God help me, xml and xslt?
Why are they giving me fixed ingredient quantities, rather than ratios and quantity-to-serving numbers?
Do recipes need to link up? If I'm making thousand island dressing or tartar sauce, should I be able to tap a hyperlink to a sweet pickle recipe? How would that even work if I had multiple sweet pickle recipes?
Much more important to me: is the listed cooking time of onions accurate.
But I find cooking to be resistant to this sort of thing, at least if you have a family. Meal planning is more of a negotiation than a tallying of numbers. You tend to cluster around a few, well-honed recipes that are repeated often. And when you're cooking, having a piece of paper or an index card attached to the vent hood or whatever with a magnet is far more user friendly than having to wake up a tablet or a phone.
(Not to mention passing recipes down through the generations. It's not the same to bequeath the recipes to your grandchildren by saying "give me a ssh key and I'll rsync these MySQL tables to your VPS".)
It is not clear why that would be better than an xml-type arrangement like
<step>cut your <ing>apple</ing> into slices<step>
Or even just plain text.
The simple use case for XML is always easy, but then it always ends up looking like this:
<step>prepare fruit
<step>prepare <ing variety"bartlet anjou comice">pear slices</ing> from a <ing state="unprepped">pear</ing>
<step>wash</step>
<step>trim
<step>remove stem</step>
<step>peel</step>
</step>
<step>
<step thickness=".25mm">slice</step>
</step>
</step>
<step>...
Plain text is great and all as a display format but it sucks even more than XML to parse as a data format.You can make JSON that's just as stupid as XML but especially if you have people hand-writing XML, it invites a lot of complexity for a little more expressiveness. If you need to, you can always have flatter XML markup in JSON fields to avoid the large scale recursive structural insanity when parsing.
In contrast, imagine relaxing the everything-in-notepad requirement, imagine a renderer that can easily display cross-referenced materials in a readable way. Or a step beyond that, an editor which also gives you "jump to definition" etc.
That change permits a much more internally-consistent XML file, such as one where "materials" and "steps" are separate sections, and any step can references a material that is being used as input or output, with something like <mat_ref id="sliced_uncooked_apples"/> .
- Shopping
- Scaling up/Scaling down
- Finding ratios of key ingredients when you're looking at multiple recipes to figure out a dish or what's wrong with the last recipe you tried
- Mise en place, which is conventionally omitted except in very detailed recipes
- Planning cooktimes
- The actual cooking process
And as a home cook, I'm not personally experienced with commercial use cases, but there's even more there: costing servings, menu planning, mise across several dishes with common ingredients, etc. Having seen some commercial recipes, pros will frequently use very simple lists of ingredients and just a few notes on technique. Bakers will use baker's percentages.
The weird "cooking for people who insist on modeling the world in complicated categories" format doesn't support these very well, but it sure helps with "is grinding the whole spices a substep of combining the spice mixture?".
Simple formats and clear written language go a long way for human use cases.
For now I've ended up on ingredients being more or less recipes themselves, and recipes being recursive (as in, recipes use other recipes to create new recipes). Some recipes you can either buy & make yourself. For example, sweet soy sauce: easy enough to make but you could also just buy it in the store. The resulting structure is basically:
Recipe:
directions: rich text
storageInstructions: rich text
prepTime: minutes
cookTime: minutes
priceEstimateperServing: money
ingredients: RecipeIngredient[]
// other fields (e.g. tags, id, name, slug, purchaseableAt, nutrients, etc)
RecipeIngredient:
recipeId: reference to recipe
ingredientId: reference to recipe as well
// Allows grouping ingredients (e.g. "sauce", although the sauce could be a recipe of its own instead)
group: string | null
There's some challenges with this though:- If you have a shopping list, how do you determine in a complex recipe which "recipes" you'll purchase and which you'll make from scratch (UX issue)
- Some recipes may have alternatives instead (for example: if allergic to X, substitute with Y)
- It puts a lot of burden on the recipe writer.
- Some recipes don't scale linearly with just the ingredients, but perhaps also the cookware (baking a cake for example). Cooklang docs talk about this as well.
Scaling of recipes could be done with a measurement-aware type. Something similar to frinklang[0] for example.
I like the of a list of ingredients with the quantity in the top and then repeated in the steps (if no quantity is mentioned in the steps its implied the whole ingredient is used). This makes sense in that you may need to have on hand 3 tbs of butter but 2 get melted and mixed in step 3, and 1 is used to grease the pan in step 5.
The next dimension would be a language/glossary of preparation terms (slice apple - how? radially or into x thickness sheets?) This would be helpful for those without any clue on common actions and maybe later for automation. Though cooking is way more an art than just a set of steps and standard unit quantities.
With a glossary you could search for recipes that use grated apples or recipes that use a food processor, or don't use an oven, etc.
Good "food for thought" :-D
I've had multiple recipes on common recipe sites in which, mid-cooking I've realized were missing steps, didn't mention reserving a portion for later, or some elements were not impacted by the serving size multiplier. A diagram of some sort could help me reduce my error rate.
http://torfinseth.wpengine.com/wp-content/uploads/2016/07/Bu...
- Ingredients are listed in one column on the left in order of use.
- Duplicate ingredients are separate.
- Each step has one or more input products and one or more output products, indicated by arrows, and braces to group multiple.
- Handwritten because it's much easier. Computers are just too much trouble.
Check it out, I've open sourced as well a syntax highlight for vscode, a cli for the terminal, a tutorial and a playground, and the wasm modules.
I use the language for more than food recipes, see: https://www.reciperium.com/woile/garlic-tea-for-plants
I felt that for someone who is not familiar with these things, it can be confusing. In recipe-lang the explanation is IMO simpler: wrap the ingredient with `{}`, there are no ambiguities. {salt} or {ingredient with space}, it's quite clear where the ingredient starts and end.
Once they learn that, everything else is a prefix of the curly braces, timer? t{}, link to another recipe? @{}, material? &{}. I'm considering for images something like i{} but I haven't had time to experiment with it.
I would probably prefer a more generic syntax if I were doing it from scratch, but then I'd just wind up with HTML and it wouldn't be as good for recipes.
I could see a more structured approach being useful if you were following one step at a time on a tablet, so maybe that scales better to more complicated recipes?
Most of the stuff I cook is simple enough it all fits on one screenful anyway, on the rare occasion I even use a recipe at all, so I'm not quite sure what the best approach is to cover very complex recipes.
Then I can search by "love" field <= 0 and get the best recipes. Because let's face it-- everything with the highest love field is really being documented for the documenter. But if it's zero (or even better, negative), that's likely to be a good recipe.
Imagine: "I hated that guy sooo much, but damned if he didn't make the best potatoes au gratin." That's a recipe I want to try.
Allows for videos too. Sauces and Main Dishes in the same recipe. It’s comprehensive.
https://developers.google.com/search/docs/appearance/structu...
So if we had a checklist format, we could easily derive a recipe format from that.
Though, tables in markdown are not so easy to read unless you put effort into formatting the data.
You might also want to consider why you want your recipes to be machine readable. I loved the idea in theory but unless you’ve integrated this with your smart larder/fridge or something it might not be useful.
Had no idea about some of these other formats!
I now jot down rough notes in Obsidian when I make a meal I like, and let AI re-format it if I want to share the full recipe with somebody. This also lets me control the output: if I’m sending the recipe to somebody who is new to cooking, I might ask for a more detailed output than if they were only interested in my flavour combinations or specific techniques.
Assuming the LLM doesn't unpredictably add something poisonous. :p
Cooking is more like life than mixing things. There is a hidden magic to it. It's the closest thing to magic next to programming.
Exactly like programming. It can get to you and will swallow you whole if you let it.
Go eat now. Eat well. Sleep well. Love well. That is the essence of a good life.