mirror of
https://github.com/runyanjake/cooking.git
synced 2026-09-27 05:38:40 -07:00
103 lines
3.1 KiB
Markdown
103 lines
3.1 KiB
Markdown
# 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: ``
|
||
- `:::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
|
||

|
||
:::
|
||
|
||
:::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).
|