Use Content Adapters to get several images

How can Content adapters | Hugo be used to generate, store and show all the images below inside the content page?

[
  {
      "id": 1,
      "name": "Window Pane",
      "description": "The best window pane in town",
      "price": 99,
      "images": [
          "/images/SKUWP-window-pane.jpg",
          "/images/SKUWP2-window-pane.jpg",
          "/images/SKUWP3-window-pane.jpg"
      ],
      "category": "Windows"
  },
]

Where are these images stored?

In the assets folder (I am creating a products section for a site, and I was advised using a data file is better, rather than page bundles for scalability).

I would approach this by organizing images by SKU, eliminating the need to specify image paths in front matter. I think this would be much easier to maintain.

structure
assets/
β”œβ”€β”€ images/
β”‚   └── products/
β”‚       β”œβ”€β”€ skuwf/
β”‚       β”‚   β”œβ”€β”€ 01.jpg
β”‚       β”‚   β”œβ”€β”€ 02.jpg
β”‚       β”‚   └── featured.jpg
β”‚       └── skuwp/
β”‚           β”œβ”€β”€ 01.jpg
β”‚           β”œβ”€β”€ 02.jpg
β”‚           └── featured.jpg
└── sass/
    └── main.scss
content/
β”œβ”€β”€ products/
β”‚   β”œβ”€β”€ _content.gotmpl
β”‚   └── _index.md
└── _index.md


data/products.json
[
  {
    "sku": "skuwp",
    "name": "Window Pane",
    "description": "The best **window pane** in town.",
    "price": 99,
    "categories": [
      "Windows"
    ]
  },
  {
    "sku": "skuwf",
    "name": "Window Frame",
    "description": "The best **window frame** in town.",
    "price": 42,
    "categories": [
      "Windows"
    ]
  }
]

content/products/_content.gotmpl
{{ range site.Data.products }}
  {{ $content := dict "mediaType" "text/markdown" "value" .description }}
  {{ $params := dict "sku" .sku "categories" .categories "price" .price }}
  {{ $page := dict
    "content" $content
    "kind" "page"
    "params" $params
    "path" .name
    "title" .name
  }}
  {{ $.AddPage $page }}
{{ end }}

layouts/products/single.html
{{ define "main" }}
  <h1>{{ .Title }}</h1>

  {{ with resources.GetMatch (printf "images/%s/%s/featured.*" .Section .Params.sku) }}
    {{ with .Resize "300x" }}
      <div class="image image-featured">
        <img src="{{ .RelPermalink }}" alt="{{ $.Title }} featured image">
      </div>
    {{ end }}
  {{ end }}

  {{ range resources.Match (printf "images/%s/%s/*.*" .Section .Params.sku) }}
    {{ if not (in .Name "featured") }}
      {{ with .Resize "300x" }}
        <div class="image">
          <img src="{{ .RelPermalink }}" alt="{{ $.Title }}">
        </div>
      {{ end }}
    {{ end }}
  {{ end }}

  {{ .Content }}
{{ end }}

Notes:

  1. In your data file, use an array for your categories, even if there’s only one category.
  2. Always use lower case when naming directories and files.
  3. The non-featured images will be ordered by filename. You can name them however you’d like, but I would prefix with something like β€œ01” to control the rendering order.

Try it:

git clone --single-branch -b hugo-forum-topic-51724 https://github.com/jmooring/hugo-testing hugo-forum-topic-51724
cd hugo-forum-topic-51724
hugo server

Remember that you can include markdown files in the products directory, and they will be merged with the pages created by the content adapter to form the page collection. This could be used to temporarily add a product to the site until you have time to update the data file.

2 Likes

I don’t have enough words to thank you for this solution. I took time to study it and I was able to include it in my own design, including adding the featured image in the list page.

This ByParam | Hugo was also handy since I wanted to show the products by price in ascending order on the product page.

1 Like

A question please? When I do {{ .Params.categories }} the category name appears with angled brackets. How to go around that?

The categories field is a slice of taxonomy terms. Range through it using the GetTerms method on the Page object. See documentation for an example.

I was thinking ranging will show all categories. My bad. I am just designing using one category and a few dummy items for now.

Yeah, even though you’re only assigning a single term for now, you can accommodate future needs with a slice of terms.

1 Like

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