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.
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.
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.
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.
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.
- 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...
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.
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.
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)
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"/> .
Yes, those are all constraints that need to be stored there. Some of them are fixed, others can be computed when optimizing the plan.
It's also information you should have specified on the recipe. Most of it usually isn't, as it's either obvious[0] or the recipe author doesn't even realize it's a parameter.
--
[0] - Some obvious to anyone, some obvious to someone very experienced at cooking. Confusing them makes things really difficult for beginners.
First of all, you can't really model exactly what chefs do algorithmically. Or you can, maybe, but you shouldn't do that in a recipe. Unless you are building an autonomous robot-chef arm. I've seen these in China, they only cook very simple dishes.
What developers tend to forget, the recipe is a tool, and it helps chefs put together a dish. A mere combination of ingredients and maybe cooking techniques is usually sufficient for that. It is NOT an algorithm.
That's why I liked the 3 column layout linked somewhere else in this topic better than the cooking for engineers forget: it has less information which makes the things that matter stand out more.
Using the mushroom soup recipe as an example:
(1) Melt the butter.
(2) Wash and dice the onions, celery, and leeks.
(3) Sweat the melted butter from step (1) and the diced onions, celery, and leeks from step (2) together for 6 minutes.
In the cookingforengineers.com (COE) format, the order is to do each step in the first column and then move right to the next column and do those steps, etc.
Problem is column 1 and 2 wont necesarily have ingredients on the same row...
I probably also have a different perspective on both of these topics than most. I’ve dove a lot of automated document work, and also was a chef so I’ve got a more structured, less prosaic approach to recipes.
To me, it sounds like you want to annotate data that doesn't even exist.
I also haven’t seen a site that actually turns that into a neat visualisation, but as an amateur chef, properly timing steps of a recipe is definitely important.
I’m inclined to agree with GP though that a good model should be able to capture that.
But this is inconvenient during the shopping step of the process. There you want all uses of an ingredient (possibly across multiple recipes) collapsed into 1 node.
Maybe someday I'll add a feature to grab a shopping list. Could organise it into sections of the store and do a quick traveling salesman problem :D
also due to the conciseness of the grid, it's also not great if you're making it for the first time
This is a constant source of stress for me cooking from cookbooks I otherwise like. I prefer to measure on-demand, and wish the steps would just duplicate the quantities of the ingredients "whisk in the olive oil (1/4 cup)" instead of "whisk in the olive oil" so I don't have to scan the list of ingredients and figure it out
That way there are three "segments" of the spreadsheet: shopping; prep; cooking.
You can then _decide_ what to paralellize (maybe you want to take it slow, maybe you have another person to help you, etc).
To me, it sounds way simpler. Specially for those writing or annotating the recipes. You're thinking of the reader, but the writing is important too, it's the hidden cost of making super detailed models.
I was implicitly assuming that your graph models instructions and procedures. You seem to assume that the graph models concrete physical items.
You can execute the same steps twice, but you can't eat the same piece of butter twice.
When you come back to do the "same" operation again, you're fundamentally dealing with different items, even if it doesn't appreciably appear to be the case.
You might have different criteria for evaluation, but something has fundamentally changed.
Let's look at the simplest case you might be tempted to model as a cycle:
> "Salt to taste"
Now, that would traditionally be modelled in a flowchart as a cycle:
1. Add salt
2. Test taste. Too little salt? Go to step 1. Else go to step 3.
3. End.
However, in strict modelling terms, I'd argue there's a hidden parameter, "number of saltings attempted".
You wouldn't repeat that a hundred times and keep adding salt, after a while you'd suspect that your taste-buds had gone or the salt had gone funny.
So rather than a cycle, it's actually a series of steps with a hidden step counter, which eventually has different outcomes.
Have a look at the example of a turnstile state machine on Wikipedia: https://commons.wikimedia.org/wiki/File:Turnstile_state_mach...
The graph of that state machine suggests that you repeat the cycles indefinitely. But I have it on good authority that real world turnstiles only have a finite coin box. [citation needed] So there's some extra hidden state.
Recipes are not a tree.
https://news.ycombinator.com/item?id=41700416
In particular the lemon meringe pie. You separate whites and yolks to prepare the filling and the meringue separately before merging them in the last step.
>it'd be a false re-use
Technically, recipes are monoidal pre-orders and I guess you could find arguments against what you propose in the mathematical foundation, unfortunately I'm not versed enough in category theory to articulate it properly.
For example, if you make the "Lobster, Poached with Shellfish, Pear, and Kale" from the 11-madison park cookbook, you will make a "white balsamic vinaigrette" which is then used directly to make the "Pear Glaze", "Pickled Mustard Seeds", and "Pear marmalade" components. (The pickled mustard seeds also go into the "Pear marmalade" component.)
I think the post you're replying to is saying that you'll make 3 "white balsamic vinaigrettes" instead of reusing the same one 3 times.
Which makes sense since one step of the recipe will be to divide the vinaigrette into 3 amounts to make the other ingredients.
You'd only have one node. Just like you don't put every bite of food into its own node.