cooking/.claude/rules/recipe-format.md
Olomana (multica agent) b7c526a784 PWS-13: Make recipe markdown fully control the tabs
Every top-level :::name block is now a tab, shown in file order, so
authors can add custom tabs and reorder them in the markdown. Titles
come from the name or a :::name[Title] label.

The recipe card is an ordinary :::card tab. Its body lists what it
prints (::ingredients, or a block written just for the card), replacing
::card, the fallback to full sections, and its fixed tab position.

All recipes are migrated, with pages and card images unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-11-07 00:34:10 -08:00

112 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Recipe Markdown Format
Recipes are plain `.md` files (not MDX) at `recipes/[category]/[slug]/[slug].md`, parsed with remark + remark-gfm + remark-directive in `lib/recipe-content.ts`.
## Frontmatter Fields
```yaml
---
title: "Recipe Title"
slug: "recipe-slug"
date: "YYYY-MM-DD"
lastUpdated: "YYYY-MM-DD"
category: "mains" # free-form string (e.g. "mains", "soups", "desserts")
tags: ["tag1", "tag2"] # free-form strings (e.g. ["italian", "chicken"])
cookTime: 45 # minutes
prepTime: 20 # minutes
servings: 4
author: "PWS" # ID from public/authors.json
description: "Short description for SEO and previews"
featured: false
display: true # set to false to hide without deleting
displayPhoto: "./assets/hero.jpg"
---
```
## Content Structure
The markdown controls the page: every tab is written in the file, in the order it appears, and the renderer adds, removes and reorders nothing.
The body uses [generic markdown directives](https://talk.commonmark.org/t/generic-directives-plugins-syntax/444). Each top-level container `:::name` … `:::` is a tab:
- Any name works, so custom tabs need no code: `:::equipment`
- The title comes from the name (`:::wine-pairing` → "Wine Pairing"); a label overrides it: `:::notes[Chef Tips]`
- The body is ordinary markdown. An image's title becomes its caption: `![Alt text](./assets/hero.jpg "Caption")`
Standard tabs are `:::photos`, `:::ingredients`, `:::instructions`, `:::notes`, `:::references`, and `:::card`. Only `card` has reserved behaviour.
Markdown before the first tab renders as intro prose above the tabs; markdown after the last tab renders as outro prose below. Prose between tabs is an error.
### Recipe card
`:::card[Recipe Card]` is a tab showing a printable 5×7 in PNG. Its body lists the one or two sections to print, left to right. `::name` reuses another tab, from anywhere in the file:
```md
:::card[Recipe Card]
::ingredients
::instructions
:::
```
A `:::name` block inside it is written just for the card, and can be mixed with references. The outer fence then needs **four** colons:
```md
::::card[Recipe Card]
::ingredients
:::instructions
1. Condensed step one.
2. Condensed step two.
:::
::::
```
Only what's listed is printed; images, tables and code are left out. The card uses one side when the text fits at 8pt or larger; otherwise it splits into a front (first section) and back (second section). The build fails if even front/back doesn't fit — write shorter content inside `:::card`.
### Validation
Duplicate tab names, a top-level leaf directive (`::notes`), an invalid card body, and a card listing a missing tab or nothing printable fail the build with the file. Since any name is a valid tab, a typo like `:::ingrediants` shows up as a misspelled tab rather than an error, and a card listing `::ingredients` then fails the build. `:word` inside prose (e.g. "Tip:Use") is left as literal text.
### Example
```md
---
title: "Lentils"
description: "A neutral lentil dish."
...
---
This recipe uses brown lentils (whole Masoor Dal)...
:::photos
![Lentils](./assets/hero.jpg "Finished lentils")
:::
:::ingredients
- 1 cup brown lentils
:::
:::instructions
1. Rinse lentils...
:::
:::notes
### Tips
- Try with different lentils!
:::
:::card[Recipe Card]
::ingredients
::instructions
:::
:::references
- Reference Recipe **[HERE](https://example.com)**
:::
```
## Image Paths
Images use relative paths: `./assets/image.jpg`
These are rewritten at render time to `/recipes/[category]/[slug]/assets/image.jpg` (from frontmatter category and slug, not the folder name).