Trying to process images, should I revamp my whole structure?

I’m currently in the process of improving the performances of my website. It has a blog, with all the articles stored inside a blog directory, as markdown files, in two languages.

Posts’ images are stored in the static directory, and I make the connection between posts and their images thanks to variables in the front-matter.

Now I see that I can’t use Image Processing for files that are stored in the static folder. So does that mean I need to change my whole site structure ?

I currently have:

blog/post1.md
blog/post1.fr.md
blog/post2.md
blog/post2.fr.md

static/img/resource1.jpg
static/img/resource2.jpg

Should I instead do this?

blog/post1/_index.md
blog/post1/_index.fr.md
blog/post1/resource1.jpg
blog/post2/_index.md
blog/post2/_index.fr.md
blog/post2/resource2.jpg

Thanks in advance for your help :slight_smile:

You could create a headless bundle at blog/resources. Stick all of your images there and create a blog/resources/index.md that has headless=true

1 Like

It looks to be a good solution but for some reason I can’t access the bundle when I try to add resources from a content that’s in another language.

My posts are all stored in the content/blog directory, in the form of post1.md / post1.fr.md. English is the default language and it has no problem accessing the headless bundle, but I can’t seem to access it from french pages.

I have a feeling I should put each post into its separate directory. It might be a bit more strict but I’m wondering if it’s not the best thing to do.

You should be able to do something like

{{ $r := .Sites.First.GetPage "blog/resources"}}
r: {{ $r }}

You can also mount your static images into the assets dir and do something like:

{{ $img := resources.Get "images/photo.jpg" }}
{{ ($img.Fill "200x200").Permalink }}

Do the resources have to be in a folder named resources?

Before I saw your comment, I tried something “simpler”. I removed all my blog posts but one, and tried another structure. That is put it in its own sub-folder. So now I have this :

/content
|-- blog
    |-- 2020-04-27-test-post
        |-- cover.jpg
        |-- img1.jpg
        |-- img2.jpg
        |-- index.md
        |-- index.fr.md

I kinda like this because I can refer the post’s image straight in my markdown thanks to the ![]() markdown shortcut. The problem is I don’t know how to access cover.jpg which would be used in my list.html and single.html layouts.

Nope, you can name it whatever you want.


You can .GetPage your testpage, then get Resources as per usual.

hmm I don’t think I follow you there.

I have this in my list.html for instance. Note that I’m using range because I do some trickery on the $index to calculate a few CSS classes.

{{ range $index, $element := .Pages  }}
{{ $cover := $element.Resources.GetMatch "cover.jpg" }}
{{ .Scratch.Set "coverUrl" $cover.RelPermalink }}
<div class="blog-cover lazy" data-src="{{ .Scratch.Get "coverUrl" }}">
    <a href="{{ .Permalink }}"></a>
</div>
{{ end }}

But I get this error: execute of template failed: template: blog/list.html:20:53: executing "blog/list.html" at <$cover.RelPermalink>: nil pointer evaluating resource.Resource.RelPermalink

I don’t think I understand how I could use .GetPage in that context.

Do you have your repo somewhere I can clone? It’s easier to help if we are talking about the same site context.

Otherwise, I would guess based on the error that you have a page somewhere without a cover.jpg, so .GetMatch returns nil, which gives an error when you try to get .RelPermalink. If that is the cause, enclose it in a with or test whether the resource exists before trying to access it.

I do actually, you can check out this branch : https://github.com/fbnlsr/primative.net/tree/hugo-resources

The current live version of the site (without resources) is on the master branch.

Ok, so in your blog/list.html:

{{ range $index, $element := .Pages  }}
    {{ $element }}
    <br>
    {{ $cover := $element.Resources.GetMatch "cover.jpg" }}
    {{ with $cover }}
        {{ .RelPermalink }}
    {{ end }}
{{ end }}

Renders the following:

hugo server:

en:

http://localhost:1313/blog/
Page(/blog/2018-06-15-forestry-a-static-website-cms/index.md)
/blog/forestry-a-static-website-cms/cover.jpg

fr:
http://localhost:1313/fr/blog/

Page(/blog/2018-06-15-forestry-a-static-website-cms/index.fr.md)
/fr/blog/forestry-un-cms-statique/cover.jpg

hugo:

en:

