Headless bundles and content structure

My objective is to create a page /sponsors/ that lists all sponsors, sponsor1 and sponsor2, and show their titles, descriptions and logos. I want to use this information on other pages as well, such as the homepage.

I do not want to create single pages for the sponsors, so no /sponsors/sponsor1/, which is why I’ve made them headless.

This is the content structure I’ve created:

content
  sponsors
  _index.md
     sponsor1
       index.md (headless = true)
       logo.png
     sponsor2
       index.md (headless = true)
       logo.png

Is this the correct approach? I’m struggling with getting this to work. I’ve been trying to do this:

{{ $headlessbundle := .Site.GetPage "/sponsors/sponsor1" }}
{{ range ( $headlessbundle.Resources.ByType "page" ) }}
{{.Title}}
{{ end }}

which gives the title of sponsor1.

I don’t know if I’m doing this overly complicated, or just not understanding correctly. I’ve searched through the forum and read the docs. Appreciate any guidance.

1 Like

I’ve managed to get this to work how I want, but the solution doesn’t feel right. Any suggestions?

Content Folder

content
  sponsors
  _index.md
     sponsor1
       index.md (headless = true)
       sponsor1.md
       sponsor1.png
     sponsor2
       index.md (headless = true)
       sponsor2.md
       sponsor2.png

sponsors/_index.md

+++
date = "2019-01-08T18:14:52+01:00"
description = "Description"
title = "Title"
+++

sponsors1/index.md

+++
date = "2019-01-08T18:14:52+01:00"
description = "Description"
title = "Sponsor1"
headless = "true"
[[resources]]
src = "/sponsors/sponsor1/sponsor1.png"
name = "sponsor1.png"
+++

layouts/sponsors/list.html

{{$headlessbundle1 := .Site.GetPage "/sponsors/sponsor1"}}
{{range ($headlessbundle1.Resources.ByType "page")}}
{{.Title}} - {{.Description}} - {{.Content}}
{{end}}

{{range ($headlessbundle1.Resources.ByType "image")}}
<img src="{{.RelPermalink}}>
{{end}}

{{$headlessbundle2 := .Site.GetPage "/sponsors/sponsor2"}}
{{range ($headlessbundle2.Resources.ByType "page")}}
{{.Title}} - {{.Description}} - {{.Content}}
{{end}}

{{range ($headlessbundle2.Resources.ByType "image")}}
<img src="{{.RelPermalink}}">
{{end}}

If you have a lot of sponsors that’s a lot of headless bundles to configure.

The bright side through is that with this cumbersome structure you will be able to call each sponsor’s details whenever and wherever you want.

However if these are meant to go in a simple row or a table then the above approach seems like overkill.

In this case I would create just one headless bundle and enter all relevant resources along with their meta data in a long index.md then I would use a naming convention for all the logos to control their order i.e. 00-<logo-name>.png, 01-<logo-name>.png and then simply range through them as needed in the template.

1 Like

Thanks. There will only be 2-3 sponsors.

Is there a way I can use the same structure, but not have to repeat the same logic and hard code the path to each sponsor? I would use a range, but it seems you can’t range over headless bundles.

I’m looking for something like this:

{{$headlessbundle := .Site.GetPage "/sponsors/%s" (some_variable)}}

where some variable would be sponsor1, sponsor2.

Try something like this (untested)

{{$slice := slice "sponsor1" "sponsor2" }}

{{range $slice}}
  {{$headlessbundle := $.Site.GetPage (printf "/sponsors/%s" .)}}
  {{range ($headlessbundle.Resources.ByType "page")}}
    {{.Title}} - {{.Description}} - {{.Content}}
  {{end}}
  {{range ($headlessbundle.Resources.ByType "image")}}
    <img src="{{.RelPermalink}}>
  {{end}}
{{end}}
3 Likes

Thanks for helping out.

I get the following error message:

execute of template failed: template: sponsors/list.html:4:12: executing "sponsors/list.html" at <"sponsor1">: can't give argument to non-function "sponsor1"

Try changing the above to:
{{$slice := slice "sponsor1" "sponsor2" }}

Yep, as @alexandros mentioned, was missing the slice keyword.

1 Like

Thanks again. Unfortunately, I get this error message now:

execute of template failed: template: sponsors/list.html:16:30: executing "sponsors/list.html" at <.Site.GetPage>: can't evaluate field Site in type string

Not sure if this is to do with headless bundles.

I think I’ve solved it now. Need to add a $ to .Site.GetPage

It’s a context issue. I’ve updated the code snippet again.

Thanks again for helping out. You too @alexandros :pray:

As of Hugo v.53, the .Site var has a lowercase alias site that behaves the same in any context. I have simplified my code by replacing all instances of .Site , $.Site etc… with site and it works the same. Please correct me if I’m mistaken, I’d hate to spread misinformation.

1 Like

You are correct. Here’s a refactoring I did recently: Replaced $.Site and .Site with just site, and the same for .Hugo to hugo.