Inside out layouts with Hugo partials. Pt 1

Published on January 12, 2022

This article goes over how we use inside out layouts to standardize our partial components. It will go through conceptual in part 1 through our current use in part 3.

Before you start: We are using: Hugo, Tailwind, and AlpineJS for our SSG, our CSS and JS respectively. Cloudcannon is our CMS and we are leveraging it’s bookshop workflow to speed up our dev time.

To find out how this is setup please see the following articles from hugostatus.com

We also use OpenGraphImage for my OG images which you can find the setup for here: Integrating opengraphimage with Hugo

When designing reusable components or partials for a Hugo site you have to pick a path on how to manage layouts. The common options we’ve seen are to give every component or partial it’s own layout preferences or using layout start and finish partials.

/content/index.md

layout:
  bg_color_class: bg-black
  bg_width: w-full
  content_color_class: bg-white
  content_with: max-w-screen-2xl
  paragraph: Lorem ipsum doler

/layout/_default/index.html

{{partial "paragraph/paragraph.hugo.html" .}}

/partials/paragraph/paragraph.hugo.html

<div id=”layout” class=”{{.Params.bg_color}} {{ .Params.bg_width }}”>
  <div class=”{{.Params.content_color_class}} {{ .Params.content_width }}”>
    <p>{{ .Params.paragraph }}</p>
  </div >
</div>

Putting layout options in a partial certainly while seemingly organized can cause a problem when you need to adjust that layout in various different components. And as the site grows, forget about standardization.

You could also use the before and after method where the partial calls a layout_start and layout_end that would give us

/partials/layout_start.html

<div id=”layout” class=”{{.Params.bg_color}} {{.Params.bg_width}}”>
  <div class=”{{.Params.content_color_class}} {{.Params.content_width}}”>

/partials/layout_end.html

  </div >
</div>

/partials/paragraph/paragraph.hugo.html

{{partial "layout_start" .}}
  <p>{{.Params.paragraph}}</p>
{{partial "layout_end" .}}

This works and lets us keep our layout easy to edit but separating layout div HTML can easily lead to the HTML not matching up if you change one and not the other and generally I just like having self contained components.

Since neither of those are up to par we started playing with Hugo partials and have arrived on using the inside out method. This has a layout partial which we pass our post through solving the problem of separated content. It becomes even more powerful when combined with our CMS but more on that later. In this mode we have.

/partials/layout.html

<div id=”layout” class=”{{.Params.bg_color}} {{.Params.bg_width}}”>
  <div class=”{{.Params.content_color_class}} {{.Params.content_width}}”>
    <p>{{.}}</p>
  </div > 
</div>

/partials/paragraph/paragraph.hugo.html

{{ partial "layout" (partial "paragraph/component/hugo.html .) }}

/partials/paragraph/component.hugo.html

<p>{{ .Params.paragraph }}</p>

Arguably we have a simpler layout setup. It is reusable and contained in one file. The one downside is that we are using an extra partial to pass content into because of how we integrate it with our CMS, I imagine you could use an inline partial to keep it to one page. However the real power shines when we combine it with our CMS’s product bookshop so we keep it this way. Enabling schemas for the layout allows us to add and create components with only the necessary frontmatter while still keeping everything in one small area to edit. The next post will cover how we use this in our CMS.