Beginner questions

Hey guys. As I read through the docs, I have some questions. I couldn’t find a chatroom so I will just post here, and maybe continue to ask questions in this thread.

  1. I couldn’t find much in the docs about themes, but I gather that they are a mirror of the top level directory structure. So if I am just making a website and I don’t need to switch themes in the future, can I use no theme, and just use the top level?

  2. Are global npm packages ever required? This page seems to suggest that everything, even all my postcss plugins, need to be installed globally. See quote:

Hugo Pipe’s PostCSS requires the postcss-cli JavaScript package to be installed in the environment ( npm install -g postcss postcss-cli ) along with any PostCSS plugin(s) used (e.g., npm install -g autoprefixer ).

Thanks

  1. What’s the difference between {{ partial partial.html . }} and {{ .Render "partial" }}? They seem interchangeable but I’m sure there’s a good reason that they both exist
  1. Are Data Templates real, or are they just partials that use data?

Data templates are not something separate, they can be partials or any other template that calls data.

.Render is a function that is only available when applied to a single piece of content within a list context.

A partial template can exist outside a list context, it is meant as a reusable component that helps keep Hugo templating DRY (don’t-repeat-yourself).

Sure. I never use themes these days. Everything goes under the top level layouts folder.

Regarding your second question perhaps someone else will answer as I do not rely on npm for the projects that I maintain.

Thanks for the help. I don’t quite understand the need for .Render + Content View Templates when we can just pass arguments to partials

No. Additionally, if you install Hugo on Linux with the snap package, globally installed npm packages will fail. As an aside, I wouldn’t use the snap package as it stands today. It has issues.

Content View templates are easier to use in some situations. Example:

content
├── employees/
│   ├── john-smith/
│   │   ├── index.md
│   │   └── portrait.jpg
│   └── tricia-rogers/
│       ├── index.md
│       └── portrait.jpg
├── products/
│   ├── product-1.md
│   └── product-2.md
└── _index.md

Let’s say we want to:

  1. Use the same template to list both employees and products
  2. Display the title, summary, and a photograph when listing employees
  3. Display the title and summary (no photograph) when listing products

layouts/_default/list.html

{{ define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content }}
  {{ range .Pages }}
    {{ .Render "summary" }}
  {{ end }}
{{ end }}

The .Render method is aware of the Content Type it is rendering. So we can structure our layout directory like this:

layouts/
├── _default/
│   ├── baseof.html
│   ├── home.html
│   ├── list.html
│   └── single.html
├── employees/
│   └── summary.html
└── products/
    └── summary.html

layouts/employees/summary.html

<h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
{{ with .Resources.GetMatch "portrait.jpg" }}
  {{ $i := .Resize "120x webp" }}
  <img src="{{ $i.RelPermalink }}" alt="{{ $i.Title }}" width="{{ $i.Width }}" height="{{ $i.Height }}">
{{ end }}
<div>{{ .Summary }}</div>

layouts/products/summary.html

<h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
<div>{{ .Summary }}</div>

You could accomplish the same thing using conditionals, but it is not as clean:

Details...
layouts/
└── _default/
    ├── baseof.html
    ├── home.html
    ├── list.html
    └── single.html

layouts/_default/list.html

{{ define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content }}
  {{ range .Pages }}
    {{ if eq .Type "employees" }}
      <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
      {{ with .Resources.GetMatch "portrait.jpg" }}
        {{ $i := .Resize "120x webp" }}
        <img src="{{ $i.RelPermalink }}" alt="{{ $i.Title }}" width="{{ $i.Width }}" height="{{ $i.Height }}">
      {{ end }}
      <div>{{ .Summary }}</div>
    {{ end }}
    {{ if eq .Type "products" }}
      <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
      <div>{{ .Summary }}</div>
    {{ end }}
  {{ end }}
{{ end }}

You could accomplish the same thing using partials, but again, it is not as clean:

Details...
layouts/
├── _default/
│   ├── baseof.html
│   ├── home.html
│   ├── list.html
│   └── single.html
└── partials/
    ├── employees/
    │   └── summary.html
    └── products/
        └── summary.html

layouts/_default/list.html

{{ define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content }}
  {{ range .Pages }}
    {{ partial (printf "%s/summary" .Type) . }}
  {{ end }}
{{ end }}

A couple of other differences between Content View templates and partials:

  1. When you call a template with .Render it receives the current context. When you call a template with partial you can pass whatever you want. Example:

    {{ partial (printf "%s/summary" .Type) (dict "page" . "myvar" 42) }}
    
  2. A partial can return a value, allowing you to create your own functions. Example:

    layouts/partials/functions/sum.html

    {{ $total := 0 }}
    {{ range . }}
      {{ $total = add $total .}}
    {{ end }}
    {{ return $total }}
    

    Then call it with:

    {{ partial "functions/sum" (slice 1 2 3 4 5) }} --> 15
    
1 Like

To clarify: you can call a template using .Render from:

  • The base template
  • List templates
  • Single page templates
  • Partial templates (“partials”)
  • Shortcode templates (“shortcodes”)
  • Content View templates

Remember that .Render is a method on .Page. So, if you’re using it in a shortcode, call it with .Page.Render.

Also, if you try to render .Content or similar items using a Content View called from a shortcode, it’s not going to work. :chicken::egg::chicken::egg::chicken::egg::chicken::egg:

1 Like

@jmooring this is great, thank you!