public/blog/forestry-a-static-website-cms/
├── cover.jpg
...
└── index.html

fr:

public/fr/blog/forestry-un-cms-statique/
├── cover.jpg
...
└── index.html

Do you get the same results?

Yes I do.

Does that answer your question?


Going back to .GetPage, you would use that if you were to have a dedicated headless page to dump your resources into.

So in your example, if your example content bundle was renamed blog/headless/index.md and had headless:true, you would do:

with index.md headless:true
{{ $page := .Sites.First.GetPage "/blog/headless/index.md" }}

or, if you have both index.md and index.fr.md, headless:true
{{ $page := .GetPage "/blog/2018-06-15-forestry-a-static-website-cms" }}

headlesspage: {{ $page }}
<br>
{{ $cover := $page.Resources.GetMatch "cover.jpg" }}
{{ with $cover }}
    {{ .RelPermalink }}
{{ end }}

Well… no. :smile:

I still don’t understand how I can access each post’s cover in the list.html template. I’m gonna have to access them since I loop into each post to retrieve the post’s title, excerpt, etc…

The thing I’m looking for in the end is a way to use Image Processing so that I can manipulate those covers depending if we’re in the post list or in the post itself.

You can see a live version of this site here btw: https://www.primative.net/blog/

I think I’ve got it!

With this code in my list.html

{{ $cover := $element.Resources.GetMatch "cover.jpg" }}
{{ if $cover }}
  {{ $coverResized := $cover.Resize "926x q90" }}
  {{ .Scratch.Set "coverUrl" $coverResized.RelPermalink }}
{{ end }}
<div class="blog-cover lazy" data-src="{{ .Scratch.Get "coverUrl" }}">
  <a href="{{ .Permalink }}"></a>
</div>

And this in my single.html

{{ $coverImg := .Page.Resources.GetMatch "cover.jpg" }}
{{ if $coverImg }}
  {{ $resizedCover := $coverImg.Resize "2000x q90" }}
  {{ .Scratch.Set "cover" $resizedCover.RelPermalink }}
{{ end }}
{{ $cover := .Scratch.Get "cover" }}

I think I’m doing what I’ve been trying! I can fetch the cover.jpg resource in both english and french, and resize the images. It looks like it’s working! :slight_smile:

So, I don’t know if you still need the explanation:


{{ range $index, $element := .Pages  }} <-- this bit goes through all the child pages in the list
    {{ $element }} <-- one child page, ie .Pages[$index]
    <br>
    {{ $cover := $element.Resources.GetMatch "cover.jpg" }} <-- grabs the resource matching "cover.jpg"
    {{ with $cover }} <-- checks if $cover exists
        {{ .RelPermalink }} <-- only gets run if 'with' statement is true
    {{ end }}
{{ end }}

So you would modify that to do:

{{ $coverUrl := "" }}
{{ with $cover }}
  {{ $coverResized := $cover.Resize "926x q90" }}
  {{ $coverUrl = $coverResized.RelPermalink }}
{{ end }}
... do stuff with {{ $coverUrl }} here ...

A minor point:

You don’t really need to .Scratch here (unless you really want to…)

Your code above could be rewritten as:

{{ $cover := $element.Resources.GetMatch "cover.jpg" }}
{{ $coverUrl := "" }}
{{ if $cover }}
  {{ $coverResized := $cover.Resize "926x q90" }}
  {{ $coverUrl = $coverResized.RelPermalink }}
{{ end }}
<div class="blog-cover lazy" data-src="{{ $coverUrl }}">
  <a href="{{ .Permalink }}"></a>
</div>
{{ $coverImg := .Page.Resources.GetMatch "cover.jpg" }}
{{ $cover := "" }}
{{ if $coverImg }}
  {{ $resizedCover := $coverImg.Resize "2000x q90" }}
  {{ $cover = $resizedCover.RelPermalink }}
{{ end }}
$cover: {{ $cover }}
3 Likes

Thank you so much @pointyfar, you have no idea how much you’ve helped me not only resolve my problem, but also understand better how Hugo works.

I still had to use .Scratch, for some odd reason it would not let me directly use the variable.

Anyways I just deployed a new version of my site with a completely revamped architecture, and now I’m using extensively the pages resources and image processing features.

Thanks again for taking the time to answer my questions. I’d buy you a coffee if I could. :smile:

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.