Page Resources with ability to hotlink (i.e. utilize external src)

Greetings,

I can’t tell if what i’m trying to accomplish is a wonton abuse of Page Resources, or if it is a current limitation which could potentially be improved.

Motivation

Hotlinking media files is a constant reality on the web (e.g. YouTube videos). In addition to videos, it often makes sense to (legally) hotlink image files as well (e.g. hosting images on a service like Flickr). Hugo’s Page Resources is designed specifically for files hosted in the site’s content directory. But, being a robust solution for media handling + media metadata, the ability to employ the logic of Page Resources for media files external to the site would be helpful (i think).

Problem

A Page Resource will return empty/nil unless the src specified in the corresponding markdown file targets a file that is actually present in the content directory. It doesn’t matter what other Page Resources metadata may be set in front matter. It’s the src that makes or breaks it. So, for example, the following would return empty/nil:

Front Matter

resources:
- name: "image"
  src: ""
  title: "Title for the image"
  params:
    alt: "Description of the image"
    caption: "Caption for the image"

Template

{{ $image := .Resources.Match "**image*" }}
{{ printf "%#v" $image }}

Whereas, assuming “image.jpg” is actually located in the same directory as the markdown file, this would return a result:

Front Matter

resources:
- name: "image"
  src: "image.jpg"
  title: ""
  params:
    alt: ""
    caption: ""

Template

{{ $image := .Resources.Match "**image*" }}
{{ printf "%#v" $image }}

So it doesn’t matter about all that other metadata. As long as the src accurately targets an existing file, there will be a result. But, if the src does not accurately target an existing file—regardless of how much metadata may be set in the front matter—there will be no result.

Proposal

What if Page Resources could return a result in the absence of a src in the content directory? For example:

Front Matter

resources:
- name: "image"
  src: ""
  title: "Title for the image"
  params:
    alt: "Description of the image"
    caption: "Caption for the image"
    hotlink: "//some-other-website.com/image.jpg"

Template

{{ with .Resources.GetMatch "image" }}
  {{ if or ( .Params.hotlink ) ( .RelPermalink ) }}
    <img
    {{ with .Params.alt }} 
      alt="{{ .Params.alt }}"
    {{ end }}
    {{ if .Params.hotlink }}
      src="{{ .Params.hotlink }}"
    {{ else if .RelPermalink }}
      src="{{ .RelPermalink }}"
    {{ end }}
    >
  {{ end }}
{{ end }}

In this way, the user could hotlink to an image, but keep/utilize the metadata set in the Page-Resource-specific front matter. In my example, both a hotlink and a content-directory-located src could be specified, with the default behavior favoring the hotlink (but obviously this could be reversed). The point however, is that Page Resources is a robust solution for media files and their corresponding metadata. Getting it to work with media files outside of the site could make it that much more powerful (i think).

Of course i realize there’s a workaround to achieve a similar behavior. For example the following could be done:

Front Matter

hotlink:
  src: "//some-other-website.com/image.jpg"
  alt: "Description of the image"
  title: "Title for the image"
  caption: "Caption for the image"
resources:
- name: "image"
  src: "image.jpg"
  title: "Title for the image"
  params:
    alt: "Description of the image"
    caption: "Caption for the image"

Template

{{ if .Params.hotlink.src }}
  <img
  {{ with .Params.hotlink.alt }}
    alt="{{ .Params.hotlink.alt }}"
  {{ end }}
  src="{{ .Params.hotlink.src }}"
  >
{{ else if .Resources.GetMatch "image" }}
  {{ with.Resources.GetMatch "image" }}
    <img
    {{ with .Params.alt }}
      alt="{{ .Params.alt }}"
    {{ end }}
    src="{{ .RelPermalink }}"
    >
  {{ end }}
{{ end }}

But my question is motivated by a desire to keep all of this under the umbrella of Page Resources.

Thoughts?

1 Like

There are ethical, copyright, security and privacy implications associated with the practice of hotlinking images.

I don’t think that external images should be incorporated in Hugo Resources.

But I do not speak for anyone else here. This is my personal opinion.

3 Likes

Thanks @alexandros,

Of course i agree people hotlink in the wrong way. But in the same way that YouTube is a provider for videos, there are countless image hosting services which permit (or exist solely in order to provide) “hotlinking.” In fact i think the word “hotlinking” itself is probably too negatively loaded of a word and possibly an outdated hangover from an earlier age in the history of web development. CDNs exist to deliver javascript and CSS, YouTube exists to deliver videos, Imgur exists to deliver images, etc. Call it “remote storage” or “external media” or something else. When rightly employing such resources, there’s no foul.

