Mastodon github.com/rknightuk proven.lol/aaecd5

Thinking About Recipe Formats More Than Anyone Should

posts 2024-11-04

I've had a note in my todo list for quite a while to get my (admittedly small) collection of recipes on my website. The note mentioned to look into Cooklang which is a "recipe markup language" but I also wanted to see if anyone knew of any other standards I should be looking at before I went ahead. I got a few responses:

I should note at this point, I started writing out how my own standard might work because I am an idiot. A real XKCD#927 moment. I stopped, I swear.

Of these I narrowed it down to two that were worth my time: Cooklang and the schema type. Recipe microformat is useful but I was looking for how should I store these and not necessarily how to display them.

Cooklang

A very basic Cooklang recipe looks like this:

>> source: https://en.wikipedia.org/wiki/Apple
>> note: Recommended by doctor exorcists

Cut the @Apple{1} into slices. This takes ~{1%minute}. You need a #knife.

Ingredients are identified with @ and quantity is defined in the brackets {100%g}. Timers are done with ~{10%minutes}. Each paragraph becomes an instruction step. You can also define cookware with #. >> is the metadata. When this is run through a parser the output will be represented like so:

{
"metadata": {
"source": "https://en.wikipedia.org/wiki/Apple",
"note": "Recommended by doctor exorcists"
},
"ingredients": [
{
"type": "ingredient",
"name": "Apple",
"quantity": 1,
"units": ""
}
],
"cookware": [
{
"type": "cookware",
"name": "knife.",
"quantity": ""
}
],
"steps": [
[
{
"type": "text",
"value": "Cut the "
},
{
"type": "ingredient",
"name": "Apple",
"quantity": 1,
"units": ""
},
{
"type": "text",
"value": " into slices. This takes "
},
{
"type": "timer",
"name": "",
"quantity": 1,
"units": "minute"
},
{
"type": "text",
"value": ". You need a "
},
{
"type": "cookware",
"name": "knife.",
"quantity": ""
}
]
]
}

The main limititation I've had when converting my recipes is if you have a recipe that is simply "mix all the ingredients" you can't list them out without them becoming instruction steps.

Mix all the ingredients together.

- @Butter{230%g}
- @Garlic{8-10%cloves}
- @Parsley{25%g}

So you need to write it out like this instead:

Mix @Butter{230%g}, @Garlic{8-10%cloves}, and @Parsley{25%g} together.

Which is fine but in the case of a recipe like this[1] I would prefer to have the ingredients defined separately from the instructions. There's also no option to add multi line notes in the metadata section with >> but that's not a massive problem.

Schema Recipe Type

The example Apple recipe above can be represented with JSON-LD like so:

<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Recipe",
"author": "Robb Knight",
"cookTime": "PT1M",
"datePublished": "2024-11-04",
"description": "Cutting up an apple",
"recipeIngredient": [
"1 Apple"
],
"name": "Sliced Apple",
"recipeInstructions": [
"Cut the apple into slices. This takes 1 minute. You need a knife."
],
}
</script>

There are loads of other attributes available like calorie count and suitability for diet types, among others. This is the format that large recipe sites like allrecipes use, moreso for SEO than anything else, but I suspect the recipe extractor tools that exist are using this where they can. However, there's no world in which I'm going to write my recipes in JSON so this can't be the source format - but it would make sense to also include this on a recipe page.

Output

I wondered what this might look like on a recipe post or page. I think the solution I want is:

  • Have the recipe, rendered from the cooklang file, as the content of the page. cooklang-ts will parse the file and give me back all the info I need.
  • Have the raw cooklang content available so anyone can download it and use it in their own system.
  • Include the JSON-LD schema on the page so recipe extractors can grab it easily.
  • Mark it up with the h-recipe microformat.

That final point is relatively simple to implement:

<article class="h-recipe">  
<ul>
<li class="p-ingredient">Apple (1)</li>
</ul>

<div class="e-instructions">
<p>Cut the apple into slices. This takes 1 minute. You need a knife.</p>
</div>
</article>

There's also p-yield for quantity produced by the recipe and dt-duration for how long it takes.

I think this is what I want to achieve on my site. Recipes are blog posts tagged with #recipes and all the extra info is available if it's needed. I have a working branch of my site that adds support for .cook files as well as parsing the files and I'll put up a post about that when I've got it working exactly how I want.


  1. This is a shortened version of a garlic butter recipe, the real recipe has nine total ingredients so you can see how this would be very annoying.

Popular Posts

Analytics powered by Fathom