How to handle sidecar files?

I am trying to create an index of my recipes.

All my recipes are currently a mix of plain text files (named *.txt) and Markdown files (named *.md).

I want to create a small jekyll site that generates an index of these recipes as well as a static HTML page for each recipe.

I have a few problems that I haven’t found a solution to:

1: I have a collection of recipe files in a folder. Lets just focus on the .md files for now. Each file has a name like Some-title.md, Some-Other-Title.md, etc. I then want to list these with links. But this means that I want to link like this: <a href="/path/Some-title.html">Some title</a> <a href="/path/Some-Other-Title.html">Some Other Title</a>.

I basically want to convert “-” and “_” with " " as well as to remove the file extension when I present the link text but keep it in the actual href. How do I do this?

2: Another somewhat related issue is regarding what I would call sidecar files. What I mean by this is that each recipe is a single markdown file with the filename being the name of the dish with hyphens or underscores instead of spaces as well as the .md file extension. Now each recipe might have one or more sidecar files that relates to that recipe. A typical example is images. So for the recipe Tiramisu.md, there might be various Tiramisu*.jpg files. For example Tiramisu.jpg or even Tiramisu-01.jpg Tiramisu-02.jpg, …

This means that when I render Tiramisu.md, I need to generate something like this: <img src="Tiramisu.jpg"> for each such sidecar file - if they exist.

How can I accomplish this with Jekyll?

Maybe too obvious… but how about adding it to the front matter?

is this a jekyll collection or are you just using that word?

If you use a collection I think you get the title for free - and it will take the filename and output it with spaces?

I did a recipe site here and that is what it looks like it happening:

Yeah, I could do that. However, there are nearly a thousand files now. So I specifically want to do this programmatically and not by specifying anything in the front matter. I would like to now have to open and edit any files. I think it should be possible to do this programmatically.

It is a jekyll collection as well, although, I just used the word casually without thinking that it was ambiguous. I tried setting this up as a collection, however, it does not have to be a collection if there are better ways of doing it.

This is what I have in my _config.yml:

 20 defaults:                                                                        
 21   - scope:                                                                       
 22       path: "" # an empty string here means all files in the project.            
 23     values:                                                                      
 24       lang: da                                                                   
 25   - scope:                                                                       
 26       path: "_recipes/*.jpg"                                                     
 27     values:                                                                      
 28       image: true                                                                
 29                                                                                  
 30 collections:                                                                     
 31   recipes:                                                                       
 32     output: true                                                                 
 33     permalink: /recipes/:path                                                    
 34   pages:                                                                         
 35     output: true                                                                 
 36     permalink: /:path/index.html                                                 
 37                                       

I will take a look at your link.Thanks.

the more I think about it maybe you get a title for pages as well? I can’t see anything documenting it other than for posts where it is a thing for sure. But it seems to work on the collection on my recipe site - and maybe it would work for just regular pages too. Not sure. Normally when I do plain pages I add a title in front matter.

I used collections so I could use each collection as a category. Makes it easier/more efficient to categorize them.

As for the images, I am not sure there is a purely programmatic way to do it. The static files do have some attributes, and you can check the paths of them to do things, but I am not sure how you would easily match up a recipe with its images without front matter. But this may just be a matter of needing to be creative. For your example of images, I think you could do some liquid to match up stuff the problem would be that the time to generate would likely go way up. One idea is you could use liquid to build a json file of all your image paths, then use JS to do something on each page to check the url and see if the recipe name part matches anything in the json and if so output an img tag. I can see how technically that might be possible but sounds messy.

Thanks for the link to your recipe collection.

I finally got some time to work on this again.

I will try to summarize what I have:

This is the file list:

_config.yml
_includes
_includes/debug.html
_includes/recipe-list.html
_layouts
_layouts/default.html
_layouts/recipe.html
Makefile
_pages
_pages/_favorites.list
_pages/index.md
_pages/_template.md
recipe-images
recipe-images/Brioche.jpg
recipe-images/Carbonara.jpg
recipe-images/Marieboller-1.jpg
recipe-images/Marieboller-2.jpg
recipe-images/_missing.jpg
recipe-images/test2.jpg
recipe-images/test.jpg
recipe-images/Zuchini-con-Salvia-31.jpg
recipe-images/Zuchini-con-Salvia-321.jpg
recipe-images/Zuchini-con-Salvia-322.jpg
_recipes
_recipes/index.md
_recipes/Marieboller.md
_recipes/_template.md
_recipes/Yoghurtmarinade.md
_recipes/Zombie-farsbrød.md
_recipes/Zuchini-con-Salvia.md
_sass
_sass/main.scss

_config.yml

title: Opskriftsamlingen
host: 0.0.0.0
description: De bedste opskrifter.
#baseurl: "/opskrifter"
baseurl: 
url: "https://mydomain.dk"
production_url: "https://mydomain.dk"

markdown: kramdown
permalink: pretty

include: ['_pages', '_recipes']

exclude:
  - commit_site
  - convert_images
  - Makefile
  - opdater-dev
  - opdater-prod
  - README.md

collections:
  recipes:
    output: true
    permalink: /recipes/:path
  pages:
    output: true
    #permalink: /:path/index.html

