cooking/.claude/rules/recipe-format.md
2026-09-13 14:50:11 -07:00

103 lines
3.1 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 body uses [generic markdown directives](https://talk.commonmark.org/t/generic-directives-plugins-syntax/444):
- **Container** `:::name` … `:::` wraps a section of ordinary markdown
- **Leaf** `::name` on its own line inserts a generated object
### Sections (each becomes a tab, in this order)
- `:::photos` — images; the image title becomes the caption: `![Alt text](./assets/hero.jpg "Caption")`
- `:::ingredients` — bullet lists, optionally grouped with `###` subheadings
- `:::instructions` — numbered steps, optionally grouped with `###` subheadings
- `:::notes` — tips, variations, storage (optional)
- `:::references` — credits and sources (optional)
Markdown before the first section renders as intro prose above the tabs; markdown after the last section renders as outro prose below. Prose between sections is an error.
### Recipe card (opt in)
- `::card` adds a Recipe Card tab with a printable 5×7 in PNG generated from `:::ingredients` and `:::instructions`
- To give the card a shorter version, use the container form. The outer fence needs **four** colons; any section left out falls back to the full one:
```md
::::card
:::instructions
1. Condensed step one.
2. Condensed step two.
:::
::::
```
The card uses one side when the text fits at 8pt or larger; otherwise it splits into a front (ingredients) and back (instructions). The build fails if even front/back doesn't fit — add a `::::card` with shorter content.
### Validation
Unknown directives (e.g. `:::ingrediants`), duplicate sections, and a leaf form of a section (`::notes`) fail the build with the file and line. `: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!
:::
:::references
- Reference Recipe **[HERE](https://example.com)**
:::
::card
```
## 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).