What are the Pros/Cons of adding resources to Content Folder (in branches) vs. Static Folder?

Hey all, I’m new to Hugo, and I’ve been reading through the docs about Page Bundles in the Content folder. To me, it seems like good organization to bundle my media files together in a folder with the corresponding blog post. So I like the idea.

However, there’s also the Static folder, the default location for uploading those same media files. I can link to that folder and those files from anywhere. And that confuses me. Why are there are two different ways to organize media, and what are the actual benefits and drawbacks of each? Would there be a reason to use both methods together for different situations?

I’m really looking for opinions and guidance from more experienced developers, and I’d love to hear your thoughts.

Here are some ideas I had on my own:

  1. Resources in static
  • Pros - easier to spot file duplicates, consistently accessible from any location
  • Cons - resources potentially difficult to find in connection to a post, easier to mess up typing longer links (not such bad cons)
  1. Resources in leaf branches
  • Pros - all resources easy to find relative to post location, shorter links
  • Cons - not as easy to share between posts and results in possible media duplicates

I get the feeling there are other things to consider, though. I just don’t have the experience to have thought of them. Looking forward to learning more about this! :slight_smile:

Some from me:

  • Most important is the “bundle-relative” links, I think. It means that you can just drop a folder into the content tree and it “just works”
  • The bundling is also nice when you get contributions from others (one folder = one article), creating archetype folders (see the docs site and the showcase archetype)
  • Resources are “language aware”, and there are some merging logic in play here to avoid duplication
  • Resources can be processed and transformed (Hugo Pipes, image processing …)

There are some downsides, but I suspect those will eventually go away. You can certainly reuse resources by doing ../my-bundle/myimage.png or (.GetPage "../my-bundle).Resources ... ) etc., but I agree that you often end up with some duplication.

I do expect that we not so long in the future will get:

  • Automatic de-duplication via symlinks. I don’t know exactly how that would look, but I guess it should work on both the source side and the publishing side (for web server that support it)
  • Some kind of local/remote file proxy format where myimage.png is a small placeholder text file with a hash and location info – something ala what Git LFS does. I have not investigated this too much, but I hope I don’t have to reinvent this weel, as it seems to be a common requirement. This would mean that the image/whatever could live on Amazon S3 or something, but look like a Hugo resource from the templates/markdown.
2 Likes

In Markdown files, your inline image references will use the files from /static/:

I made [a picture](/images/a-picture.jpg).

will use /static/images/a-picture.jpg.

It is a convention to use page bundle resources only from subdirectories. You might use directories further up, also. Given you had nice long holidays and you want to publish some posts about it. You already have to images organized as you like it:

images/
  - 2019-10-25 Haloween costumes/
  - 2019-10-30 Haloween preps/
  - 2019-10-31 Haloween at home/
  - 2019-10-31 Haloween dinner/
  - 2019-10-31 Haloween walk/

and you want your URLs to be /blog/haloween-2019/(costumes|preps|at-home|dinner|walk), you might consider this directory layout:

/posts/haloween-2019/index.md
/posts/haloween-2019/images (below here comes the layout from above)
/posts/haloween-2019/costumes/index.md
/posts/haloween-2019/preps/index.md
/posts/haloween-2019/at-home/index.md

Now your costumes/index.mds front matter would look like this:

---
resources:
- src: "../images/2019-10-25 Haloween costumes/DCP088.jpg"
  name: title-image.jpg
  title: "All our costumes finally finished"
  params:
    persons:
    - Peter
    - Jane
- src: "../images/2019-10-25 Haloween costumes/DCP022.jpg"
  title: "The ghost"
- src: "../images/2019-10-25 Haloween costumes/DCP001.jpg"
  title: "Ready to get started"
- src: "../images/2019-10-31 Haloween walk/DCP217.jpg"
  title: "In action"
---

Sadly you can not use markdown syntax to reference resources. You can either write native HTML:

<img src="{{ .Resources.Get('title-image.jpg').RelPermalink }}" />

Or you create a shortcode like this in a file /layouts/shortcodes/img.html:

{{ $img := $.Page.Resources.GetMatch (.Get 0) }}
<img src="{{ $img.RelPermalink }}" />
}}}

And use it like this:

{{< img "title-image.jpg" >}}

Lastly, resources can be used over hierachies (spell "Give me all title-image.* from /blog/haloween-2019/ and filtered for stuff like thumbnails:

File /layouts/shortcodes/img-thumb-gallery.html:

<section class="gallery">
    {{ range $.Page.Resources.Match (.Get 0) }}
    <a href="{{ .RelPermalink }}">
        <figure style="width: {{ $.Site.Params.imgThumbSize }}px">
            {{ $thumb := .Fill (printf "%vx%[1]v" $.Site.Params.imgThumbSize) }}
            <img src="{{ $thumb.RelPermalink }}" alt="{{ .Title }}" />
            <figcaption>{{ .Title }}</figcaption>
            <ul class="visible-persons">
            {{ range .Params.persons }}
              <li>{{ . }}</li>
            {{ end }}
            </ul>
        </figure>
    </a>
    {{ end }}
</section>

Use it like this:

{{< img-thumb-gallery "../images/**/*.jpg" >}}

This will show thumbnails of the last three images with their description below. They link to the original size image.

Also, resources can have arbitary metadata (like persons in my example).

Consider: not everything I wrote is tested :blush:

2 Likes

Yeah, I can see where that kind of modularity would be super helpful. Great benefit!

Didn’t know about that, sounds pretty cool. I guess that’s on the build side, right? I imagine there’s really no way to avoid duplication in the source if I create some on my own.

I’m not sure I totally follow this line of thought. If I have a folder that contains a single Markdown file and some resources, how is that unconventional compared to including resources in the bundle with multiple subdirectories. Maybe I’m misunderstanding this point?

Ah, quite useful! I hadn’t quite understood the setup of page resources before, but this example with your explanation has flipped on some switch in my head. Interestingly, it seems like setting up page resources only makes a noticeable difference when referencing those resources using Go scripts behind the scenes or through a shortcode written for quick resource access (as you showed). Without that system, we’d just be stuck referencing the Static folder in Markdown all the time, right?

Okay, you’ve definitely gone beyond my current range of knowledge since I haven’t really jumped into the Go side of things yet, but I’ll save this to work through it as I can. Thanks for including your example.

I do greatly appreciate your insight, gentleman. It’s great to hear from you both. :slight_smile:

1 Like

It’s on the build side, but it’s there to avoid duplication in the source, e.g.:

/content/en/my-bundle

index.md
image.png
data.json

/content/jp/my-bundle

index.md

The above is over-simplified.