Inside out layouts with Hugo partials. Final part. Making it Dry.

Published on January 29, 2022

This article will build on the concepts of inside out partials pt 1 and part 2 and cover how we make changes to bookshop’s page helper in order to minimize the code we need.

Before you start: Make sure you understand our partial layout by reading

Inside out layouts with Hugo Partials. Part 1 Inside out layouts with Hugo Partials. Part 2

In our previous article we showed how to leverage bookshop’s component system to create inside out partials that can be applied to all components. Unfortunately this causes us to use a second html template in order to pass the content in. In this part we will move some of that logic to the bookshop helper file so that we no longer need an extra component folder.

This article will cover the following:

  • Setting up our helper.
  • Removing our component files.

Setting up our helper file.

Previously we had our components in three files in the bookshop component library:

/layout/layout.layout.hugo.html /paragraph/paragraph.hugo.html /paragraph/component/component.hugo.html

Our paragraph.hugo.html relied on rendering a component and passing that into the layout folder like so.

{{partial "bookshop" (slice "layout" (dict "parms" .layout "content" (partial "bookshop" (slice "paragraph/component" .))))}}

Unfortunately this creates a lot of files. But, what if every component could be passed through the layout whether or not it had a layout attached to it. Welcome to the hugo page helper. If we open it up it lives in the components/shared/hugo/page.hugo.html and has the folloiwing code by default

<div>
{{ range . }}
  {{ partial "bookshop" . }}
{{ end }}
</div>

We can see it is calling the bookshop partial similar to what we are doing up there. The only difference is this is applied to every bookshop component. Lets abuse this a little by adding our layout as the pass through.

<div>
{{ range . }}
  {{partial "bookshop" (slice "layout" (dict "parms" .layout "content" (partial "bookshop" .)))}}
{{ end }}
</div>

Now instead of just rendering what it is passed, it will render what is passed and pass it through the layout component. Amazing but what if our component doesn’t use the layout? Lets cover for this by changing our layout code and adding an else.

{{$content := .content}}
{{with .parms}}
    <div class=" {{.bg_color}} {{.text_color}} {{.padding}}  " >
    {{$content | safeHTML}}
    </div>
{{else }}
    {{$content}}
{{end}}

Fantastic now any bookshop component will get passed through the layout component and if a layout exists it will render with the layout. Otherwise we will render just the component.

Removing our component files.

Lastly we need to fix our paragraph component. Let’s copy our paragraph/component/component.hugo.html into our paragraph/paragraph.hugo.html paragraph component.

<div>{{ .paragraph }}</div>

and now we can delete our paragraph/component folder altogether since every component gets passed through layout.

Success we now have a reusable layout component that can be edited in one location, no extra folders and no need to code any external layout. And we’ve made it dry.

Hopefully you get some use out of this and it makes your life easier.