Headless bundles and content structure


#1

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.


#2

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}}

#3

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.


#4

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.


#5

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}}

#6

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"


#7

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


#8

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


#9

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.


#10

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


#11

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


#12

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


#13

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.


#14

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