The Caramel Recipe Document Spec

I’ve been wanting to write this for awhile now, so glad to finally get pen to paper (ha) and breakdown the spec for Caramel’s Recipe format.

I created this format as a way to make recipes as interoperable as possible and to make passing rich information between Caramel users (and other apps that implement this format) incredibly easy. The format is also designed to be able to be picked apart by everyday people so they can pull out their information without any technical knowledge.

You should familiarize yourself with YAML and the Open Recipe Format as these are two structural pieces that define the data in this format. In this example, I’ll break apart the default Grilled Cheese & Tomato Soup recipe (download here) and describe both what is happening, why that choice was made, and if possible any tips about importing it into your local application.

Opening Technicals

The format extension is .recipe (com.contagious.Caramel.recipe) and are packages, so you can open them on macOS by right clicking and selecting “Show Package Contents”. The general structure looks something like this:

  • recipe.yml
  • metadata.yml
  • Items/
    • Basil.item
    • Butter.item
    • Fresh Bread.item
  • Resources/ (optional)
    • recipe.png
    • thumbnail.png

Our recipe is self-contained in recipe.yml:

recipe_uuid: default-NdvISKFRKc
recipe_name: Grilled Cheese & Tomato Soup
yield: 2 Servings
prep_time: 900
bake_time: 900
cookbook: Quick and Easy Lunches For The Heart
ingredients:
- Tomato Soup:
    amounts:
    - amount: 1
- Garlic Salt:
    amounts:
    - amount: 2 Tsp
- Butter:
    notes: Softened to be spreadable
    amounts:
    - amount: 1 Tbsp
- Fresh bread:
    notes: '2 Slices: A day or so old'
    amounts:
    - amount: 6 Slices
- Basil:
    amounts:
    - amount: 1 Tsp
- Pepperjack:
    amounts:
    - amount: 2
steps:
- step: "Preheat oven to 350\xBA"
- step: 'If preferred: remove crusts from older breads. Butter all four pieces.'
- step: Add Garlic Salt to older pieces and set on foiled tray. Place in oven for
    15 minutes.
- step: Empty Tomato Soup into saucepan, add basil, salt & pepper to taste.
- step: Heat skillet and place remaining bread slices together (cheese between) on
    skillet.
- step: Cook until just crisp and flip, repeat until sides are equal and cheese is
    just melted.
- step: Remove sandwiches from skillet, add soup to bowl, and take bread from oven.
- step: Cut up bread from oven and add as croutons to soup and enjoy!
generated_by: Caramel 2.2.2 (59)
format_version: 1.0

This follows the Open Recipe Format, with a few distinctions:

  • prep_time, bake_time are in seconds
  • generated_by and format_version tags are added

The current format is 1.0

Caramel is capable of reading the full ORF set, but may change a few items to match its model. Caramel can also import a recipe using only this file in the Recipe package (without metadata.yml or the Items directory). If your application can import .recipe format files, it should follow a similar methodology.

The ORF is incredibly well documented and has a lot of thought put into it so I highly suggest reading through it before building any sort of Recipe based application.

We chooses YAML over JSON, XML, or plist for the same reason as ORF: it’s easily readable and quick to read and write. To the average viewer, they can distinguish the different hunks of content easily and the actual file format contains a little bit less overhead.

Metadata Information

The metadata.yml contains the in-depth machine information for mapping your Recipe to an existing model. This file exists to prevent clutter to the recipe.yml file, make fetching some information faster, and define the rich context and connections to your Recipes:

recipe_uuid: default-NdvISKFRKc
recipe_name: Grilled Cheese & Tomato Soup
has_photo_representation: true
ingredient_count: 6
cookbook: Quick and Easy Lunches For The Heart
cookbook_uuid: default-VHVeZukEjF
cookbook_group: null
cookbook_order: 0
ingredient_uris:
  Tomato Soup: default-O0P5qhHbzW
  Fresh bread: default-gSdct7DC1G
  Basil: default-r1Vg4lFqBP
  Pepperjack: default-WQe10I2Coq
  Butter: default-HRRZphNKUT
  Garlic Salt: default-nVbvkfMu3j
generated_by: Caramel 2.2.2 (59)
format_version: 1.0

When importing a Recipe, you should attempt to first match the items to existing items to your store by comparing the URI/UUID. If nothing is found, you should then attempt to match by case-insensitive name and if that fails, then you should finally import the Item into the local store (using the .item contained). If it was previously found, you should not update the item’s information as the user may have made edits to distinguish their copy.

Items/*.item

Contained within the Items directory are the various items, which are also in a packaged form. These items can be individually taken from a .recipe directory or exported from Caramel’s Item section directly so your app should be able to import these independently of a Recipe. The structure is incredibly simple:

  • item.yml
  • category.yml (optional)

items.yml:

item_uuid: default-nVbvkfMu3j
item_name: Garlic Salt
category: Spices & Herbs
category_order: 14
adds_to_stock: false
generated_by: Caramel 2.2.2 (59)
format_version: 1.0.0

and category.yml, which may be excluded if the item isn’t in one:

category_uuid: default-dtrepMEl9Q
category_name: Spices & Herbs
icon: 33
color: 11
generated_by: Caramel 2.2.2 (59)
format_version: 1.0.0

 

And there you have it!

Soon I’d like to expand on this format to include more detailed expansion of properties for items and categories, but right now they’re scoped to Caramel’s inner model. Please shoot me a message if you have any questions or suggestions!

I am Dan Griffin and you can find me on Mastodon

The Blog

Base & Elevated System (and Grouped!) Background Colors

In iOS 13, Apple introduced a slew of new colors that are also dynamic – meaning they will adjust between light and dark modes (and other scenarios, such as high contrast). Of the new colors, the various background colors are pretty pecular: iOS defines two sets of background colors—system and grouped—each of which contains primary,…

iOS iOS 13

Always Taking Inquiries

At the moment I am not taking on many new projects, but am still available for inquiry or questions.

Reach Out To Dan