Creating dynamic blocks outside of templates

Hello everyone

I suspect the answer is that I can’t do what I’m trying to do, but I hope someone with a more detailed knowledge of Hugo can confirm that to be the case or, better, tell me how I can achieve what I want to achieve.

In short, what I’m trying to do is use a range command to take data from a number of pages and put that inside a shortcode (so I can deploy that chunk on any page).

If you’ve got time, here’s the longer explanation…

I’m an author. I’m (re)building the site for my books. My basic structure gives each series its own section with an associated template. I’ve then created other sections to render cross-sectional views (so for instance, I’ve created a bibliography section which draws data from every book document).

What I want to do is create “blocks” that can then be deployed–in the same way that shortcodes can be deployed–on any page, in any place on the page, irrespective of the underlying template. These blocks would be created by taking data from pages in a number of sections.

To give one example of a block. I offer readers a free introductory library–the books comprising the library are drawn from different series. I would like to create a block which displays the covers of the books in the library, with each cover linking to that book’s specific description page.

Another block would render my (say, three) most recent publications. It is the changing nature of content in these blocks that means that I’m not keen to simply create shortcodes (plus that would be duplicating work).

With those blocks created, I’d then like to be able to deploy block in a number of places–for instance to include my most recent books on the mail list sign up confirmation page. I also want to deploy the block with text before and after (as you can do with a shortcode).

I can create what I’m calling a block within a template. For instance, here’s the code to create a block for my introductory library:

{{ range (where .Site.Pages "Params.introductorylibrary" "true") }}
<a href="{{ .Permalink }}"><img src="/{{ .Params.coverimage}}"></a>

While the template works, I can’t then deploy the block in the manner I want (in that I can’t deploy it on any page generated by a different template). Hence, I’d like to use a shortcode…

But if I put this code into a shortcode, then I get the following error message:

ERR: template: shortcodes/test.html:3:21: executing “shortcodes/test.html” at <.Site.Pages>: Site is not a field of struct type *hugolib.ShortcodeWithPage

So…is there a way to achieve what I’m trying to do or is the best option to duplicate work and create shortcodes which have to be updated by hand each time I make a change?

Very many thanks in advance for your help.




You post long, so I answer short:

  • If you want to list pages (title, URL, params etc.), this is possible in shortcodes
  • If you want to list pages with their rendered content, this must be done in templates

I have thought a little bit about delaying the shortcode evaluation, but one will in any case be restricted by the chicken-and-egg-problem: I cannot show the page I’m part of.

Also see

Perfect! Thank you so much, @bep.