Moreover, i think there’s a number of structural/organizational reasons for wanting to keep images out of one’s repository.

Appreciate the opportunity to hear yours and other thoughts about this.

Ok. But as far as I know legit services like Cloudinary that are meant for serving images in the way you describe typically serve different image sizes on their own, so one wouldn’t need to use Hugo resources when using such services.

Also YouTube does not allow hotlinking of its videos. The video URL even if you manage to find it changes after a few hours. What YouTube allows is video embedding which is different.

The problem these days is that if a feature has the potential to be abused we should expect it that down the line it will be abused.

We had a discussion a while back about fetching Open Graph tags from remote pages with Hugo and the Dev team answered with an emphatic NO because they felt that this fell under the web scraping category.

I’m sorry to put this plainly but what you propose seems unlikely to be developed.

But again the only ones who can give you a definite answer are the Devs. However please bear in mind that these are busy people and they might not reply to you here. If you don’t get a reply here, you could ask on GitHub I suppose.

Thanks again @alexandros,

Forestry.io does support ‘cloud media storage’ (as they call it) using Cloudinary. I’m not yet using Forestry with my Hugo sites, but—for my clients’ sakes—i plan to after i’ve got enough of a handle on Hugo itself.

My motivation in making this post was the potential of pushing the native possibilities of Page Resources further, without needing to rely on a third-party service like Forestry. I regret employing the word “hotlinking” in describing my proposal. The difference between embedding and hotlinking isn’t something i’ve investigated. In simplistic terms, i only know that it’s Google’s ga-jillion servers which serve embedded videos to viewers.

Granted, i can employ the same logic that Forestry describes in my template + Markdown files. I probably will. But clearly this will be a different solution than using Page Resources (and will therefor forfeit the features + flexibility thereof).

This may be all just be food for thought. But perhaps in future there would be more interest/demand for such a thing.

Yes, something like this is a great idea. I think we have discussed it (or I just have thought about it). There is “ethical dilemmas” with lots of stuff (reason why we don’t add web scraping) … people can steal pictures and host them from disc.

Primary use case for this is probably to host files (images, documents) somewhere else (still your files), but keep the metadata in your Hugo site.

1 Like

Haha @bep, this does a much better job of summarizing my point, using far fewer characters than i did. It really is just about where the metadata lives, while allowing Hugo to be more agnostic about where the file lives.

Hi,

I just wanted to open a new thread about this, than I found this.

My current use case is a blog with loads of images. I started with Hugo more than a year ago and there were no image resources. At that time I didn’t need them. My requirements back then were simple: travel friendly text-only blog repository. So no images of my travels in the Git repo means I could also use Hugo on my phone or tablet to write.
All images are hosted on an external server, server by Amazon S3 over CDN. So basically I could drop off my images to my S3 and AWS managed to serve (through Lambda) all required responsive image sizes. I never needed to resize images manually. I just applied a replace on my .Content and added my external image server.

So now I am very interested in referencing those external images as page resources. My intention differs somewhat to stephenpiscura intention: I want want Hugo to get the external image sizes for me because for AMP HTML I need to know the image sizes.

Is my wish something which can be done with Hugo in the future?

Besides I would really like to know best practices: does everyone host all images inside his Hugo Git repo, no matter the size?

Thanks!

Thanks for sharing your experience, @adulescentulus. I learned I continue to learn Hugo because I accepted a client project which required it. Since my original post—and for my client’s sake—i’ve integrated forestry.io into my stack and recently setup media handling on AWS S3—a native feature recently added to forestry.io. As such, i’m no longer using Page Resources and have very few images in my repository, save static files like logo, favicon, etc.

The next part of the puzzle will be adding something like AWS’s Serverless Image Handler—similar (or identical) to what you’ve described.

How was your experience setting up the responsive image delivery via S3—Lambda—API Gateway—CloudFront? I haven’t seen many posts here or elsewhere outlining that process. It strikes me as a little intimidating.

Sorry that I didn’t reply to you I just missed the answer notification mail. Regarding your question: If you are completely new to the serverless part it is way complicated. I basically followed the AWS blog post and extended it to my needs. As I wanted to serve the Images over https under my domain I had to use cloudfront as well. In total it took me quite some time but used it as a good training.
I always wanted to write a blog post about all of it, so far no time … But perhaps my GitHub Repo will help you. The Cloudformation including Cloudfront is there.
Hope it helps