# Front matter defaults
defaults:
  - scope:
      path: "" # an empty string here means all files in the project 
    values:
      lang: "da"
  - scope:
      path: "_recipes/*"
    values:
      layout: "recipe"
  - scope:
      path: "_recipes/*.jpg"
    values:
      image: true

keep_files: ['assets'] 

gini_magick:
  thumbnail:
    source: img/photos/original
    destination: img/photos/thumbnail
    resize: 128x128


layouts:

$ cat _layouts/default.html 
---
---
<!doctype html>
<html lang="da">
  <head>
    <!-- Required meta tags -->
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <link rel="stylesheet" href="/assets/bootstrap-5.2.0-dist/css/bootstrap.min.css">
    <title>{{ page.title }} - {{ site.data.vars.site_title }}</title>
    <link rel="stylesheet" href="/assets/css/styles.css">
    <script type="module" src="{{ '/assets/js/main.js' | prepend: site.baseurl }}"></script>
  </head>
  <body>
    <div class="container content">
      {{ content }}
    </div>
    {% include debug.html %}
  </body>
</html>
$ cat _layouts/recipe.html 
---
layout: default
---
<h1>{{ page.title }}</h1>
<div class="byline">
  {{ page.date | date: "%-d %B %Y" }}
</div>
<div class="content">
  {{ content }}
</div>
<div class="tags">
  Tags:
  {% assign tags_sorted = page.tags | sort_natural %}
  {% for tag in tags_sorted %}
  {% if forloop.last == false %}
  <a href="/tags/#tag-{{ tag }}">{{ tag }}</a>,
  {% else %}
  <a href="/tags/#tag-{{ tag }}">{{ tag }}</a>
  {% endif %}

  {% endfor %}
</div>
<h2>Billeder</h2>
<div>
{% assign images_sorted = page.images | sort_natural %}
{% for image in images_sorted %}
<img alt="{{ image }}" src="{{ site.baseurl }}/recipe-images/{{ image }}" class="recipe-image">
  {{ image }}
{% endfor %}
</div
<hr>
<p>
  <a href="/">Tilbage til oversigten</a>
</p>

includes:

 $ cat _includes/recipe-list.html 
{% for recipe in site.recipes %}
<a href="{{ recipe.url }}">{{ recipe.title }}</a>
{% endfor %}
$ cat _includes/debug.html      
<pre class="debug">
page.layout={{ page.layout }}
page.title={{ page.title }}
page.url={{ page.url }}
page.permalink={{ page.permalink }}
page.published={{ page.published }}
</pre>

Sample recipe

$ head -n 5 _recipes/Marieboller.md
---
#images: test.jpg test2.jpg
images: test.jpg
---
# Marieboller

Now, I am trying to have page.images be a list of images and then iterating through them in _layouts/recipe.html
But it seems it treats page.images as a single string and not a list. So if I have “images: test1.jpg test2.jpg”, it will output an image tag with src=“test1.jpg test2.jpg”…

The strange thing is, if I set: tags: dansk bagværk in the front matter, it will list those tags as separate tags. That is, it treats tags as a list and not a single string. Is this because tags is a special name?

tags and categories are special.

If you want a “list” that is really an array, see [SOLVED] Front matter array with multiple values I personally like the bracket method with the value in quotes.

then you have to figure out how to loop thru the list which I assume is a for loop but not sure.

Thanks.

This works and seems like a really sane way of handling this stuff.
Once again, I am impressed by Jekyll :slight_smile:

While this does seem to work well, I have one problem: I want to have a recipe list.
This list should contain links to each recipe. But it should include a thumbnail of the first image for each recipe and show a default placeholder image if no first image exists for a recipe.

Something like this works for recipes which has at least one image defined. However, not sure how to handle the case when a recipe does not have an image:

{% for recipe in site.recipes %}                                                 
<a href="{{ recipe.url }}">                                                      
  <img src="/recipe-thumbnails/{{ recipe.images[0] }}" alt="{{ recipe.title }}">                                       
</a>                                                                             
<a href="{{ recipe.url }}">{{ recipe.title }}</a>                                
{% endfor %}

This produces:

<p><a href="/recipes/Marieboller">
  <img src="/recipe-thumbnails/test.jpg" alt="Marieboller" />
</a>
<a href="/recipes/Marieboller">Marieboller</a></p>

when a recipe has an image.

And produces this when a recipe does not have an image:

<p><a href="/recipes/Zuchini-con-Salvia">
  <img src="/recipe-thumbnails/" alt="Zuchini Con Salvia" />
</a>
<a href="/recipes/Zuchini-con-Salvia">Zuchini Con Salvia</a></p>

I want it to produce something like this:

<p><a href="/recipes/Zuchini-con-Salvia">
  <img src="/recipe-thumbnails/placeholder.jpg" alt="Zuchini Con Salvia" />
</a>
<a href="/recipes/Zuchini-con-Salvia">Zuchini Con Salvia</a></p>

Nevermind. I found this solution:

<img src="/recipe-thumbnails/{{ recipe.images[0] | default: "placeholder.jpg" }}" alt="{{ recipe.title }}">