merge: feature/recipe-images into main

Add image metadata to all 78 .cook recipe files:
- Download and relink 19 existing images to roux.roo.lol
- Find and download images for 50 recipes with frontmatter
- Add frontmatter and images for 9 recipes without frontmatter
- All images converted to proper WebP format
This commit is contained in:
2026-05-21 15:05:58 -04:00
167 changed files with 1385 additions and 34 deletions
+1
View File
@@ -16,6 +16,7 @@ tags:
- french - french
image: https://roux.roo.lol/recipe-images/alain-ducase-bread.webp
--- ---
+1 -1
View File
@@ -3,7 +3,7 @@ title: Apple Cider Vinegar Dressing
description: This homemade apple cider vinaigrette is SO much better than any store bought dressing! Made with 7 simple ingredients, it's tangy, healthy, and easy to make. description: This homemade apple cider vinaigrette is SO much better than any store bought dressing! Made with 7 simple ingredients, it's tangy, healthy, and easy to make.
servings: 6 servings: 6
source: https://www.loveandlemons.com/apple-cider-vinegar-dressing/ source: https://www.loveandlemons.com/apple-cider-vinegar-dressing/
image: https://kitchen.roo.lol/data/images/14663763-8d52-4e31-a4e8-36a7f3c6c229.webp image: https://roux.roo.lol/recipe-images/apple-cider-vinegar-dressing.webp
thumbnail: https://kitchen.roo.lol/data/images/thumbnails/14663763-8d52-4e31-a4e8-36a7f3c6c229.webp thumbnail: https://kitchen.roo.lol/data/images/thumbnails/14663763-8d52-4e31-a4e8-36a7f3c6c229.webp
date_created: 2024-11-03 date_created: 2024-11-03
date_modified: 2024-11-03 date_modified: 2024-11-03
@@ -20,6 +20,7 @@ tags:
- pesto - pesto
image: https://roux.roo.lol/recipe-images/arugula-pesto-chicken-with-pecans-roasted-butternut.webp
--- ---
+1
View File
@@ -8,6 +8,7 @@ tags:
- arugula - arugula
- pesto - pesto
- wheat berries - wheat berries
image: https://roux.roo.lol/recipe-images/arugula-pesto-wheat-berries-recipe.webp
--- ---
Place the @cooked wheat berries{3%cups} in a large mixing bowl and set them aside so they can come up to room temperature if you've had them in the refrigerator. Place the @cooked wheat berries{3%cups} in a large mixing bowl and set them aside so they can come up to room temperature if you've had them in the refrigerator.
+1
View File
@@ -10,6 +10,7 @@ tags:
- salad - salad
description: A fresh spring asparagus salad with peas, radishes, feta, pine nuts, and herbs, tossed with lemon and olive oil and finished with creamy avocado dressing. description: A fresh spring asparagus salad with peas, radishes, feta, pine nuts, and herbs, tossed with lemon and olive oil and finished with creamy avocado dressing.
source: Love and Lemons source: Love and Lemons
image: https://roux.roo.lol/recipe-images/asparagus-salad.webp
--- ---
Bring a large #pot of well-salted @water{} to a boil and prepare a #bowl of @ice water{}. Bring a large #pot of well-salted @water{} to a boil and prepare a #bowl of @ice water{}.
+1
View File
@@ -8,6 +8,7 @@ tags:
- pasta - pasta
- italian - italian
- quick - quick
image: https://roux.roo.lol/recipe-images/authentic-cacio-e-pepe-recipe.webp
--- ---
In a #pot, bring @water{} to a boil. Lightly salt the water when it comes to a boil. In a #pot, bring @water{} to a boil. Lightly salt the water when it comes to a boil.
@@ -9,6 +9,7 @@ tags:
- butternut squash - butternut squash
- chili - chili
- turkey - turkey
image: https://roux.roo.lol/recipe-images/butternut-turkey-chili-with-sweet-peppers-spiced-pepitas-queso-fresco.webp
--- ---
Heat ~{1%Tbsp} @olive oil{} in a #pot over medium heat. Heat ~{1%Tbsp} @olive oil{} in a #pot over medium heat.
@@ -9,6 +9,7 @@ tags:
- mexican - mexican
- peppers - peppers
- vegetarian - vegetarian
image: https://roux.roo.lol/recipe-images/baked-chile-relleno-with-black-beans.webp
--- ---
Preheat the #oven to high broil with a rack near the broiler. Preheat the #oven to high broil with a rack near the broiler.
+1
View File
@@ -10,6 +10,7 @@ tags:
- rice - rice
- tofu - tofu
- vegetarian - vegetarian
image: https://roux.roo.lol/recipe-images/bang-bang-tofu.webp
--- ---
Drain @tofu{1%lb}, pat dry, and place on a plate lined with several paper towels or a clean dish towel to dry for ~{15%minutes}. Drain @tofu{1%lb}, pat dry, and place on a plate lined with several paper towels or a clean dish towel to dry for ~{15%minutes}.
@@ -9,6 +9,7 @@ tags:
- chicken - chicken
- biscuits - biscuits
- okra - okra
image: https://roux.roo.lol/recipe-images/barbecue-chicken-with-crispy-pan-fried-okra-cheddar-biscuits.webp
--- ---
Preheat the #oven to 400°F and lightly grease a #baking sheet. Preheat the #oven to 400°F and lightly grease a #baking sheet.
+1
View File
@@ -12,6 +12,7 @@ tags:
- avocado - avocado
- summer - summer
- healthy - healthy
image: https://roux.roo.lol/recipe-images/black-bean-and-corn-salad.webp
--- ---
In a large #mixing bowl{}, whisk together the @lime juice{1/4%cup}, @avocado oil{3%tablespoons}, @garlic{1%clove}, grated, @cumin{1/2%teaspoon}, @sea salt{3/4%teaspoon}, and @black pepper{}. In a large #mixing bowl{}, whisk together the @lime juice{1/4%cup}, @avocado oil{3%tablespoons}, @garlic{1%clove}, grated, @cumin{1/2%teaspoon}, @sea salt{3/4%teaspoon}, and @black pepper{}.
+9
View File
@@ -1,3 +1,12 @@
---
title: Black Pepper Tofu (Ottolenghi)
description:
servings: 1
category: uncategorized
source: Unknown
image: https://roux.roo.lol/recipe-images/black-pepper-tofu-ottolenghi.webp
---
>> Servings: 4 >> Servings: 4
Pour enough @vegetable oil{} into a large #frying pan or wok{} to come 1/4 inch and turn on heat. Pour enough @vegetable oil{} into a large #frying pan or wok{} to come 1/4 inch and turn on heat.
+9
View File
@@ -1,3 +1,12 @@
---
title: Black Pepper Tofu with Bok Choy
description:
servings: 1
category: uncategorized
source: Unknown
image: https://roux.roo.lol/recipe-images/black-pepper-tofu-with-bok-choy.webp
---
>> Servings: 2 >> Servings: 2
>> Prep time: 30 minutes >> Prep time: 30 minutes
>> Total time: 30 minutes >> Total time: 30 minutes
+1
View File
@@ -7,6 +7,7 @@ tags: caesar salad,garnish-and-gather,seafood,shrimp and grits,southern
source: Unknown source: Unknown
description: Southern-style shrimp and grits with smoked gouda, served with a charred scallion kale caesar salad description: Southern-style shrimp and grits with smoked gouda, served with a charred scallion kale caesar salad
prep_time: 25 minutes prep_time: 25 minutes
image: https://roux.roo.lol/recipe-images/blackened-shrimp-and-gouda-grits.webp
--- ---
In a #pot{}, bring 3 cups @water{} & @salt{1/2 teaspoon} to a boil. In a #pot{}, bring 3 cups @water{} & @salt{1/2 teaspoon} to a boil.
+1 -1
View File
@@ -4,7 +4,7 @@ servings: 6
category: uncategorized category: uncategorized
source: https://cooking.nytimes.com/recipes/1020094-tofu-makhani-indian-butter-tofu source: https://cooking.nytimes.com/recipes/1020094-tofu-makhani-indian-butter-tofu
description: This recipe is a vegetarian riff on butter chicken, or murgh makhani, a classic Indian dish in which chicken simmers in a rich, dairy-laden tomato sauce that's seasoned with heady spices like turmeric, cumin, garam masala and cardamom. This weeknight-friendly version has a toned-down ingredient list, and the tofu doesn't require hours of marinating, which means you can get everything on the table in under an hour if you start the rice as the tomatoes are cooking down. Heavy cream gives this dish a rich finish, but full-fat coconut milk makes a fine substitute. Whatever you do, don't substitute anything for butter or ghee (sorry, vegans) — it's signature ingredient. description: This recipe is a vegetarian riff on butter chicken, or murgh makhani, a classic Indian dish in which chicken simmers in a rich, dairy-laden tomato sauce that's seasoned with heady spices like turmeric, cumin, garam masala and cardamom. This weeknight-friendly version has a toned-down ingredient list, and the tofu doesn't require hours of marinating, which means you can get everything on the table in under an hour if you start the rice as the tomatoes are cooking down. Heavy cream gives this dish a rich finish, but full-fat coconut milk makes a fine substitute. Whatever you do, don't substitute anything for butter or ghee (sorry, vegans) — it's signature ingredient.
image: https://kitchen.roo.lol/data/images/99596aa7-0678-40ce-8020-f2ae9308be6a.webp image: https://roux.roo.lol/recipe-images/butter-tofu.webp
--- ---
In a large #bowl{}, whisk @fresh lemon juice{2 tablespoons}, @ground cumin{1 tablespoon} and 1 heaping tablespoon @ground turmeric{} with 1 tablespoon @water{} to make a thin paste. Drain and pat @tofu{2 (14-ounce) packages, firm} dry then cut it into 1-inch cubes. Add @tofu{} to the @turmeric{} marinade, gently stirring to coat. Set aside at room temperature while you prepare the remaining ingredients, or cover and refrigerate for up to 1 day. In a large #bowl{}, whisk @fresh lemon juice{2 tablespoons}, @ground cumin{1 tablespoon} and 1 heaping tablespoon @ground turmeric{} with 1 tablespoon @water{} to make a thin paste. Drain and pat @tofu{2 (14-ounce) packages, firm} dry then cut it into 1-inch cubes. Add @tofu{} to the @turmeric{} marinade, gently stirring to coat. Set aside at room temperature while you prepare the remaining ingredients, or cover and refrigerate for up to 1 day.
+1
View File
@@ -9,6 +9,7 @@ tags:
- butternut squash - butternut squash
- chili - chili
- turkey - turkey
image: https://roux.roo.lol/recipe-images/butternut-turkey-chili-2.webp
--- ---
Heat ~{1%Tbsp} @olive oil{} in a #pot over medium heat. Heat ~{1%Tbsp} @olive oil{} in a #pot over medium heat.
+1
View File
@@ -3,6 +3,7 @@ title: Cabbage Salad
servings: 6 servings: 6
category: Salad category: Salad
source: https://www.loveandlemons.com/cabbage-salad/ source: https://www.loveandlemons.com/cabbage-salad/
image: https://roux.roo.lol/recipe-images/cabbage-salad.webp
--- ---
In a large bowl, toss together @green cabbage{4%cup}, @red cabbage{4%cup}, @red bell pepper{1%medium}, @carrots{1%cup}(julienned), @cilantro{1/2%cup}(chopped). In a large bowl, toss together @green cabbage{4%cup}, @red cabbage{4%cup}, @red bell pepper{1%medium}, @carrots{1%cup}(julienned), @cilantro{1/2%cup}(chopped).
@@ -4,7 +4,7 @@ servings: 4
category: uncategorized category: uncategorized
source: https://therecipecritic.com/cajun-shrimp-and-sausage-vegetable-foil-packets/ source: https://therecipecritic.com/cajun-shrimp-and-sausage-vegetable-foil-packets/
description: Cajun Shrimp and Sausage Foil Packets are loaded with shrimp, sausage, summer vegetables and tossed in cajun spices. These are quick and easy and packed with big flavor! description: Cajun Shrimp and Sausage Foil Packets are loaded with shrimp, sausage, summer vegetables and tossed in cajun spices. These are quick and easy and packed with big flavor!
image: https://kitchen.roo.lol/data/images/9f6c7d9f-c6d7-4ea3-bad7-dcffe1187cba.webp image: https://roux.roo.lol/recipe-images/cajun-shrimp-and-sausage-vegetable-foil-packets.webp
--- ---
In a large #bowl{} add @shrimp{1 pound, large, peeled and deveined}, @sausage{14 ounce, pork or chicken, sliced}, @zucchini{2 medium sized, sliced}, @yellow squash{2 medium sized, sliced}, @asparagus{½ bunch, sliced into thirds}, @red bell pepper{2, chopped into chunks} and @salt{} and @pepper{}. Add @olive oil{3 Tablespoons} and @cajun seasoning{3 Tablespoons} and toss until coated. In a large #bowl{} add @shrimp{1 pound, large, peeled and deveined}, @sausage{14 ounce, pork or chicken, sliced}, @zucchini{2 medium sized, sliced}, @yellow squash{2 medium sized, sliced}, @asparagus{½ bunch, sliced into thirds}, @red bell pepper{2, chopped into chunks} and @salt{} and @pepper{}. Add @olive oil{3 Tablespoons} and @cajun seasoning{3 Tablespoons} and toss until coated.
@@ -3,7 +3,7 @@ title: Cajun Spice Mix (for pecans, oysters, etc)
description: A Leonard-family recipe for spice mix for seasoning Cajun Pecans or Oysters description: A Leonard-family recipe for spice mix for seasoning Cajun Pecans or Oysters
servings: 9 servings: 9
source: Mealie source: Mealie
image: https://kitchen.roo.lol/data/images/c0540c17-29a5-4fe3-b038-1b421037c6e8.webp image: https://roux.roo.lol/recipe-images/cajun-spice-mix-for-pecans-oysters-etc.webp
thumbnail: https://kitchen.roo.lol/data/images/thumbnails/c0540c17-29a5-4fe3-b038-1b421037c6e8.webp thumbnail: https://kitchen.roo.lol/data/images/thumbnails/c0540c17-29a5-4fe3-b038-1b421037c6e8.webp
date_created: 2024-11-03 date_created: 2024-11-03
date_modified: 2024-11-03 date_modified: 2024-11-03
+9
View File
@@ -1,3 +1,12 @@
---
title: Caramel Cake
description:
servings: 1
category: uncategorized
source: Unknown
image: https://roux.roo.lol/recipe-images/caramel-cake.webp
---
>> Servings: 10 >> Servings: 10
Combine @sour cream{8 ounces} and @milk{1/4 cup}. Combine @sour cream{8 ounces} and @milk{1/4 cup}.
+9
View File
@@ -1,3 +1,12 @@
---
title: Caramel Icing
description:
servings: 1
category: uncategorized
source: Unknown
image: https://roux.roo.lol/recipe-images/caramel-icing.webp
---
>> Servings: 10 >> Servings: 10
Sprinkle @sugar{1/2 cup} in a shallow heavy #3½-quart Dutch oven{}. Sprinkle @sugar{1/2 cup} in a shallow heavy #3½-quart Dutch oven{}.
+1
View File
@@ -7,6 +7,7 @@ servings: 6
category: side category: side
source: OCR source: OCR
tags: salad, indian, vegan, gluten-free, instant-pot, chickpea tags: salad, indian, vegan, gluten-free, instant-pot, chickpea
image: https://roux.roo.lol/recipe-images/chana-chickpea-salad.webp
--- ---
In the inner cooking pot of the #Instant Pot, combine the @chickpea{1%can}, @bay leaf{2}, and @water{4%cups}. In the inner cooking pot of the #Instant Pot, combine the @chickpea{1%can}, @bay leaf{2}, and @water{4%cups}.
+1 -1
View File
@@ -4,7 +4,7 @@ servings: 6
category: side category: side
source: OCR source: OCR
description: I think my mom lied to me about this chana salaad. She said it was junk food so I would eat it, but now that I'm older I know better. After all, it's chickpeas and vegetables! But I'm glad my mom said whatever it took at time to get me to eat it, because I love this salad. It is perfect for summer and is easy to make. Serve it as a side salad or as a main dish for a vegan meal. Adjust cayenne as desired for your heat preference. SERVES 6 description: I think my mom lied to me about this chana salaad. She said it was junk food so I would eat it, but now that I'm older I know better. After all, it's chickpeas and vegetables! But I'm glad my mom said whatever it took at time to get me to eat it, because I love this salad. It is perfect for summer and is easy to make. Serve it as a side salad or as a main dish for a vegan meal. Adjust cayenne as desired for your heat preference. SERVES 6
image: https://kitchen.roo.lol/data/images/bd956abd-bbc8-4b7c-87e1-8c7ca70f804d.webp image: https://roux.roo.lol/recipe-images/chana-salad.webp
--- ---
In inner cooking pot of #InstantPot, combine @chickpeas{1 can, 15-16 ounces}, @bay leaves{}, and @water{}. In inner cooking pot of #InstantPot, combine @chickpeas{1 can, 15-16 ounces}, @bay leaves{}, and @water{}.
@@ -7,6 +7,7 @@ source: garnish-and-gather
description: description:
prep_time: 35 minutesnutes prep_time: 35 minutesnutes
totalTime: PT35M totalTime: PT35M
image: https://roux.roo.lol/recipe-images/chicken-and-pumpkin-gnocchi-with-ricotta.webp
--- ---
Remove any large stems from @spinach{2 1/2 cups} and roughly chop. Remove any large stems from @spinach{2 1/2 cups} and roughly chop.
+1
View File
@@ -8,6 +8,7 @@ source: Unknown
description: A vegetarian curry with chickpeas, cauliflower, and coconut milk, served with spiced oil drizzle description: A vegetarian curry with chickpeas, cauliflower, and coconut milk, served with spiced oil drizzle
prep_time: 20 minutes prep_time: 20 minutes
cook_time: 20 minutes cook_time: 20 minutes
image: https://roux.roo.lol/recipe-images/chickpea-butter-curry.webp
--- ---
In a small #pot{}, bring 1 1/2 cups @water{} & @basmati rice{3/4 cup} to a boil, then cover, reduce heat to low, and cook ~{12-15 minutes} or until @rice{} is tender. In a small #pot{}, bring 1 1/2 cups @water{} & @basmati rice{3/4 cup} to a boil, then cover, reduce heat to low, and cook ~{12-15 minutes} or until @rice{} is tender.
+1
View File
@@ -3,6 +3,7 @@ title: Chickpea Butter Curry
servings: 2 servings: 2
category: Main category: Main
source: Rebel Recipes source: Rebel Recipes
image: https://roux.roo.lol/recipe-images/chickpea-butter-curry-2.webp
--- ---
In a small pot, bring 1 1/2 cups water and @basmati rice{3/4%cup} to a boil, then cover, reduce heat to low, and cook 12-15 minutes or until rice is tender. In a small pot, bring 1 1/2 cups water and @basmati rice{3/4%cup} to a boil, then cover, reduce heat to low, and cook 12-15 minutes or until rice is tender.
+1
View File
@@ -8,6 +8,7 @@ source: Unknown
description: Shrimp in orange sauce with brussels sprouts and carrots served over scallion rice description: Shrimp in orange sauce with brussels sprouts and carrots served over scallion rice
prep_time: 15 minutes prep_time: 15 minutes
cook_time: 15 minutes cook_time: 15 minutes
image: https://roux.roo.lol/recipe-images/chinese-orange-shrimp.webp
--- ---
In a #pot{}, bring 1 1/2 cups @water{} & @salt{1/4 teaspoon} to a boil. In a #pot{}, bring 1 1/2 cups @water{} & @salt{1/4 teaspoon} to a boil.
@@ -3,6 +3,7 @@ title: Chocolate Mousse Cake with Raspberries
servings: 24 servings: 24
category: Desserts category: Desserts
source: King Arthur Baking source: King Arthur Baking
image: https://roux.roo.lol/recipe-images/chocolate-mousse-cake-with-raspberries.webp
--- ---
Preheat the oven to 325°F. Lightly grease two 8" round pans (or adjust for your pan mix) and line with parchment. Preheat the oven to 325°F. Lightly grease two 8" round pans (or adjust for your pan mix) and line with parchment.
+1
View File
@@ -7,6 +7,7 @@ source: Unknown
description: description:
prep_time: 20 minutes prep_time: 20 minutes
totalTime: PT20M totalTime: PT20M
image: https://roux.roo.lol/recipe-images/cilantro-pesto-shrimp-over-orzo.webp
--- ---
Juice HALF of @lemon{1} and cut remainder into wedges. Juice HALF of @lemon{1} and cut remainder into wedges.
@@ -3,6 +3,7 @@ title: Crispy Roasted Chickpeas (Garbanzo Beans)
servings: 2 servings: 2
category: Snack category: Snack
source: Unknown source: Unknown
image: https://roux.roo.lol/recipe-images/crispy-roasted-chickpeas-garbanzo-beans.webp
--- ---
Preheat the oven to 400°F. Preheat the oven to 400°F.
@@ -4,7 +4,7 @@ servings: 4
category: uncategorized category: uncategorized
source: https://cooking.nytimes.com/recipes/1021200-crispy-tofu-with-cashews-and-blistered-snap-peas?campaign_id=9&emc=edit_nn_20230415&instance_id=90280&nl=the-morning&regi_id=123169868&segment_id=130511&te=1&user_id=c5863897ec3230a42bc044f493123ca2 source: https://cooking.nytimes.com/recipes/1021200-crispy-tofu-with-cashews-and-blistered-snap-peas?campaign_id=9&emc=edit_nn_20230415&instance_id=90280&nl=the-morning&regi_id=123169868&segment_id=130511&te=1&user_id=c5863897ec3230a42bc044f493123ca2
description: A ginger and coconut milk reduction can coat pretty much anything that browns nicely on its own. Here, it's pieces of pan-seared tofu, but small morsels of chicken and pork will work just as well. The soy and teaspoons of molasses give sauce a little caramelization, and a little shine and gloss. For a fresh side, add some blistered snap peas, tossed with sliced scallions, a little mint and a splash of rice vinegar. Snow peas, green beans, broccoli or asparagus? If it's fresh and green, it'll work just fine. description: A ginger and coconut milk reduction can coat pretty much anything that browns nicely on its own. Here, it's pieces of pan-seared tofu, but small morsels of chicken and pork will work just as well. The soy and teaspoons of molasses give sauce a little caramelization, and a little shine and gloss. For a fresh side, add some blistered snap peas, tossed with sliced scallions, a little mint and a splash of rice vinegar. Snow peas, green beans, broccoli or asparagus? If it's fresh and green, it'll work just fine.
image: https://kitchen.roo.lol/data/images/9fe7eb34-2b1c-4dba-88e8-eb4ba4abea8e.webp image: https://roux.roo.lol/recipe-images/crispy-tofu-with-cashews-and-blistered-snap-peas.webp
--- ---
Slice @tofu{1 (14-ounce) block, firm or extra-firm, drained} in half horizontally, and leave on #paper towels{} to dry any excess liquid. Slice @tofu{1 (14-ounce) block, firm or extra-firm, drained} in half horizontally, and leave on #paper towels{} to dry any excess liquid.
@@ -3,6 +3,7 @@ title: Crispy Roasted Chickpeas (Garbanzo Beans)
servings: 2 servings: 2
category: Snack category: Snack
source: Unknown source: Unknown
image: https://roux.roo.lol/recipe-images/crispy-roasted-chickpeas-garbanzo-beans-2.webp
--- ---
Preheat the oven to 400°F. Preheat the oven to 400°F.
+1
View File
@@ -11,6 +11,7 @@ tags:
- soup - soup
description: A slow-simmered dried fava bean soup with roasted tomatoes, garlic, and onion, finished with mint and cilantro and topped with a tangy quick-pickled guajillo chile mixture. description: A slow-simmered dried fava bean soup with roasted tomatoes, garlic, and onion, finished with mint and cilantro and topped with a tangy quick-pickled guajillo chile mixture.
source: 101 Cookbooks (adapted from Rick Baylesss Mexican Kitchen) source: 101 Cookbooks (adapted from Rick Baylesss Mexican Kitchen)
image: https://roux.roo.lol/recipe-images/dried-fava-soup.webp
--- ---
Make sure the @hulled dried fava bean{1%lb} are clean and free of dirt, then rinse them well. Make sure the @hulled dried fava bean{1%lb} are clean and free of dirt, then rinse them well.
+1
View File
@@ -3,6 +3,7 @@ title: EASY LEMON ROSEMARY WHITE BEAN SOUP
servings: 4 servings: 4
category: Soup category: Soup
source: Simple Veganista source: Simple Veganista
image: https://roux.roo.lol/recipe-images/easy-lemon-rosemary-white-bean-soup.webp
--- ---
Saute @olive oil{2%tbsp} in a large pot. Add @onion{1%small}, @carrots{3%large} and @celery{2 stalks}; cook for 7 minutes until softened. Saute @olive oil{2%tbsp} in a large pot. Add @onion{1%small}, @carrots{3%large} and @celery{2 stalks}; cook for 7 minutes until softened.
+1 -1
View File
@@ -4,7 +4,7 @@ servings: 6
category: uncategorized category: uncategorized
source: https://www.loveandlemons.com/vegetarian-chili-recipe/ source: https://www.loveandlemons.com/vegetarian-chili-recipe/
description: You'll LOVE this easy vegetarian chili recipe! It's gluten-free, and without yogurt or sour cream on top, it's also vegan. description: You'll LOVE this easy vegetarian chili recipe! It's gluten-free, and without yogurt or sour cream on top, it's also vegan.
image: https://kitchen.roo.lol/data/images/61187b69-c326-4ad4-aa03-f3eb7c0b1806.webp image: https://roux.roo.lol/recipe-images/easy-vegetarian-chili.webp
--- ---
Heat @extra-virgin olive oil{2 tablespoons} in a large #pot{} over medium heat. Add @yellow onion{1 small, chopped}, a few pinches of @salt{} and @pepper{}, and stir. Cook until @onion{} is translucent, ~{5 minutes}, then add @garlic{2 cloves, minced} and @red bell pepper{1, diced}. Stir and cook until soft, ~{5 to 8 minutes}, turning heat down as needed. Heat @extra-virgin olive oil{2 tablespoons} in a large #pot{} over medium heat. Add @yellow onion{1 small, chopped}, a few pinches of @salt{} and @pepper{}, and stir. Cook until @onion{} is translucent, ~{5 minutes}, then add @garlic{2 cloves, minced} and @red bell pepper{1, diced}. Stir and cook until soft, ~{5 to 8 minutes}, turning heat down as needed.
+1
View File
@@ -3,6 +3,7 @@ title: EASY LEMON ROSEMARY WHITE BEAN SOUP
servings: 4 servings: 4
category: Soup category: Soup
source: Simple Veganista source: Simple Veganista
image: https://roux.roo.lol/recipe-images/easy-lemon-rosemary-white-bean-soup-2.webp
--- ---
Saute @olive oil{2%tbsp} in a large pot. Add @onion{1%small}, @carrots{3%large} and @celery{2 stalks}; cook for 7 minutes until softened. Saute @olive oil{2%tbsp} in a large pot. Add @onion{1%small}, @carrots{3%large} and @celery{2 stalks}; cook for 7 minutes until softened.
@@ -6,7 +6,7 @@ source: Mealie
description: This is basically spaghetti with a sauce made from scratch. The sauce is great and I think this whole recipe is really good especially considering the ingredients are so basic. description: This is basically spaghetti with a sauce made from scratch. The sauce is great and I think this whole recipe is really good especially considering the ingredients are so basic.
I added red pepper to the recipe for extra kick. I added red pepper to the recipe for extra kick.
image: https://kitchen.roo.lol/data/images/1a3fbf92-6d4b-4f74-adf3-0b004b5f021a.webp image: https://roux.roo.lol/recipe-images/fettucine-with-spiced-cherry-tomato-sauce.webp
prep_time: 30 minutes prep_time: 30 minutes
cook_time: 1 hour cook_time: 1 hour
--- ---
+1
View File
@@ -6,6 +6,7 @@ tags: bulgogi,garnish-and-gather,korean,lettuce wraps
source: Unknown source: Unknown
description: description:
prep_time: 20 minutes prep_time: 20 minutes
image: https://roux.roo.lol/recipe-images/gaja-s-bulgogi-lettuce-wraps.webp
--- ---
Pat @steak bulgogi{8 oz} dry. Pat @steak bulgogi{8 oz} dry.
+1
View File
@@ -7,6 +7,7 @@ tags: crispy rice,garnish-and-gather,gochugaru,korean,salmon
source: Unknown source: Unknown
description: Salmon with spicy honey sauce served with crispy rice, broccoli, and carrots description: Salmon with spicy honey sauce served with crispy rice, broccoli, and carrots
prep_time: 25 minutes prep_time: 25 minutes
image: https://roux.roo.lol/recipe-images/gochugaru-honey-salmon.webp
--- ---
In a #pot{}, bring 1 1/2 cups @water{} to a boil for @rice{3/4 cup, long grain}. In a #pot{}, bring 1 1/2 cups @water{} to a boil for @rice{3/4 cup, long grain}.
+1 -1
View File
@@ -4,7 +4,7 @@ servings: 6
category: Thanksgiving category: Thanksgiving
source: https://www.foodnetwork.com/recipes/patrick-and-gina-neely/green-beans-with-lemon-and-garlic-recipe-1938670 source: https://www.foodnetwork.com/recipes/patrick-and-gina-neely/green-beans-with-lemon-and-garlic-recipe-1938670
description: The Neelys' healthy Green Beans with Lemon and Garlic recipe from Food Network is the perfect, simple side for any occasion. Quickly blanch and finish on the skillet, these green beans will be on the table in less than 20 minutes. description: The Neelys' healthy Green Beans with Lemon and Garlic recipe from Food Network is the perfect, simple side for any occasion. Quickly blanch and finish on the skillet, these green beans will be on the table in less than 20 minutes.
image: https://kitchen.roo.lol/data/images/704b15f5-0eda-4f7f-8762-1d8f36c2dea6.webp image: https://roux.roo.lol/recipe-images/green-beans-with-lemon-and-garlic.webp
nutrition: nutrition:
calories: 122 kcal calories: 122 kcal
carbohydrate: 11g carbohydrate: 11g
+1
View File
@@ -7,6 +7,7 @@ source: Unknown
description: description:
prep_time: 20 minutes prep_time: 20 minutes
cook_time: 20 minutes cook_time: 20 minutes
image: https://roux.roo.lol/recipe-images/indian-spiced-chicken-2.webp
--- ---
Bring 1 1/2 cups @water{} & @salt{1/4 tsp} to a boil in a #pot{}. Bring 1 1/2 cups @water{} & @salt{1/4 tsp} to a boil in a #pot{}.
@@ -1,3 +1,12 @@
---
title: Italian Sausage & Delicata Rigatoni
description:
servings: 1
category: uncategorized
source: Unknown
image: https://roux.roo.lol/recipe-images/italian-sausage-and-delicata-rigatoni.webp
---
>> title: Italian Sausage & Delicata Rigatoni >> title: Italian Sausage & Delicata Rigatoni
>> author: Chef Robin Pridgen >> author: Chef Robin Pridgen
>> servings: 2 >> servings: 2
+1
View File
@@ -8,6 +8,7 @@ source: Garnish & Gather — Chef Emily Golub
description: Cozy kale-and-chestnut stew finished with cream and topped with a bright parsleywalnut pesto. Allergens: dairy, walnuts. description: Cozy kale-and-chestnut stew finished with cream and topped with a bright parsleywalnut pesto. Allergens: dairy, walnuts.
prep_time: 20 minutes prep_time: 20 minutes
cook_time: 35 minutes cook_time: 35 minutes
image: https://roux.roo.lol/recipe-images/kale-and-chestnut-stew.webp
--- ---
Remove any large stems from @kale{3 c} and thinly slice into ribbons. Remove any large stems from @kale{3 c} and thinly slice into ribbons.
+1
View File
@@ -4,6 +4,7 @@ servings: 2
category: uncategorized category: uncategorized
source: https://thekoreanvegan.com/spicy-crunchy-garlic-tofu-kkampoong-tofu/ source: https://thekoreanvegan.com/spicy-crunchy-garlic-tofu-kkampoong-tofu/
description: description:
image: https://roux.roo.lol/recipe-images/kkanpoong-tofu.webp
--- ---
To a large #bowl{}, add a pinch of @salt{} and 2 tablespoons of @potato starch{} to @tofu{1 16 ounce block, extra firm, pressed and chopped into 1/2 inch bite sized chunks}. Gently toss @tofu{} to make sure they are all evenly coated. Set aside. To a large #bowl{}, add a pinch of @salt{} and 2 tablespoons of @potato starch{} to @tofu{1 16 ounce block, extra firm, pressed and chopped into 1/2 inch bite sized chunks}. Gently toss @tofu{} to make sure they are all evenly coated. Set aside.
+1
View File
@@ -8,6 +8,7 @@ source: Unknown
description: Crispy shrimp tacos with gochujang sauce and bok choy rice salad description: Crispy shrimp tacos with gochujang sauce and bok choy rice salad
prep_time: 25 minutes prep_time: 25 minutes
cook_time: 25 minutes cook_time: 25 minutes
image: https://roux.roo.lol/recipe-images/korean-shrimp-tacos.webp
--- ---
In a #pot{}, bring 1 1/2 cups @water{} & @salt{1/4 teaspoon} to a boil. In a #pot{}, bring 1 1/2 cups @water{} & @salt{1/4 teaspoon} to a boil.
@@ -6,6 +6,7 @@ tags: chinese,garnish-and-gather,kung pao,shrimp
source: Unknown source: Unknown
description: description:
prep_time: 25 minutes prep_time: 25 minutes
image: https://roux.roo.lol/recipe-images/kung-pao-shrimp-with-sichuan-roasted-green-beans.webp
--- ---
Preheat #oven{} to 425°. Preheat #oven{} to 425°.
+1
View File
@@ -5,6 +5,7 @@ category: Cookies
tags: cookies tags: cookies
source: Mealie source: Mealie
description: description:
image: https://roux.roo.lol/recipe-images/lactation-cookies.webp
--- ---
Preheat #oven{} to 350°. Preheat #oven{} to 350°.
+1
View File
@@ -3,6 +3,7 @@ title: Lactation Cookies
servings: 12 servings: 12
category: Cookies category: Cookies
source: Mealie source: Mealie
image: https://roux.roo.lol/recipe-images/lactation-cookies-2.webp
--- ---
@butter{1%cup} @butter{1%cup}
+1 -1
View File
@@ -4,7 +4,7 @@ servings: 8
category: uncategorized category: uncategorized
source: https://www.inspiredtaste.net/40400/lentil-soup/ source: https://www.inspiredtaste.net/40400/lentil-soup/
description: This is our favorite lentil soup recipe. I make this soup with lentils, carrots, turmeric, and fresh lemon whenever we are in need of some healthy comfort food. It's savory, satisfying, and utterly delicious. I like quite a bit of fresh lemon in this soup and actually serve soup with slices of lemon. This adds even more lemony flavor and shows that lemon was added to soup. description: This is our favorite lentil soup recipe. I make this soup with lentils, carrots, turmeric, and fresh lemon whenever we are in need of some healthy comfort food. It's savory, satisfying, and utterly delicious. I like quite a bit of fresh lemon in this soup and actually serve soup with slices of lemon. This adds even more lemony flavor and shows that lemon was added to soup.
image: https://kitchen.roo.lol/data/images/47a68b65-c916-4c5d-86f2-ea989ea310a7.webp image: https://roux.roo.lol/recipe-images/lentil-soup-with-lemon-and-turmeric.webp
--- ---
Heat @olive oil{2 tablespoons} in a large #pot{} (like a #Dutch oven{}) over medium heat. Add @onions{2 cups, finely chopped (1 medium onion)}, @carrot{1 1/2 cups, chopped (2 large carrots)}, and @salt{1/4 teaspoon} of and cook, stirring occasionally until they are softened and starting to smell sweet, about ~{5 to 7 minutes}. Stir in @garlic{2 teaspoons, minced (3 cloves)}, @ground cumin{1 teaspoon}, @ground coriander{1/2 teaspoon}, @fresh ground black pepper{1/2 teaspoon}, and @ground turmeric{1/2 teaspoon} and cook for ~{30 seconds}. Heat @olive oil{2 tablespoons} in a large #pot{} (like a #Dutch oven{}) over medium heat. Add @onions{2 cups, finely chopped (1 medium onion)}, @carrot{1 1/2 cups, chopped (2 large carrots)}, and @salt{1/4 teaspoon} of and cook, stirring occasionally until they are softened and starting to smell sweet, about ~{5 to 7 minutes}. Stir in @garlic{2 teaspoons, minced (3 cloves)}, @ground cumin{1 teaspoon}, @ground coriander{1/2 teaspoon}, @fresh ground black pepper{1/2 teaspoon}, and @ground turmeric{1/2 teaspoon} and cook for ~{30 seconds}.
@@ -3,6 +3,7 @@ title: Moroccan Spiced Lentil & Chickpea Soup
servings: 1 servings: 1
category: Soup category: Soup
source: Rebel Recipes source: Rebel Recipes
image: https://roux.roo.lol/recipe-images/moroccan-spiced-lentil-chickpea-soup.webp
--- ---
In a large pan, add @olive oil{2%tbsp} and @onion{1%large}(chopped); cook on medium heat for 7-8 minutes until soft and browning. In a large pan, add @olive oil{2%tbsp} and @onion{1%large}(chopped); cook on medium heat for 7-8 minutes until soft and browning.
@@ -3,6 +3,7 @@ title: Moroccan Spiced Lentil & Chickpea Soup
servings: 1 servings: 1
category: Soup category: Soup
source: Rebel Recipes source: Rebel Recipes
image: https://roux.roo.lol/recipe-images/moroccan-spiced-lentil-and-chickpea-soup.webp
--- ---
In a large pan, add @olive oil{2%tbsp} and @onion{1%large}(chopped); cook on medium heat for 7-8 minutes until soft and browning. In a large pan, add @olive oil{2%tbsp} and @onion{1%large}(chopped); cook on medium heat for 7-8 minutes until soft and browning.
+1
View File
@@ -8,6 +8,7 @@ tags:
- breakfast - breakfast
- rolls - rolls
- orange - orange
image: https://roux.roo.lol/recipe-images/orange-rolls.webp
--- ---
Make the dough: Heat the #oven to 375°F. Place @light brown sugar{1/3%cup} in a small #bowl and zest the @orange{1} directly over it. Gently rub the zest into the sugar and transfer 2 tablespoons/25 grams of the orange sugar to a large #bowl to use for the dough. Save the rest of the orange sugar for the filling. Make the dough: Heat the #oven to 375°F. Place @light brown sugar{1/3%cup} in a small #bowl and zest the @orange{1} directly over it. Gently rub the zest into the sugar and transfer 2 tablespoons/25 grams of the orange sugar to a large #bowl to use for the dough. Save the rest of the orange sugar for the filling.
+1
View File
@@ -3,6 +3,7 @@ title: Palak Paneer
servings: 4 servings: 4
category: Indian category: Indian
source: Mealie source: Mealie
image: https://roux.roo.lol/recipe-images/palak-paneer.webp
--- ---
Preheat the #Instant Pot by selecting Sauté and adjust to More for high heat. When the inner cooking pot is hot, add @peanut oil{2%tbsp} and heat until it is shimmering. Add @garlic cloves{5}(minced), @ginger{2%tsp}(minced), and @serrano or jalapeño chile{1}(minced), and sauté for ~{1%minute} or until fragrant. Preheat the #Instant Pot by selecting Sauté and adjust to More for high heat. When the inner cooking pot is hot, add @peanut oil{2%tbsp} and heat until it is shimmering. Add @garlic cloves{5}(minced), @ginger{2%tsp}(minced), and @serrano or jalapeño chile{1}(minced), and sauté for ~{1%minute} or until fragrant.
+1 -1
View File
@@ -4,7 +4,7 @@ servings: 10
category: uncategorized category: uncategorized
source: https://www.theflavorbender.com/make-passion-fruit-curd/#recipe source: https://www.theflavorbender.com/make-passion-fruit-curd/#recipe
description: Makes about 1 1/4 cups of passion fruit curd description: Makes about 1 1/4 cups of passion fruit curd
image: https://kitchen.roo.lol/data/images/803d123d-d98f-4a68-a820-e47c88b7a66a.webp image: https://roux.roo.lol/recipe-images/passion-fruit-curd-recipe.webp
--- ---
Indirect Heat Method Indirect Heat Method
+1
View File
@@ -8,6 +8,7 @@ source: Unknown
description: Pan-seared trout with pecan-brown butter sauce, served with herbed sweet potatoes, radishes, and wilted greens description: Pan-seared trout with pecan-brown butter sauce, served with herbed sweet potatoes, radishes, and wilted greens
prep_time: 30 minutes prep_time: 30 minutes
cook_time: 30 minutes cook_time: 30 minutes
image: https://roux.roo.lol/recipe-images/pecan-brown-butter-trout.webp
--- ---
Preheat #oven{} to 400°F. Preheat #oven{} to 400°F.
+1 -1
View File
@@ -4,7 +4,7 @@ servings: 10
category: uncategorized category: uncategorized
source: https://www.101cookbooks.com/ribollita-recipe/ source: https://www.101cookbooks.com/ribollita-recipe/
description: Ribollita, a beautifully thick Tuscan stew made with dark greens, lots of beans, vegetables, olive oil, and thickened with day-old bread. One of my favorites. description: Ribollita, a beautifully thick Tuscan stew made with dark greens, lots of beans, vegetables, olive oil, and thickened with day-old bread. One of my favorites.
image: https://kitchen.roo.lol/data/images/4bc005e2-168b-43bb-a75e-a463eb5bbdc6.webp image: https://roux.roo.lol/recipe-images/ribollita.webp
prep_time: 15 minutes prep_time: 15 minutes
cook_timee:25 minutesinutes cook_timee:25 minutesinutes
totalTime: PT40M totalTime: PT40M
+1
View File
@@ -7,6 +7,7 @@ servings: 5
category: uncategorized category: uncategorized
source: https://www.skinnytaste.com/roasted-pumpkin-sage-soup source: https://www.skinnytaste.com/roasted-pumpkin-sage-soup
tags: soup, pumpkin, fall, vegetarian-option, gluten-free tags: soup, pumpkin, fall, vegetarian-option, gluten-free
image: https://roux.roo.lol/recipe-images/roasted-pumpkin-sage.webp
--- ---
Heat the oven to 400°F. Heat the oven to 400°F.
+1
View File
@@ -3,6 +3,7 @@ title: Saag Paneer
servings: 1 servings: 1
category: Indian category: Indian
source: Mealie source: Mealie
image: https://roux.roo.lol/recipe-images/saag-paneer.webp
--- ---
Preheat the #Instant Pot by selecting Sauté and adjust to More for high heat. When the inner cooking pot is hot, add @peanut oil{2%tbsp} and heat until it is shimmering. Add @garlic cloves{5}(minced), @ginger{2%tsp}(minced), and @serrano or jalapeno chile{1}(minced), and sauté for ~{1%minute} or until fragrant. Preheat the #Instant Pot by selecting Sauté and adjust to More for high heat. When the inner cooking pot is hot, add @peanut oil{2%tbsp} and heat until it is shimmering. Add @garlic cloves{5}(minced), @ginger{2%tsp}(minced), and @serrano or jalapeno chile{1}(minced), and sauté for ~{1%minute} or until fragrant.
+1 -1
View File
@@ -4,7 +4,7 @@ servings: 4
category: Thanksgiving category: Thanksgiving
source: https://www.marthastewart.com/316639/sauteed-asparagus-with-lemon source: https://www.marthastewart.com/316639/sauteed-asparagus-with-lemon
description: description:
image: https://kitchen.roo.lol/data/images/15498ca3-db5d-461f-a3b7-ce6674fc6bea.webp image: https://roux.roo.lol/recipe-images/sauteed-asparagus-with-lemon.webp
--- ---
In a large #skillet{}, heat @olive oil{1 tablespoon} over medium. Add @asparagus{2 bunches, 14 ounces each, ends trimmed}, and season with @coarse salt{} and @ground pepper{}. Cook, tossing occasionally, until lightly browned and crisp-tender, ~{10 to 15 minutes}, depending on thickness. Add @lemon zest{4 wide strips} and cook ~{1 minute}. Add @lemon juice{from 1/2 lemon}, toss to coat, and serve warm. In a large #skillet{}, heat @olive oil{1 tablespoon} over medium. Add @asparagus{2 bunches, 14 ounces each, ends trimmed}, and season with @coarse salt{} and @ground pepper{}. Cook, tossing occasionally, until lightly browned and crisp-tender, ~{10 to 15 minutes}, depending on thickness. Add @lemon zest{4 wide strips} and cook ~{1 minute}. Add @lemon juice{from 1/2 lemon}, toss to coat, and serve warm.
+1 -1
View File
@@ -4,7 +4,7 @@ servings: 6
category: uncategorized category: uncategorized
source: https://acleanbake.com/slow-cooker-chicken-shawarma/ source: https://acleanbake.com/slow-cooker-chicken-shawarma/
description: Slow cooker chicken shawarma combines the ease of a slow cooker meal with the complex flavor of a slow-roasted middle eastern chicken feast! This is a quick version of middle eastern favorite: the slow cooker does a lot of the work and it can be prepped ahead of time. Various serving options make this sensational paleo and gluten free dinner recipe adaptable for low carb and Whole30 compliance, too! description: Slow cooker chicken shawarma combines the ease of a slow cooker meal with the complex flavor of a slow-roasted middle eastern chicken feast! This is a quick version of middle eastern favorite: the slow cooker does a lot of the work and it can be prepped ahead of time. Various serving options make this sensational paleo and gluten free dinner recipe adaptable for low carb and Whole30 compliance, too!
image: https://kitchen.roo.lol/data/images/0cea2c65-f549-4f57-97fd-5a1d23941297.webp image: https://roux.roo.lol/recipe-images/slow-cooker-chicken-shawarma.webp
--- ---
Place @chicken breasts{2 lbs, boneless, skinless} in #bowl{} of your #slow cooker{}, and add @water{1/2 cup}. Cook on high ~{2 hours} until @chicken{} is cooked through (the juices run clear and @fat{} has rendered out of @chicken{}). Place @chicken breasts{2 lbs, boneless, skinless} in #bowl{} of your #slow cooker{}, and add @water{1/2 cup}. Cook on high ~{2 hours} until @chicken{} is cooked through (the juices run clear and @fat{} has rendered out of @chicken{}).
+1 -1
View File
@@ -4,7 +4,7 @@ servings: 10
category: Thanksgiving category: Thanksgiving
source: https://cooking.nytimes.com/recipes/1020515-southern-macaroni-and-cheese source: https://cooking.nytimes.com/recipes/1020515-southern-macaroni-and-cheese
description: There is macaroni and cheese, and then there is special occasion macaroni and cheese like this one. Unlike most recipes, which start with a roux, this one begins with a milk-and-egg base, which gives the dish an incredibly rich, silky taste. It's adapted from Millie Peartree, the owner of Millie Peartree Fish Fry & Soul Food restaurant in the Bronx, who has been making this dish since she was a little girl. The recipe was passed down in her family for generations, but because of the generous amount of cheese used, the dish was only made for events like Christmas and Thanksgiving. Extra-sharp Cheddar adds tartness and a layer of Colby Jack creates a gooey, molten center. If you can't find a Colby Jack blend, shredded mozzarella or a Mexican-style blend will work in its place. description: There is macaroni and cheese, and then there is special occasion macaroni and cheese like this one. Unlike most recipes, which start with a roux, this one begins with a milk-and-egg base, which gives the dish an incredibly rich, silky taste. It's adapted from Millie Peartree, the owner of Millie Peartree Fish Fry & Soul Food restaurant in the Bronx, who has been making this dish since she was a little girl. The recipe was passed down in her family for generations, but because of the generous amount of cheese used, the dish was only made for events like Christmas and Thanksgiving. Extra-sharp Cheddar adds tartness and a layer of Colby Jack creates a gooey, molten center. If you can't find a Colby Jack blend, shredded mozzarella or a Mexican-style blend will work in its place.
image: https://kitchen.roo.lol/data/images/657048ab-342f-4ca3-84cb-fe9dcb3ae2a4.webp image: https://roux.roo.lol/recipe-images/southern-macaroni-and-cheese.webp
--- ---
Heat #oven{} to 350 degrees. Bring a large #pot{} of generously salted water to a boil. Add @elbow macaroni{1%pound} and cook according to package directions until a little under al dente, about ~{4%minutes}. Transfer to a #colander{} and rinse under cold water to stop cooking. Set aside. Heat #oven{} to 350 degrees. Bring a large #pot{} of generously salted water to a boil. Add @elbow macaroni{1%pound} and cook according to package directions until a little under al dente, about ~{4%minutes}. Transfer to a #colander{} and rinse under cold water to stop cooking. Set aside.
+1
View File
@@ -8,6 +8,7 @@ source: Unknown
description: description:
prep_time: 15 minutes prep_time: 15 minutes
cook_time: 15 minutes cook_time: 15 minutes
image: https://roux.roo.lol/recipe-images/spaghetti-carbonara.webp
--- ---
Trim root from @lettuce{1 head} and separate into leaves. Trim root from @lettuce{1 head} and separate into leaves.
@@ -3,6 +3,7 @@ title: Spaghetti Squash w/ Chickpeas & Kale
servings: 3 servings: 3
category: Main category: Main
source: Love and Lemons source: Love and Lemons
image: https://roux.roo.lol/recipe-images/spaghetti-squash-w-chickpeas-and-kale.webp
--- ---
Preheat the oven to 400F. Preheat the oven to 400F.
Prepare your squash following the directions in this post. Prepare your squash following the directions in this post.
+1
View File
@@ -3,6 +3,7 @@ title: Skillet Spanakopita (Greek Spinach Feta Pie)
servings: 8 servings: 8
category: Greek category: Greek
source: From a Chef's Kitchen source: From a Chef's Kitchen
image: https://roux.roo.lol/recipe-images/spanakopita.webp
--- ---
Preheat the oven to 375 degrees. Preheat the oven to 375 degrees.
+1
View File
@@ -8,6 +8,7 @@ tags:
- paella - paella
- shrimp - shrimp
- spanish - spanish
image: https://roux.roo.lol/recipe-images/spicy-shrimp-paella.webp
--- ---
In a large sauté #pan, cook @chorizo{2%oz} over medium for ~{3-5%minutes}, until cooked through, then remove, keeping drippings in the pan. In a large sauté #pan, cook @chorizo{2%oz} over medium for ~{3-5%minutes}, until cooked through, then remove, keeping drippings in the pan.
+1 -1
View File
@@ -4,7 +4,7 @@ servings: 12
category: uncategorized category: uncategorized
source: https://www.bonappetit.com/recipe/strawberry-wild-rice-tartlets source: https://www.bonappetit.com/recipe/strawberry-wild-rice-tartlets
description: This simple six-ingredient dessert is vegan and bursting with texture (crispy wild rice crust) and flavor (rehydrated cherries with fresh strawberries for the filling). description: This simple six-ingredient dessert is vegan and bursting with texture (crispy wild rice crust) and flavor (rehydrated cherries with fresh strawberries for the filling).
image: https://kitchen.roo.lol/data/images/ed78da5c-1aa5-4d0b-90bc-4d317b7f7b89.webp image: https://roux.roo.lol/recipe-images/strawberry-and-wild-rice-tartlets.webp
--- ---
Heat #oven{} to 350°. Brush the cups of one standard 12-cup #muffin pan{} or two standard 6-cup #muffin pans{} with @vegetable oil{}. Bring 6 cups lightly salted @water{} to a boil in a medium #saucepan{}. Add @wild rice{1 cup}, cover, and cook until @water{} evaporates and grains split open, about ~{1½ hours}. Spread out @rice{} on a large rimmed #baking sheet{} and let cool. Reserve #pan{}. Heat #oven{} to 350°. Brush the cups of one standard 12-cup #muffin pan{} or two standard 6-cup #muffin pans{} with @vegetable oil{}. Bring 6 cups lightly salted @water{} to a boil in a medium #saucepan{}. Add @wild rice{1 cup}, cover, and cook until @water{} evaporates and grains split open, about ~{1½ hours}. Spread out @rice{} on a large rimmed #baking sheet{} and let cool. Reserve #pan{}.
+1
View File
@@ -3,6 +3,7 @@ title: Thai Veggie Pad See Ew
servings: 2 servings: 2
category: Thai category: Thai
source: Unknown source: Unknown
image: https://roux.roo.lol/recipe-images/thai-veggie-pad-see-ew.webp
--- ---
Bring water to a boil for rice noodles. Bring water to a boil for rice noodles.
+1 -1
View File
@@ -4,7 +4,7 @@ servings: 1
category: uncategorized category: uncategorized
source: Unknown source: Unknown
description: Georgie Grasso recipe - GGBO winner 2024 with this recipe featured! description: Georgie Grasso recipe - GGBO winner 2024 with this recipe featured!
image: https://kitchen.roo.lol/data/images/d15cdb2C-71db-42d7-a603-a29389e13bd3.webp image: https://roux.roo.lol/recipe-images/tiramisu.webp
prep_time: 15 minutes prep_time: 15 minutes
cook_time: 30 minutes cook_time: 30 minutes
--- ---
@@ -3,6 +3,7 @@ title: Warm Up With a Quick Lemony Chicken Soup
servings: 6 servings: 6
category: Soup category: Soup
source: EatingWell source: EatingWell
image: https://roux.roo.lol/recipe-images/warm-up-with-a-quick-lemony-chicken-soup.webp
--- ---
Heat @olive oil{1%tbsp} in a Dutch oven over medium-high. Add @carrots{3/4%cup} and @yellow onion{1/2%cup}; cook, stirring often, until vegetables are softened, 3 to 4 minutes. Add @garlic cloves{2}(minced) and @crushed red pepper flakes{3/4%tsp}, and cook, stirring constantly, until fragrant, about 1 minute. Heat @olive oil{1%tbsp} in a Dutch oven over medium-high. Add @carrots{3/4%cup} and @yellow onion{1/2%cup}; cook, stirring often, until vegetables are softened, 3 to 4 minutes. Add @garlic cloves{2}(minced) and @crushed red pepper flakes{3/4%tsp}, and cook, stirring constantly, until fragrant, about 1 minute.
+1
View File
@@ -7,6 +7,7 @@ source: Unknown
description: description:
prep_time: 25 minutes prep_time: 25 minutes
cook_time: 25 minutes cook_time: 25 minutes
image: https://roux.roo.lol/recipe-images/west-african-peanut-chicken.webp
--- ---
Mince @fresno pepper{1}—remove seeds and use only half for less heat. Mince @fresno pepper{1}—remove seeds and use only half for less heat.
+1 -1
View File
@@ -3,7 +3,7 @@ title: Wheat Berry Salad
servings: 1 servings: 1
description: This healthy wheat berry salad is a delicious fall side dish or lunch with dried cranberries, fresh herbs, walnuts, and a tangy vinaigrette. description: This healthy wheat berry salad is a delicious fall side dish or lunch with dried cranberries, fresh herbs, walnuts, and a tangy vinaigrette.
source: https://www.loveandlemons.com/wheat-berry-salad/ source: https://www.loveandlemons.com/wheat-berry-salad/
image: https://kitchen.roo.lol/data/images/eb72067c-28c7-4ae3-88ed-1fc0b9aba762.webp image: https://roux.roo.lol/recipe-images/wheat-berry-salad.webp
--- ---
= Wheat berries = = Wheat berries =
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
while IFS='|' read -r file slug; do
url=$(grep "^image:" "$file" | sed 's/^image:[[:space:]]*//')
echo "[$slug] Downloading from $url"
curl -sL -o "recipe-images/$slug.webp" "$url" || echo "[$slug] DOWNLOAD FAILED"
done
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -euo pipefail
slug="$1"
url="$2"
echo "[$slug] Fetching $url" >&2
html=$(curl -sL --max-time 15 "$url" 2>/dev/null) || { echo "[$slug] FETCH FAILED" >&2; echo ""; exit 0; }
# Try multiple og:image patterns
img_url=$(echo "$html" | grep -oP 'property="og:image"\s+content="[^"]*"' | sed 's/.*content="//;s/"//' | head -1)
if [ -z "$img_url" ]; then
img_url=$(echo "$html" | grep -oP 'name="og:image"\s+content="[^"]*"' | sed 's/.*content="//;s/"//' | head -1)
fi
if [ -z "$img_url" ]; then
img_url=$(echo "$html" | grep -oP 'content="[^"]*"[^>]*property="og:image"' | sed 's/.*content="//;s/".*//' | head -1)
fi
if [ -n "$img_url" ]; then
echo "[$slug] Found: $img_url" >&2
echo "$img_url"
else
echo "[$slug] No og:image found" >&2
fi
+242
View File
@@ -0,0 +1,242 @@
#!/usr/bin/env python3
"""Final attempt: search DDG text, scrape recipe pages for actual images."""
import csv
import json
import re
import sys
import time
from pathlib import Path
import requests
from bs4 import BeautifulSoup
from ddgs import DDGS
WORKDIR = Path("/home/jbrechtel/recipes/.worktrees/recipe-images")
HEADERS = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
}
SKIP_DOMAINS = {"pinterest", "facebook", "instagram", "twitter", "youtube", "tiktok"}
MIN_IMAGE_SIZE = 10000 # 10KB minimum for a recipe photo
def search_url(query: str) -> str | None:
"""Search and return first relevant recipe page URL."""
try:
results = list(DDGS().text(query, max_results=8))
except Exception as e:
print(f" Search error: {e}", file=sys.stderr)
return None
for r in results:
url = r.get("href", "")
domain = url.split("/")[2] if "//" in url else ""
if any(s in domain for s in SKIP_DOMAINS):
continue
# Prefer recipe sites
if any(kw in domain for kw in ["recipe", "cook", "food", "kitchen", "nytimes", "loveandlemons"]):
return url
# Return first non-wikipedia result
for r in results:
url = r.get("href", "")
if "wikipedia.org" not in url:
return url
return None
def find_recipe_images(url: str) -> list[str]:
"""Fetch a page and find actual recipe/food images."""
try:
resp = requests.get(url, headers=HEADERS, timeout=15, allow_redirects=True)
resp.raise_for_status()
except requests.RequestException:
return []
soup = BeautifulSoup(resp.text, "html.parser")
images = []
# 1. Check JSON-LD for recipe image
for script in soup.find_all("script", type="application/ld+json"):
try:
data = json.loads(script.string)
except (json.JSONDecodeError, TypeError):
continue
# Handle list or single
items = data if isinstance(data, list) else [data]
for item in items:
if not isinstance(item, dict):
continue
if item.get("@type") == "Recipe":
img = item.get("image")
if isinstance(img, str):
images.append(img)
elif isinstance(img, list):
for i in img:
if isinstance(i, str):
images.append(i)
elif isinstance(i, dict):
u = i.get("contentUrl") or i.get("url", "")
if u:
images.append(u)
elif isinstance(img, dict):
u = img.get("contentUrl") or img.get("url", "")
if u:
images.append(u)
# 2. Check og:image
for meta in soup.find_all("meta"):
content = meta.get("content", "")
if (meta.get("property") == "og:image" or meta.get("name") == "og:image" or meta.get("name") == "twitter:image"):
if content and "logo" not in content.lower():
images.append(content)
# 3. Check all img tags for large, relevant images
for img in soup.find_all("img"):
src = img.get("src") or img.get("data-src") or ""
if not src.startswith("http"):
continue
src_lower = src.lower()
if any(kw in src_lower for kw in ["logo", "avatar", "icon", "banner", "pixel", "spacer", "thumb"]):
continue
# Check for recipe-related class/id
parent_classes = ""
parent = img.parent
if parent:
parent_classes = " ".join(parent.get("class", []) or []) + " " + (parent.get("id") or "")
if any(kw in parent_classes.lower() for kw in ["logo", "nav", "header", "footer", "menu", "icon"]):
continue
images.append(src)
# Deduplicate
seen = set()
unique = []
for img in images:
if img not in seen:
seen.add(img)
unique.append(img)
return unique
def download_image(url: str, dest: Path) -> bool:
"""Download image, validate it's a real image."""
try:
resp = requests.get(url, headers=HEADERS, timeout=30, stream=True)
resp.raise_for_status()
ct = resp.headers.get("content-type", "")
if not ct.startswith("image/"):
return False
content = resp.content
if len(content) < MIN_IMAGE_SIZE:
return False
dest.write_bytes(content)
return True
except requests.RequestException:
return False
def get_title(filepath: Path) -> str:
content = filepath.read_text(encoding="utf-8")
m = re.search(r"^title:\s*(.+)$", content, re.MULTILINE)
if m:
return m.group(1).strip()
return filepath.stem.replace("_", " ").replace("-", " ")
def add_image_field(filepath: Path, slug: str):
url = f"https://roux.roo.lol/recipe-images/{slug}.webp"
content = filepath.read_text(encoding="utf-8")
if re.search(r"^image:", content, re.MULTILINE):
content = re.sub(r"^image:.*$", f"image: {url}", count=1, flags=re.MULTILINE, string=content)
else:
content = re.sub(r"^---$", f"image: {url}\n---", count=1, flags=re.MULTILINE, string=content)
filepath.write_text(content, encoding="utf-8")
print(f" Updated {filepath.name}", file=sys.stderr)
def get_source_url(filepath: Path) -> str | None:
content = filepath.read_text(encoding="utf-8")
m = re.search(r"^source:\s*(.+)$", content, re.MULTILINE)
if m:
val = m.group(1).strip()
if val.startswith("http"):
return val
return None
def main():
csv_file = WORKDIR / "docs" / "no-image-has-fm.csv"
recipes = []
with open(csv_file) as f:
reader = csv.reader(f, delimiter="|")
for row in reader:
if len(row) >= 2:
recipes.append((row[0].strip(), row[1].strip()))
success = []
failed = []
for filename, slug in recipes:
filepath = WORKDIR / filename
if not filepath.exists():
failed.append(slug)
continue
dest = WORKDIR / "recipe-images" / f"{slug}.webp"
# Skip if already has image AND file exists
content = filepath.read_text(encoding="utf-8")
has_field = bool(re.search(r"^image:", content, re.MULTILINE))
has_file = dest.exists()
if has_field and has_file and dest.stat().st_size > 10000:
print(f"[{slug}] Already done, skipping", file=sys.stderr)
success.append(slug)
continue
title = get_title(filepath)
query = f"{title} recipe"
print(f"[{slug}] Searching: {query}", file=sys.stderr)
page_url = search_url(query)
if not page_url:
print(f" No search results", file=sys.stderr)
failed.append(slug)
continue
print(f" Page: {page_url}", file=sys.stderr)
time.sleep(0.3)
img_urls = find_recipe_images(page_url)
if not img_urls:
print(f" No images found on page", file=sys.stderr)
failed.append(slug)
continue
downloaded = False
for img_url in img_urls[:5]:
print(f" Trying: {img_url[:80]}...", file=sys.stderr)
if download_image(img_url, dest):
print(f" Downloaded ({dest.stat().st_size} bytes)", file=sys.stderr)
add_image_field(filepath, slug)
downloaded = True
break
time.sleep(0.2)
if downloaded:
success.append(slug)
else:
failed.append(slug)
time.sleep(0.5)
print(f"\n=== Results ===", file=sys.stderr)
print(f"Success: {len(success)}", file=sys.stderr)
print(f"Failed: {len(failed)}", file=sys.stderr)
if failed:
print(f"Failed: {', '.join(failed)}", file=sys.stderr)
if __name__ == "__main__":
main()
+95
View File
@@ -0,0 +1,95 @@
#!/usr/bin/env python3
"""Find images for remaining 6 recipes."""
import re, sys, time
from pathlib import Path
import requests
from bs4 import BeautifulSoup
from ddgs import DDGS
WORKDIR = Path("/home/jbrechtel/recipes/.worktrees/recipe-images")
HEADERS = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36"}
recipes = [
("Arugula Pesto Chicken with Pecans & Roasted Butternut.cook", "arugula-pesto-chicken-with-pecans-roasted-butternut", "Arugula Pesto Chicken Pecans Roasted Butternut recipe garnishandgather"),
("Bang Bang Tofu.cook", "bang-bang-tofu", "Bang Bang Tofu recipe"),
("Chana Chickpea Salad.cook", "chana-chickpea-salad", "Chana Chickpea Salad recipe"),
("Gaja's Bulgogi Lettuce Wraps.cook", "gaja-s-bulgogi-lettuce-wraps", "Gaja Bulgogi Lettuce Wraps recipe garnishandgather"),
("Pecan-Brown Butter Trout.cook", "pecan-brown-butter-trout", "Pecan Brown Butter Trout recipe"),
("West African Peanut Chicken.cook", "west-african-peanut-chicken", "West African Peanut Chicken recipe"),
]
for file, slug, query in recipes:
fp = WORKDIR / file
dest = WORKDIR / "recipe-images" / f"{slug}.webp"
if dest.exists() and dest.stat().st_size > 10000:
print(f"[{slug}] Already done")
continue
print(f"[{slug}] Searching: {query}")
try:
results = list(DDGS().text(query, max_results=5))
except Exception as e:
print(f" Search error: {e}")
continue
found = False
for r in results:
url = r.get("href", "")
if not url or any(s in url for s in ["pinterest","facebook","instagram"]):
continue
print(f" Fetching: {url}")
try:
resp = requests.get(url, headers=HEADERS, timeout=15)
resp.raise_for_status()
except Exception as e:
print(f" Failed: {e}")
continue
soup = BeautifulSoup(resp.text, "html.parser")
img_urls = []
# og:image
for meta in soup.find_all("meta"):
c = meta.get("content", "")
p = (meta.get("property") or "").lower()
n = (meta.get("name") or "").lower()
if ("og:image" in p or "og:image" in n or "twitter:image" in n) and c and "logo" not in c.lower():
img_urls.append(c)
# img tags
for img in soup.find_all("img"):
src = img.get("src") or img.get("data-src") or ""
if src.startswith("http") and "logo" not in src.lower() and "icon" not in src.lower():
img_urls.append(src)
for img_url in img_urls[:5]:
try:
r2 = requests.get(img_url, headers=HEADERS, timeout=15)
r2.raise_for_status()
ct = r2.headers.get("content-type", "")
if ct.startswith("image/") and len(r2.content) > 10000:
dest.write_bytes(r2.content)
print(f" Downloaded ({len(r2.content)} bytes): {img_url[:60]}")
found = True
break
except:
pass
if found:
break
time.sleep(0.3)
if found:
# Add image field
url_val = f"https://roux.roo.lol/recipe-images/{slug}.webp"
content = fp.read_text(encoding="utf-8")
if re.search(r"^image:", content, re.MULTILINE):
content = re.sub(r"^image:.*$", f"image: {url_val}", count=1, flags=re.MULTILINE, string=content)
else:
content = re.sub(r"^---$", f"image: {url_val}\n---", count=1, flags=re.MULTILINE, string=content)
fp.write_text(content, encoding="utf-8")
print(f" Updated image field")
else:
print(f" FAILED")
time.sleep(0.5)
print("\nDone!")
+128
View File
@@ -0,0 +1,128 @@
#!/usr/bin/env python3
"""Fix the broken YAML frontmatter: move image field inside YAML, and convert non-WebP images."""
import re, subprocess, sys
from pathlib import Path
WORKDIR = Path("/home/jbrechtel/recipes/.worktrees/recipe-images")
def fix_frontmatter(content: str) -> str:
"""Move image: field inside the YAML block if it's outside."""
# Check if image: is before the opening ---
lines = content.split('\n')
# Find the first --- line
first_hr = -1
for i, line in enumerate(lines):
if line.strip() == '---':
first_hr = i
break
if first_hr <= 0:
return content # No frontmatter or image is at first line
# Check if the line just before the first --- has image:
if first_hr > 0 and lines[first_hr - 1].startswith('image:'):
# Extract the image line
img_line = lines[first_hr - 1]
# Remove it from before ---
del lines[first_hr - 1]
# Now first_hr is one index less (or same if we deleted the line before)
# Find the closing ---
closing_hr = -1
for i in range(first_hr, len(lines)):
if lines[i].strip() == '---':
closing_hr = i
break
if closing_hr > first_hr:
# Insert image line before the closing ---
lines.insert(closing_hr, img_line)
else:
# Insert after the closing --- (fallback)
lines.insert(first_hr + 1, img_line)
return '\n'.join(lines)
def fix_all_frontmatter():
"""Fix frontmatter for all .cook files."""
fixed = 0
for f in sorted(WORKDIR.glob("*.cook")):
content = f.read_text(encoding="utf-8")
fixed_content = fix_frontmatter(content)
if fixed_content != content:
f.write_text(fixed_content, encoding="utf-8")
print(f" Fixed: {f.name}")
fixed += 1
print(f"\nFixed {fixed} files with mis-placed image fields")
return fixed
def convert_images():
"""Convert non-WebP images to actual WebP format."""
converted = 0
for img in sorted(WORKDIR.glob("recipe-images/*.webp")):
mime = subprocess.run(
["file", "-b", "--mime-type", str(img)],
capture_output=True, text=True
).stdout.strip()
if mime != "image/webp":
print(f" Converting {img.name} (mime: {mime})")
# Use temp file to avoid corruption
tmp = img.with_suffix(".webp.tmp")
result = subprocess.run(
["convert", str(img), str(tmp)],
capture_output=True, text=True
)
if result.returncode == 0 and tmp.exists():
tmp.replace(img)
print(f" Converted successfully")
converted += 1
else:
print(f" Convert failed: {result.stderr}")
print(f"\nConverted {converted} images to proper WebP")
return converted
if __name__ == "__main__":
print("=== Fixing YAML frontmatter ===")
fix_all_frontmatter()
print("\n=== Converting image formats ===")
convert_images()
# Final check
print("\n=== Final verification ===")
bad = 0
for f in sorted(WORKDIR.glob("*.cook")):
content = f.read_text(encoding="utf-8")
# Check if image: is between --- markers
if "image:" in content:
# Find the opening ---
parts = content.split('---', 2)
if len(parts) >= 3:
if "image:" not in parts[1]:
print(f" STILL BROKEN: {f.name}")
bad += 1
if bad == 0:
print(" All files have image: inside YAML block ✅")
webp_count = 0
non_webp_count = 0
for img in sorted(WORKDIR.glob("recipe-images/*.webp")):
mime = subprocess.run(
["file", "-b", "--mime-type", str(img)],
capture_output=True, text=True
).stdout.strip()
if mime == "image/webp":
webp_count += 1
else:
non_webp_count += 1
if non_webp_count <= 5:
print(f" NOT WEBP: {img.name} ({mime})")
print(f" WebP images: {webp_count}, Non-WebP: {non_webp_count}")
+171
View File
@@ -0,0 +1,171 @@
#!/usr/bin/env python3
"""Scrape og:image from recipe source URLs, download images, update .cook files."""
import csv
import os
import re
import sys
import time
from pathlib import Path
import requests
from bs4 import BeautifulSoup
WORKDIR = Path("/home/jbrechtel/recipes/.worktrees/recipe-images")
HEADERS = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
}
def get_source_url(filepath: Path) -> str | None:
"""Extract the source URL from a .cook file's YAML frontmatter."""
content = filepath.read_text(encoding="utf-8")
match = re.search(r"^source:\s*(.+)$", content, re.MULTILINE)
if not match:
return None
val = match.group(1).strip()
# Only return actual URLs
if val.startswith("http://") or val.startswith("https://"):
return val
return None
def fetch_og_image(url: str, timeout: int = 20) -> str | None:
"""Fetch a page and extract og:image URL."""
try:
resp = requests.get(url, headers=HEADERS, timeout=timeout, allow_redirects=True)
resp.raise_for_status()
except requests.RequestException as e:
print(f" FETCH FAILED: {e}", file=sys.stderr)
return None
soup = BeautifulSoup(resp.text, "html.parser")
# Try og:image meta tag
for meta in soup.find_all("meta"):
if meta.get("property") == "og:image" and meta.get("content"):
return meta["content"]
if meta.get("name") == "og:image" and meta.get("content"):
return meta["content"]
# Try twitter:image
for meta in soup.find_all("meta"):
if meta.get("name") == "twitter:image" and meta.get("content"):
return meta["content"]
# Try finding the first large image (common in recipe sites)
for img in soup.find_all("img"):
src = img.get("src") or ""
if "logo" in src.lower() or "avatar" in src.lower() or "icon" in src.lower():
continue
if src.startswith("http") and any(kw in src.lower() for kw in ["upload", "wp-content", "images"]):
return src
return None
def download_image(url: str, dest: Path) -> bool:
"""Download an image from URL to destination path."""
try:
resp = requests.get(url, headers=HEADERS, timeout=30, stream=True)
resp.raise_for_status()
dest.write_bytes(resp.content)
return True
except requests.RequestException as e:
print(f" DOWNLOAD FAILED: {e}", file=sys.stderr)
return False
def add_image_field(filepath: Path, slug: str):
"""Add or update the image field in a .cook file's YAML frontmatter."""
url = f"https://roux.roo.lol/recipe-images/{slug}.webp"
content = filepath.read_text(encoding="utf-8")
# If image field already exists, replace it
if re.search(r"^image:", content, re.MULTILINE):
content = re.sub(r"^image:.*$", f"image: {url}", content, count=1, flags=re.MULTILINE)
else:
# Insert before closing ---
content = re.sub(r"^---$", f"image: {url}\n---", content, count=1, flags=re.MULTILINE)
filepath.write_text(content, encoding="utf-8")
print(f" Updated image field: {filepath.name}", file=sys.stderr)
def process_recipe(filepath: Path, slug: str) -> bool:
"""Process a single recipe: find image, download, update frontmatter."""
dest = WORKDIR / "recipe-images" / f"{slug}.webp"
# Skip if already downloaded
if dest.exists():
print(f"[{slug}] Image already exists, skipping download", file=sys.stderr)
add_image_field(filepath, slug)
return True
# Try to get source URL and scrape image
src_url = get_source_url(filepath)
if src_url:
print(f"[{slug}] Scraping {src_url}", file=sys.stderr)
img_url = fetch_og_image(src_url)
if img_url:
print(f" Found: {img_url}", file=sys.stderr)
if download_image(img_url, dest):
print(f" Downloaded to {dest.name}", file=sys.stderr)
add_image_field(filepath, slug)
return True
else:
print(f" Download failed", file=sys.stderr)
return False
def main():
csv_file = WORKDIR / "docs" / "no-image-has-fm.csv"
if not csv_file.exists():
print(f"CSV not found: {csv_file}", file=sys.stderr)
sys.exit(1)
recipes = []
with open(csv_file) as f:
reader = csv.reader(f, delimiter="|")
for row in reader:
if len(row) >= 2:
recipes.append((row[0].strip(), row[1].strip()))
print(f"Processing {len(recipes)} recipes...", file=sys.stderr)
success = []
failed = []
for filename, slug in recipes:
filepath = WORKDIR / filename
if not filepath.exists():
print(f"[{slug}] File not found: {filepath}", file=sys.stderr)
failed.append(slug)
continue
ok = process_recipe(filepath, slug)
if ok:
success.append(slug)
else:
failed.append(slug)
# Be polite to servers
time.sleep(0.5)
print(f"\n=== Results ===", file=sys.stderr)
print(f"Success: {len(success)}", file=sys.stderr)
print(f"Failed: {len(failed)}", file=sys.stderr)
if failed:
print(f"Failed slugs: {', '.join(failed)}", file=sys.stderr)
# Write failed slugs to file for retry
if failed:
with open(WORKDIR / "docs" / "failed-images.csv", "w") as f:
for slug in failed:
f.write(f"{slug}\n")
if __name__ == "__main__":
main()
+233
View File
@@ -0,0 +1,233 @@
#!/usr/bin/env python3
"""Search the web for recipe images, download them, and update .cook files.
Uses DuckDuckGo search to find recipe pages, then scrapes og:image.
"""
import csv
import os
import re
import sys
import time
from pathlib import Path
import requests
from bs4 import BeautifulSoup
from duckduckgo_search import DDGS
WORKDIR = Path("/home/jbrechtel/recipes/.worktrees/recipe-images")
HEADERS = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
}
IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".webp", ".gif"}
def fetch_og_image(url: str) -> str | None:
"""Fetch a page and extract og:image URL."""
try:
resp = requests.get(url, headers=HEADERS, timeout=15, allow_redirects=True)
resp.raise_for_status()
except requests.RequestException:
return None
soup = BeautifulSoup(resp.text, "html.parser")
# Try og:image meta tag (property or name)
for meta in soup.find_all("meta"):
prop = (meta.get("property") or "").lower()
name = (meta.get("name") or "").lower()
content = meta.get("content", "")
if "og:image" in prop and content:
return content
if "og:image" in name and content:
return content
if "twitter:image" in name and content:
return content
# Try schema.org JSON-LD
for script in soup.find_all("script", type="application/ld+json"):
import json
try:
data = json.loads(script.string)
if isinstance(data, dict):
img = data.get("image")
if isinstance(img, str) and img.startswith("http"):
return img
if isinstance(img, dict):
url = img.get("contentUrl") or img.get("url", "")
if url.startswith("http"):
return url
if isinstance(img, list) and img:
first = img[0]
if isinstance(first, str):
return first
if isinstance(first, dict):
url = first.get("contentUrl") or first.get("url", "")
if url.startswith("http"):
return url
except (json.JSONDecodeError, AttributeError):
pass
return None
def search_and_find_image(query: str) -> str | None:
"""Search DuckDuckGo for a recipe and find og:image."""
try:
results = list(DDGS().text(query, max_results=5))
except Exception as e:
print(f" Search error: {e}", file=sys.stderr)
return None
for r in results:
url = r.get("href", "")
if not url or "pinterest" in url or "facebook" in url or "instagram" in url:
continue
print(f" Trying: {url}", file=sys.stderr)
img = fetch_og_image(url)
if img:
print(f" Found image: {img}", file=sys.stderr)
return img
time.sleep(0.3)
return None
def download_image(url: str, dest: Path) -> bool:
"""Download an image from URL to destination path."""
try:
resp = requests.get(url, headers=HEADERS, timeout=30, stream=True)
resp.raise_for_status()
dest.write_bytes(resp.content)
return True
except requests.RequestException as e:
print(f" Download failed: {e}", file=sys.stderr)
return False
def add_image_field(filepath: Path, slug: str):
"""Add or update the image field in a .cook file's YAML frontmatter."""
url = f"https://roux.roo.lol/recipe-images/{slug}.webp"
content = filepath.read_text(encoding="utf-8")
if re.search(r"^image:", content, re.MULTILINE):
content = re.sub(r"^image:.*$", f"image: {url}", count=1, flags=re.MULTILINE, string=content)
else:
content = re.sub(r"^---$", f"image: {url}\n---", count=1, flags=re.MULTILINE, string=content)
filepath.write_text(content, encoding="utf-8")
print(f" Updated {filepath.name}", file=sys.stderr)
def get_source_url(filepath: Path) -> str | None:
"""Extract source URL from .cook frontmatter."""
content = filepath.read_text(encoding="utf-8")
match = re.search(r"^source:\s*(.+)$", content, re.MULTILINE)
if match:
val = match.group(1).strip()
if val.startswith("http://") or val.startswith("https://"):
return val
return None
def process_recipe(filename: str, slug: str) -> bool:
"""Try to find and download an image for a recipe."""
filepath = WORKDIR / filename
dest = WORKDIR / "recipe-images" / f"{slug}.webp"
if dest.exists():
print(f"[{slug}] Already exists", file=sys.stderr)
add_image_field(filepath, slug)
return True
# Strategy 1: Try source URL if available
src_url = get_source_url(filepath)
if src_url:
print(f"[{slug}] Trying source URL: {src_url}", file=sys.stderr)
img = fetch_og_image(src_url)
if img:
if download_image(img, dest):
print(f" Downloaded from source", file=sys.stderr)
add_image_field(filepath, slug)
return True
# Strategy 2: Search by recipe name
# Get the title from frontmatter
content = filepath.read_text(encoding="utf-8")
title_match = re.search(r"^title:\s*(.+)$", content, re.MULTILINE)
if title_match:
query = title_match.group(1).strip() + " recipe"
else:
query = filename.replace(".cook", "").replace("_", " ").replace("-", " ") + " recipe"
print(f"[{slug}] Searching: {query}", file=sys.stderr)
img = search_and_find_image(query)
if img and download_image(img, dest):
print(f" Downloaded from search", file=sys.stderr)
add_image_field(filepath, slug)
return True
# Strategy 3: Try with "og:image" or "recipe image" variations
query2 = query + " image"
print(f"[{slug}] Searching (alt): {query2}", file=sys.stderr)
img = search_and_find_image(query2)
if img and download_image(img, dest):
print(f" Downloaded from alt search", file=sys.stderr)
add_image_field(filepath, slug)
return True
return False
def main():
# First process the no-image-has-fm list
csv_file = WORKDIR / "docs" / "no-image-has-fm.csv"
if not csv_file.exists():
print(f"CSV not found: {csv_file}", file=sys.stderr)
sys.exit(1)
recipes = []
with open(csv_file) as f:
reader = csv.reader(f, delimiter="|")
for row in reader:
if len(row) >= 2:
recipes.append((row[0].strip(), row[1].strip()))
success = []
failed = []
for filename, slug in recipes:
filepath = WORKDIR / filename
if not filepath.exists():
failed.append(slug)
continue
dest = WORKDIR / "recipe-images" / f"{slug}.webp"
if dest.exists() and re.search(r"^image:", filepath.read_text(), re.MULTILINE):
print(f"[{slug}] Already processed, skipping", file=sys.stderr)
success.append(slug)
continue
ok = process_recipe(filename, slug)
if ok:
success.append(slug)
else:
failed.append(slug)
# Be polite
time.sleep(0.5)
print(f"\n=== Results ===", file=sys.stderr)
print(f"Success: {len(success)}", file=sys.stderr)
print(f"Failed: {len(failed)}", file=sys.stderr)
if failed:
with open(WORKDIR / "docs" / "failed-images.csv", "w") as f:
for s in failed:
f.write(f"{s}\n")
print(f"Failed: {', '.join(failed)}", file=sys.stderr)
if __name__ == "__main__":
main()
+148
View File
@@ -0,0 +1,148 @@
#!/usr/bin/env python3
"""Search DuckDuckGo Images for recipe photos, download, update .cook files."""
import csv
import re
import sys
import time
from pathlib import Path
import requests
from duckduckgo_search import DDGS
WORKDIR = Path("/home/jbrechtel/recipes/.worktrees/recipe-images")
HEADERS = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
}
def download_image(url: str, dest: Path) -> bool:
"""Download an image from URL to destination path."""
try:
resp = requests.get(url, headers=HEADERS, timeout=30, stream=True)
resp.raise_for_status()
# Validate it's actually an image
content_type = resp.headers.get("content-type", "")
if not content_type.startswith("image/"):
print(f" Not an image (content-type: {content_type})", file=sys.stderr)
return False
dest.write_bytes(resp.content)
return True
except requests.RequestException as e:
print(f" Download failed: {e}", file=sys.stderr)
return False
def add_image_field(filepath: Path, slug: str):
"""Add or update the image field in a .cook file."""
url = f"https://roux.roo.lol/recipe-images/{slug}.webp"
content = filepath.read_text(encoding="utf-8")
if re.search(r"^image:", content, re.MULTILINE):
content = re.sub(r"^image:.*$", f"image: {url}", count=1, flags=re.MULTILINE, string=content)
else:
content = re.sub(r"^---$", f"image: {url}\n---", count=1, flags=re.MULTILINE, string=content)
filepath.write_text(content, encoding="utf-8")
print(f" Updated {filepath.name}", file=sys.stderr)
def search_images(query: str, max_results: int = 5):
"""Search DuckDuckGo Images for a recipe and return image URLs."""
try:
results = list(DDGS().images(query, max_results=max_results))
return [r["image"] for r in results if r.get("image")]
except Exception as e:
print(f" Image search error: {e}", file=sys.stderr)
return []
def get_title(filepath: Path) -> str:
"""Extract title from .cook frontmatter."""
content = filepath.read_text(encoding="utf-8")
match = re.search(r"^title:\s*(.+)$", content, re.MULTILINE)
if match:
return match.group(1).strip()
# Fall back to filename
name = filepath.stem
return name.replace("_", " ").replace("-", " ")
def main():
csv_file = WORKDIR / "docs" / "failed-images.csv"
# Also check which are actually missing
existing_csv = WORKDIR / "docs" / "no-image-has-fm.csv"
recipes = []
with open(existing_csv) as f:
reader = csv.reader(f, delimiter="|")
for row in reader:
if len(row) >= 2:
recipes.append((row[0].strip(), row[1].strip()))
# Filter to those without an image file or without image field
to_process = []
for filename, slug in recipes:
filepath = WORKDIR / filename
dest = WORKDIR / "recipe-images" / f"{slug}.webp"
has_image_file = dest.exists()
has_image_field = False
if filepath.exists():
content = filepath.read_text(encoding="utf-8")
has_image_field = bool(re.search(r"^image:", content, re.MULTILINE))
if not has_image_file or not has_image_field:
to_process.append((filename, slug))
print(f"Processing {len(to_process)} remaining recipes...", file=sys.stderr)
success = []
failed = []
for filename, slug in to_process:
filepath = WORKDIR / filename
dest = WORKDIR / "recipe-images" / f"{slug}.webp"
if not filepath.exists():
failed.append(slug)
continue
title = get_title(filepath)
queries = [
f"{title} recipe",
title,
]
found = False
for query in queries:
print(f"[{slug}] Searching images: {query}", file=sys.stderr)
urls = search_images(query)
for img_url in urls:
# Skip tiny icons, logos
if any(kw in img_url.lower() for kw in ["logo", "icon", "avatar", "merriam", "wikipedia"]):
continue
print(f" Trying: {img_url[:80]}...", file=sys.stderr)
if download_image(img_url, dest):
print(f" Downloaded!", file=sys.stderr)
add_image_field(filepath, slug)
found = True
break
time.sleep(0.2)
if found:
break
time.sleep(0.5)
if found:
success.append(slug)
else:
failed.append(slug)
print(f"\n=== Results ===", file=sys.stderr)
print(f"Success: {len(success)}", file=sys.stderr)
print(f"Failed: {len(failed)}", file=sys.stderr)
if failed:
print(f"Failed: {', '.join(failed)}", file=sys.stderr)
if __name__ == "__main__":
main()
+156
View File
@@ -0,0 +1,156 @@
#!/usr/bin/env python3
"""Add frontmatter and images to 9 recipes without frontmatter."""
import re, sys, time
from pathlib import Path
import requests
from bs4 import BeautifulSoup
from ddgs import DDGS
WORKDIR = Path("/home/jbrechtel/recipes/.worktrees/recipe-images")
HEADERS = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36"}
# (filename, slug, title, source_url_or_empty)
recipes = [
("Black Pepper Tofu (Ottolenghi).cook", "black-pepper-tofu-ottolenghi", "Black Pepper Tofu (Ottolenghi)", ""),
("Black Pepper Tofu with Bok Choy.cook", "black-pepper-tofu-with-bok-choy", "Black Pepper Tofu with Bok Choy", ""),
("butternut-turkey-chili.cook", "butternut-turkey-chili", "Butternut & Turkey Chili", ""),
("Caramel Cake.cook", "caramel-cake", "Caramel Cake", ""),
("Caramel Icing.cook", "caramel-icing", "Caramel Icing", ""),
("example-fried-rice.cook", "example-fried-rice", "Fried Rice", ""),
("indian-spiced-chicken.cook", "indian-spiced-chicken", "Indian Spiced Chicken", ""),
("Italian Sausage and Delicata Rigatoni.cook", "italian-sausage-and-delicata-rigatoni", "Italian Sausage & Delicata Rigatoni", ""),
("shrimp-feta.cook", "shrimp-feta", "Orzo with shrimp, tomato and marinated feta", "https://thehappyfoodie.co.uk/recipes/ottolenghis-orzo-with-prawns-tomato-and-marinated-feta/"),
]
def fetch_og_image(url: str) -> str | None:
try:
resp = requests.get(url, headers=HEADERS, timeout=15)
resp.raise_for_status()
except:
return None
soup = BeautifulSoup(resp.text, "html.parser")
for meta in soup.find_all("meta"):
c = meta.get("content", "")
p = (meta.get("property") or "").lower()
n = (meta.get("name") or "").lower()
if ("og:image" in p or "og:image" in n or "twitter:image" in n) and c:
return c
# JSON-LD
for script in soup.find_all("script", type="application/ld+json"):
try:
import json
data = json.loads(script.string)
items = data if isinstance(data, list) else [data]
for item in items:
if isinstance(item, dict) and item.get("@type") == "Recipe":
img = item.get("image")
if isinstance(img, str): return img
if isinstance(img, list):
for i in img:
if isinstance(i, str): return i
if isinstance(i, dict):
u = i.get("contentUrl") or i.get("url", "")
if u: return u
if isinstance(img, dict):
u = img.get("contentUrl") or img.get("url", "")
if u: return u
except:
pass
return None
def search_and_scrape(query: str) -> str | None:
try:
results = list(DDGS().text(query, max_results=5))
except:
return None
for r in results:
url = r.get("href", "")
if not url or "pinterest" in url or "facebook" in url:
continue
img = fetch_og_image(url)
if img:
return img
time.sleep(0.3)
return None
def download_image(url: str, dest: Path) -> bool:
try:
resp = requests.get(url, headers=HEADERS, timeout=30)
resp.raise_for_status()
ct = resp.headers.get("content-type", "")
if not ct.startswith("image/"):
return False
content = resp.content
if len(content) < 5000:
return False
dest.write_bytes(content)
return True
except:
return False
def add_frontmatter(filepath: Path, slug: str, title: str):
url = f"https://roux.roo.lol/recipe-images/{slug}.webp"
content = filepath.read_text(encoding="utf-8")
frontmatter = f"""---
title: {title}
description:
servings: 1
category: uncategorized
source: Unknown
image: {url}
---
"""
filepath.write_text(frontmatter + content, encoding="utf-8")
print(f" Added frontmatter to {filepath.name}", file=sys.stderr)
def main():
for filename, slug, title, src_url in recipes:
fp = WORKDIR / filename
dest = WORKDIR / "recipe-images" / f"{slug}.webp"
print(f"[{slug}] Processing {filename}", file=sys.stderr)
# Find and download image
img_url = None
if src_url:
print(f" Trying source URL: {src_url}", file=sys.stderr)
img_url = fetch_og_image(src_url)
time.sleep(0.3)
if not img_url:
print(f" Searching: {title} recipe", file=sys.stderr)
img_url = search_and_scrape(f"{title} recipe")
time.sleep(0.3)
if not img_url:
print(f" Searching (alt): {title}", file=sys.stderr)
img_url = search_and_scrape(title)
time.sleep(0.3)
if img_url:
print(f" Found: {img_url[:80]}", file=sys.stderr)
if download_image(img_url, dest):
print(f" Downloaded ({dest.stat().st_size} bytes)", file=sys.stderr)
else:
print(f" Download failed, will still add frontmatter", file=sys.stderr)
else:
print(f" No image found, will still add frontmatter", file=sys.stderr)
# Add frontmatter (with or without image)
add_frontmatter(fp, slug, title)
print(f" Done", file=sys.stderr)
print("\n=== Task 3 complete ===", file=sys.stderr)
if __name__ == "__main__":
main()
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
while IFS='|' read -r file slug; do
new_url="https://roux.roo.lol/recipe-images/$slug.webp"
sed -i "s|^image:.*|image: $new_url|" "$file"
echo "[$slug] Updated image field"
done
+9
View File
@@ -1,3 +1,12 @@
---
title: Butternut & Turkey Chili
description:
servings: 1
category: uncategorized
source: Unknown
image: https://roux.roo.lol/recipe-images/butternut-turkey-chili.webp
---
>> title: Butternut & Turkey Chili >> title: Butternut & Turkey Chili
>> author: Chef Torie Cox >> author: Chef Torie Cox
>> servings: 2 >> servings: 2
+1
View File
@@ -10,6 +10,7 @@ totalTime: 55 minutes
prepTime: 15 minutes prepTime: 15 minutes
cookTime: 40 minutes cookTime: 40 minutes
tags: arugula, bread crumb, budget, cauliflower, parmesan, sheet-pan, fall, vegetarian tags: arugula, bread crumb, budget, cauliflower, parmesan, sheet-pan, fall, vegetarian
image: https://roux.roo.lol/recipe-images/cauliflower-milanese.webp
--- ---
== Ingredients == == Ingredients ==
+20 -15
View File
@@ -4,7 +4,7 @@
**Goal:** Give every `.cook` recipe file an `image:` field in YAML frontmatter pointing to `https://roux.roo.lol/recipe-images/<slug>.webp`, and download each image locally. **Goal:** Give every `.cook` recipe file an `image:` field in YAML frontmatter pointing to `https://roux.roo.lol/recipe-images/<slug>.webp`, and download each image locally.
**Architecture:** Three parallel batches — (1) relink the 19 existing images, (2) discover + download + link 48 missing images (recipes with frontmatter), (3) create frontmatter + discover + link 9 more (recipes without frontmatter). Use subagent parallel dispatch for image discovery to keep wall-clock time manageable. **Architecture:** Three parallel batches — (1) relink the 19 existing images, (2) discover + download + link 50 missing images (recipes with frontmatter), (3) create frontmatter + discover + link 9 more (recipes without frontmatter). Use subagent parallel dispatch for image discovery to keep wall-clock time manageable.
**Tech Stack:** bash, curl, ImageMagick (convert), subagent researcher for web image search **Tech Stack:** bash, curl, ImageMagick (convert), subagent researcher for web image search
@@ -13,50 +13,56 @@
### Task 0: Setup — slug map, image dir, helper script ### Task 0: Setup — slug map, image dir, helper script
**Files:** **Files:**
- Create: `/home/jbrechtel/recipes/docs/slugs.csv` - Create: `docs/slugs.csv`
- Modify: none yet - Create: `docs/has-image.csv`
- Create: `docs/no-image-has-fm.csv`
- Create: `docs/no-fm.csv`
- [ ] **Step 1: Generate slug mapping** - [ ] **Step 1: Generate slug mapping**
Run a one-liner that prints every `.cook` file with its slugified stem: Run a one-liner that prints every `.cook` file with its slugified stem, then deduplicate any collisions:
```bash ```bash
cd /home/jbrechtel/recipes cd /home/jbrechtel/recipes/.worktrees/recipe-images
for f in *.cook; do for f in *.cook; do
stem="${f%.cook}" stem="${f%.cook}"
slug=$(echo "$stem" \ slug=$(echo "$stem" \
| tr '[:upper:]' '[:lower:]' \ | tr '[:upper:]' '[:lower:]' \
| sed -e 's/[^a-z0-9]/-/g' -e 's/--*/-/g' -e 's/^-//' -e 's/-$//') | sed -e 's/[^a-z0-9]/-/g' -e 's/--*/-/g' -e 's/^-//' -e 's/-$//')
echo "$f|$slug" echo "$f|$slug"
done > docs/slugs.csv done | awk -F'|' '
head docs/slugs.csv {
slug=$2
count[slug]++
if (count[slug] > 1) {
slug = slug "-" count[slug]
}
print $1 "|" slug
}' > docs/slugs.csv
``` ```
Expected: a pipe-delimited CSV like `Alain-Ducase-Bread.cook|alain-ducase-bread`. Total: 78 unique slugs (6 duplicate pairs get `-2` suffix).
- [ ] **Step 2: Create image directory** - [ ] **Step 2: Create image directory**
```bash ```bash
mkdir -p /home/jbrechtel/recipes/recipe-images mkdir -p recipe-images
``` ```
- [ ] **Step 3: Classify each recipe** - [ ] **Step 3: Classify each recipe**
```bash ```bash
cd /home/jbrechtel/recipes cd /home/jbrechtel/recipes/.worktrees/recipe-images
echo "=== Already has image ==="
while IFS='|' read -r f slug; do while IFS='|' read -r f slug; do
if grep -q "^image:" "$f" 2>/dev/null; then echo "$f|$slug"; fi if grep -q "^image:" "$f" 2>/dev/null; then echo "$f|$slug"; fi
done < docs/slugs.csv > docs/has-image.csv done < docs/slugs.csv > docs/has-image.csv
echo "=== Has frontmatter, no image ==="
while IFS='|' read -r f slug; do while IFS='|' read -r f slug; do
if head -1 "$f" 2>/dev/null | grep -q "^---"; then if head -1 "$f" 2>/dev/null | grep -q "^---"; then
if ! grep -q "^image:" "$f" 2>/dev/null; then echo "$f|$slug"; fi if ! grep -q "^image:" "$f" 2>/dev/null; then echo "$f|$slug"; fi
fi fi
done < docs/slugs.csv > docs/no-image-has-fm.csv done < docs/slugs.csv > docs/no-image-has-fm.csv
echo "=== No frontmatter ==="
while IFS='|' read -r f slug; do while IFS='|' read -r f slug; do
if ! head -1 "$f" 2>/dev/null | grep -q "^---"; then echo "$f|$slug"; fi if ! head -1 "$f" 2>/dev/null | grep -q "^---"; then echo "$f|$slug"; fi
done < docs/slugs.csv > docs/no-fm.csv done < docs/slugs.csv > docs/no-fm.csv
@@ -64,12 +70,11 @@ done < docs/slugs.csv > docs/no-fm.csv
wc -l docs/has-image.csv docs/no-image-has-fm.csv docs/no-fm.csv wc -l docs/has-image.csv docs/no-image-has-fm.csv docs/no-fm.csv
``` ```
Expected: 19 / 48 / 9 lines respectively. Expected: 19 / 50 / 9 = 78 total.
- [ ] **Step 4: Commit setup** - [ ] **Step 4: Commit setup**
```bash ```bash
cd /home/jbrechtel/recipes
git add docs/slugs.csv docs/has-image.csv docs/no-image-has-fm.csv docs/no-fm.csv git add docs/slugs.csv docs/has-image.csv docs/no-image-has-fm.csv docs/no-fm.csv
git commit -m "chore: add recipe slug mapping and classification CSVs" git commit -m "chore: add recipe slug mapping and classification CSVs"
``` ```
+9
View File
@@ -1,3 +1,12 @@
---
title: Fried Rice
description:
servings: 1
category: uncategorized
source: Unknown
image: https://roux.roo.lol/recipe-images/example-fried-rice.webp
---
-- TODO add source -- TODO add source
Mix together @oyster sauce{1%tbsp}, @soy sauce{5%tbsp} and @sesame oil{5%tsp}, set aside. Mix together @oyster sauce{1%tbsp}, @soy sauce{5%tbsp} and @sesame oil{5%tsp}, set aside.
+9
View File
@@ -1,3 +1,12 @@
---
title: Indian Spiced Chicken
description:
servings: 1
category: uncategorized
source: Gather and Garnish
image: https://roux.roo.lol/recipe-images/indian-spiced-chicken.webp
---
>> source: Gather and Garnish >> source: Gather and Garnish
>> time required: 35 minutes >> time required: 35 minutes
Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Some files were not shown because too many files have changed in this diff Show More