Recipe format
Recipes are plain text in a Markdown variant the app parses into title, ingredients, steps, and notes. Write by hand, paste from another source, or use the recipe editor — the file on disk is the same shape either way.
A complete example
# Pancakes
Fluffy weekend pancakes.
Category: Breakfast
Tags: quick, weekend
Makes: 12 pancakes
Serves: 4
Time: 25 min
Active: 15 min
## Mix the batter.
- Flour (all-purpose), 190 g
- Milk, 240 g
- Eggs, 2
- Butter, 2 tbsp: Melted.
Whisk dry ingredients. Add wet ingredients and stir until just combined.
## Cook the pancakes.
- Butter
Pour about 60 g of batter per pancake onto a hot buttered pan.
Cook until bubbles form and edges look set. Flip and cook 1 minute more.
---
Try adding blueberries or chocolate chips to the batter.
Title
The first non-blank line, marked with #. Required.
# Pancakes
Description
Optional text that appears as a subtitle on the recipe page. Place it between the title and the first step. Description and front matter can appear in any order — a Serves: line can sit above the description, below it, or between its paragraphs. (In recipes without ## headers, prose before the first ingredient line counts as the description; prose after it becomes the step instructions.)
# Pancakes
Fluffy weekend pancakes.
Front matter
Optional lines before the first step. Each line is one key, a colon, at least one space, and a value — no leading whitespace.
| Line | Example | Notes |
|---|---|---|
Category: |
Category: Breakfast |
One per recipe. Overrides the category chosen when creating |
Tags: |
Tags: quick, weekend |
Comma-separated. Each tag is lowercased; runs of whitespace become hyphens (slow cooker → slow-cooker) |
Makes: |
Makes: 12 pancakes |
What the recipe produces. Requires a unit noun; Makes: 12 alone is rejected |
Serves: |
Serves: 4 |
Number of servings. Used for per-serving nutrition |
Time: |
Time: 2 weeks |
Total time from start to plated. Accepts minutes, hours, days, and weeks — alone or combined, as in 30 min, 1h, 2 hours 30 min, 2 days 4 hours, or 2 weeks for a long ferment. A bare number is read as minutes, so Time: 20 means 20 min |
Active: |
Active: 30 min |
Hands-on portion of Time:. Requires Time: to be set; can’t exceed it. Takes the same units as Time:. A bare number is read as minutes, so Active: 15 means 15 min |
Source: |
Source: [NYT Cooking](https://cooking.nytimes.com/…) |
Where the recipe came from. A Markdown link, a plain web address, or just a name. Only http:// and https:// links are accepted. Up to 500 characters |
Makes: and Serves: can appear together — Makes: 1 loaf paired with Serves: 12 is valid.
A duration displays back in the largest tidy unit. An exact whole number of weeks shows as weeks (14 days reads as 2 weeks); anything else shows in days, hours, and minutes (15 days stays 15 days). Weeks are the longest unit — months and years aren’t accepted, since their length varies.
Source
Source: takes exactly one of three shapes:
Source: [NYT Cooking](https://cooking.nytimes.com/…) ← a name and an address
Source: https://cooking.nytimes.com/… ← an address alone
Source: Grandma's index card ← a name alone
It renders at the bottom of the recipe page, above the footer text, as Source: followed by the name — a link that opens in a new tab when you gave an address, plain text when you didn’t. An address written without a name shows as the link itself. A link address must start with http:// or https://; any other scheme is rejected.
Anything between the three shapes is rejected rather than filed away as a name — an address buried in a name (Source: NYT — https://cooking.nytimes.com/…) or a Markdown link broken by a typo. Write one of the three shapes and the error goes away. Import a recipe from a link and Mirepoix fills the line in for you, using the site’s address as the link and its host as the name.
Steps
Each step starts with a ## heading. The heading text is a short label that appears as a section header on the recipe page. Periods at the end (## Mix the batter.) are convention in the sample recipes, not a parser requirement.
## Mix the batter.
- Flour, 190 g
- Milk, 240 g
Whisk until smooth.
A recipe with ingredients but no ## headings is still valid — the parser treats the whole body as a single implicit step.
Ingredients
Ingredient lines start with - . The shape is:
- Name, quantity: prep note
- Name — matched against the ingredient catalog for grocery tracking
- Quantity — optional. Numbers, units (any capitalization), ranges, fractions, or unicode glyphs
- Prep note — optional. Renders in smaller text below the line
Examples:
- Butter ← name only
- Flour (all-purpose), 190 g ← name and quantity
- Eggs, 2 ← name and count
- Eggs, 6 large ← count with a size word
- Eggs, 1-2 ← name and range
- Milk, ½ cup ← unicode fraction
- Chickpeas, 1 can (15 oz) ← alternate measure in parentheses
- Butter, 2 tbsp: Melted. ← name, quantity, and prep note
Supported unicode fraction glyphs: ½ ⅓ ⅔ ¼ ¾ ⅛ ⅜ ⅝ ⅞. Mixed forms like 1½ or 1 1/2 work too. Ranges accept -, –, —, or − between numbers, and must read low to high. A backwards range like 3-2 is rejected with a hint to swap it. When you scale the recipe, both ends of a range scale — 1-2 at 2× becomes 2-4.
Units are flexible about how you write them. Capitalization doesn’t matter — 45 mL, 15 OZ, and 5 Tbsp all work. Common shorthand is understood: T for tablespoon and t for teaspoon (case tells them apart), c for cup, and # for pound. An abbreviation may carry a trailing period (15 oz., 2 tsp., fl. oz.), and British spellings work — litre, millilitre, gramme, kilogramme, and their families. Even gō, the Japanese rice measure, is recognized. A few near-misses aren’t accepted: tbs, tbl, and floz.
You can add an alternate measure in parentheses at the end of the quantity — 1 can (15 oz), 2 cups (250 g). Inside goes a plain number and a unit, with a space between them; the unit follows the same flexible spelling rules, so 1 can (360 mL) works. It shows alongside the main quantity and scales with it — 2 cups (250 g) at 2× becomes 4 cups (500 g), and 1 can (360 mL) at 2× becomes 2 cans (720 ml) (scaled text renders the standard lowercase abbreviation; your exact spelling shows at 1×). The shape is strict — a bare number and unit only. Anything else, like (about 15 oz) or (8 oz each), stays in the quantity as plain text.
Automatic metric weight
When an amount is in a US measure — cups, tablespoons, teaspoons, fluid ounces, pints, quarts, gallons, ounces, or pounds — the app shows a metric weight in grams or kilograms after it, so Flour (all-purpose), 2 cups reads as 2 cups (~250 g). The weight is computed from the ingredient catalog, by density for volumes and directly for ounces and pounds, and it scales with the recipe.
The same weight appears after a portion the catalog knows by name — a stick of butter, a slice of cheese, a can of beans:
- Butter, 1⅔ sticks → 1⅔ sticks (~190 g)
- American cheese, 2 slices → 2 slices (~55 g)
- Beans (any canned), 1 can → 1 can (~440 g)
And it appears after a bare count of an ingredient the catalog can weigh — produce you buy by the piece, eggs:
- Onion, 1 → 1 (~150 g)
- Eggs, 2 → 2 (~100 g)
A size word — small, medium, large, or extra large — can sit in the quantity next to the count, and the weight follows the size:
- Onion, 1 large → 1 large (~150 g)
- Eggs, 6 large → 6 large (~300 g)
The app uses that size’s weight when the catalog lists one, and otherwise falls back to the ingredient’s per-item weight if it has one.
Like the US-measure case, these scale with the recipe — two sticks of butter weigh twice as much as one.
The leading ~ marks it as an estimate the app worked out. That’s the difference from the alternate measure above: when you write your own measure in parentheses, like 2 cups (250 g), it shows with no ~ — it’s your figure, not an estimate the app computed. So you can always bake in your own conversion.
The weight appears only when it’s useful. It’s left off an amount already in metric (like g, kg, or ml), an ingredient that isn’t in the catalog, a portion or count the catalog can’t weigh, and any amount under about 10 grams — a teaspoon of vanilla or a single leaf of arugula isn’t worth weighing. And if you’ve written your own measure in parentheses, that wins and no estimate is added.
The colon and comma are reserved delimiters. The first colon starts the prep note; everything before it is the name and quantity, split at the first comma. (A comma after the colon stays in the prep note.) A comma inside parentheses doesn’t count, so Sugar (brown, packed), 150 g keeps its full name. To add a prep note without a quantity, use a colon — a comma puts the word in the quantity slot instead:
- Onion: diced ← prep note
- Onion, diced ← "diced" becomes the quantity
When two recipes share an ingredient, the grocery list combines the quantities. Two recipes calling for Flour, 190 g add up to 380 g on one line.
Quantity-first lines
You don’t have to lead with the name and a comma. A line that leads with the quantity instead — - 1 cup sugar, - 1 cup parsley, chopped — is read the same way: Mirepoix pulls out the quantity and files the ingredient normally. The next time you open the recipe to edit it, the line has been rewritten into the standard Name, quantity form.
While you’re editing, a line written this way gets a dotted underline — a sign that Mirepoix will interpret it when you save, rather than storing it exactly as typed.
A ✨ Tidy N lines button appears above the text box whenever one or more lines carry that underline (it reads ✨ Tidy 1 line for exactly one, and updates as you type). Click it and Mirepoix rewrites the lines it can read with confidence into the standard form right in the editor, so you can watch the change happen — press Cmd+Z (or Ctrl+Z) right after to undo it if you don’t like the result. A line it can’t read with that same confidence keeps its underline and stays in the count — what happens to that line at save time is covered next. You don’t have to click the button at all — an untidied line still reads the same way when you save, so no data is lost either way; tidying just lets you see the standard form before you commit to it.
If Mirepoix can’t tell the quantity apart from the name with confidence, the line falls back to the ordinary rules above: a comma-less line like 1 cup sugar is kept whole, exactly as written, while a line with a comma splits there as usual, the words after the comma landing in the quantity slot. Either way it shows up in Review ingredients (Nutrition) flagged “Couldn’t read this line — edit the recipe text to fix it.” Opening that dialog automatically tries reading the line again — if it now reads cleanly it’s rewritten into the standard form for you, no tapping required; if it still can’t be read, edit the line into the standard form yourself.
The standard Name, quantity: prep note form is unaffected by any of this — it’s already unambiguous, so Mirepoix uses it as written and never runs it through this extra reading step.
Cross-references
A step can pull in another recipe’s steps. Embedded form goes inside a step on its own line:
## Make the sauce.
> @[Simple Tomato Sauce]
A bare @[Recipe Title] in prose — step text or footer — renders as a clickable link without embedding. Full syntax, including multipliers and prep notes, is on Cross-references.
Links
Prose takes ordinary Markdown links — step instructions, ingredient and cross-reference prep notes, and the footer.
Adapted from [Bake with Jack](https://bakewithjack.co.uk).
A link address must be a web address (http:// or https://), a mailto: address, or an ftp:// address; any other scheme is rejected. A rejected link renders as the plain text you typed, brackets and all — the words stay, so fix the address and the link comes back. That covers a hand-typed path to another recipe, too: use @[Recipe Title], which links a recipe by title and isn’t affected.
Scalable numbers
Append * to a number in step instructions, ingredient prep notes, cross-reference prep notes, or the footer to mark it as scalable. When a reader changes the serving count, marked numbers update.
Divide the dough into 8* equal pieces.
- Eggs, 2: Beat with a fork until uniform, about 30* seconds.
> @[Pizza Dough], 2: Make a double batch — about 90* minutes total.
---
Yields about 12* cookies.
Numerals, fractions, and English number words from zero* through twelve* are all scalable. See Scaling for what scales automatically without *.
Footer
The first --- on its own line ends the recipe body and starts the footer. Everything after it is rendered as Markdown — good for notes, tips, and variations. Any link in it follows the rules under Links. Where the recipe came from has its own Source: line in the front matter, which renders just above the footer text. Because that first --- is reserved as the footer separator, you can’t use one as a thematic break between steps.
---
A good basic pancake. Pairs well with @[Maple Syrup].
Things to know
- Front-matter keys (
Category:,Tags:,Makes:,Serves:,Time:,Active:,Source:) parse only at the top, right after the description (or after the title if there’s none). Further down the recipe, a line that looks like front matter passes through as prose — soActive: keep whiskingin a step won’t trip the parser. Inside the block, malformed or invalid shapes (serves: 4,Serves:4,Serves: 0,Time: varies) are still rejected, so a typo at the top doesn’t disappear silently - When a recipe uses
##step headers, every ingredient bullet must sit under one. Bullets between the front matter and the first header are rejected; either move them under a header, or drop the headers and let the parser treat the body as one implicit step - A step that contains both a
> @[...]cross-reference and ingredients or instructions is rejected — the cross-reference must stand alone - Only one
> @[...]per step
Last updated July 16, 2026