72 lines
3.4 KiB
Markdown
72 lines
3.4 KiB
Markdown
# Recipe Image Ingestion Spec
|
|
|
|
**Goal:** Give every `.cook` recipe file in the repository a high-quality, relevant food image hosted at `https://roux.roo.lol/recipe-images/` and referenced in its YAML frontmatter.
|
|
|
|
## Scope
|
|
|
|
| Category | Count | Action |
|
|
|---|---|---|
|
|
| Has YAML frontmatter + already has `image:` | 19 | Download existing image, re-host, update URL |
|
|
| Has YAML frontmatter + no `image:` | 48 | Find + download image, add `image:` field |
|
|
| No YAML frontmatter | 9 | Add frontmatter with title, find + download image, add `image:` field |
|
|
| **Total** | **76** | |
|
|
|
|
## Image Filename Convention
|
|
|
|
Slugify the `.cook` filename stem:
|
|
|
|
1. Strip `.cook` extension
|
|
2. Lowercase
|
|
3. Replace runs of non-alphanumeric characters (spaces, punctuation, `&`, etc.) with a single hyphen
|
|
4. Strip leading/trailing hyphens
|
|
5. Append `.webp`
|
|
|
|
**Examples:**
|
|
- `Black Bean and Corn Salad.cook` → `black-bean-and-corn-salad.webp`
|
|
- `BUTTERNUT & TURKEY CHILI with sweet peppers, spiced pepitas & queso fresco.cook` → `butternut-turkey-chili-with-sweet-peppers-spiced-pepitas-queso-fresco.webp`
|
|
- `Chickpea_Butter_Curry.cook` → `chickpea-butter-curry.webp`
|
|
|
|
## Image URL Format
|
|
|
|
```
|
|
https://roux.roo.lol/recipe-images/<slug>.webp
|
|
```
|
|
|
|
## Image Sourcing
|
|
|
|
### For recipes that already have an `image:` field
|
|
- Download the image from its current URL (e.g., `https://kitchen.roo.lol/data/images/<uuid>.webp`)
|
|
- Save locally as `<slug>.webp`
|
|
- Update the `image:` field to `https://roux.roo.lol/recipe-images/<slug>.webp`
|
|
|
|
### For recipes without an `image:` field
|
|
- Use the recipe title (from frontmatter or content) to search for a relevant, free-to-use food image online
|
|
- Prefer reputable recipe sites, Unsplash/Pexels, or other permissively-licensed sources
|
|
- Download as `<slug>.webp`
|
|
- Add `image: https://roux.roo.lol/recipe-images/<slug>.webp` to the frontmatter
|
|
|
|
### For recipes without frontmatter
|
|
- Parse the recipe content to determine a title (from context, first line, or filename)
|
|
- Construct minimal YAML frontmatter: `---`, `title: <detected title>`, `---`
|
|
- Find and download image as above
|
|
- Insert frontmatter + image field above the recipe body
|
|
|
|
## Implementation Approach
|
|
|
|
1. **Batch by category** to minimize context switching:
|
|
- Batch 1: 19 existing-image recipes (download + relink)
|
|
- Batch 2: 48 no-image recipes with frontmatter (find + download + add field)
|
|
- Batch 3: 9 no-frontmatter recipes (create frontmatter + find + download + add field)
|
|
|
|
2. **For image discovery**, use a web-search agent to find an appropriate image URL for each recipe, then download via `curl`.
|
|
|
|
3. **Parallelize** image discovery across multiple subagent workers to keep total time reasonable.
|
|
|
|
## Edge Cases
|
|
|
|
- **Duplicate-ish recipes** (e.g., `butternut-turkey-chili.cook`, `Butternut Turkey Chili.cook`, `BUTTERNUT & TURKEY CHILI...`): Each gets its own image slug. They may share similar images, but each file gets its own entry.
|
|
- **Image download failure**: If an image URL is unreachable (for existing images) or no suitable image is found (for new ones), log the recipe slug and skip it.
|
|
- **Special characters in filenames**: Slugify handles `&`, `'`, `(`, `)`, etc. by collapsing them into hyphens.
|
|
- **Existing image URLs that are already in the target format**: Skip re-download (they're already correct).
|
|
- **Non-WebP source images**: Downloaded images should be saved as `.webp`. If the source is not WebP, use `ffmpeg` or `convert` to re-encode.
|