Hugo Basic Concepts
Note: These are incomplete personal notes and unlikely to be generally useful
Hugo creates pages by filling in templates with content.
A template is exactly a Go html template. It can make use of other
templates, configuration (defined in config.toml
, front matter, or data
files), and Hugo-specific variables that contain information about the
organization of the site as a whole. Content is written in Markdown, with
an extention that allows the use of shortcodes. A shortcode is a template
that can be called, with parameters, from within Markdown. This template will
be fully expanded when rendered. Static files (like images, js, and css) belong
in the static/
directory. Hugo does not provide js/css build tools, but it
is easy enough to use another build tool like Gulp or Webpack where static/
is the output directory.
Content
Content consists of
markdown files in the content/
directory. Each content file typically
contains front matter where metadata specific to this content is defined.
Content files are typically created with hugo new
, which initializes the
front matter. The default URL for the content will match the path under the
content/
directory, followed by index.html
. (eg.
/posts/my-first-post/index.html
). Of course, browsers will not need the
index.html
. This can all be configured with front matter.
Three important properties of content are the section, the type, and
the layout. The section is defined by the location of the content
under the content/
directory. Sections will follow the directory hierarchy
as long as every directory below the root level contains (at the deepest
level) an _index.md
file. The easiest thing is just to use first-level
directories, which don’t require an _index.md
, and are referred to as root
sections. As a matter of convention, section names are often plural.
The type of a content file can be defined in front matter. By default, it
is the same as the root section of the file. The type is used to select the
template (see the layouts section below for more on this). As a matter of
convention, type names are often singular. So articles
would be a common
section name and article
would be a type name.
Much more to say here about _index.md
files, and including resources (like
images) on specific pages.
Archetypes
Archetypes control the
front matter that is created by hugo new
. The are based on a section (TODO:
can this also be based on a type?) and have the name archetypes/<SECTION
NAME>.md
.
Layout
Layout is written in Go’s HTML
templating format, and the files live in the layout/
directory. Two
important issues to understand are what template is used for a given piece of
content, and the names and scoping of the variables that the template has
available.
The sane default for the first issue is that the top-level path component
under content/
will look for a single.html
file in a parallel directory
under layouts/
. So, for example, content/articles/.../foo.md
will be
styled by the template in layouts/articles/single.html
by default. Much
configuration is possible here, across two different dimensions, section
and type.
Templates that should be defined for even a minimal example are the homepage template, and at least one single page template. Other useful template examples are list page templates, specific section templates, content view templates (useful generating different views of the same content, which can then be embedded in other higher-level templates), and partial and short code templates (which essentially define “template functions” that can be used elsewhere).
In order to prevent repetition of boilerplate, it is useful to use a base
template. This should live at layouts/_default/baseof.html
and look
something like this:
<!DOCTYPE html>
<html>
<head>
{{ block "head" . }}
...
{{ end }}
</head>
<body>
{{ block "nav" . }}
...
{{ end }}
{{ block "main" . }}
...
{{ end }}
{{ block "footer" . }}
...
{{ end }}
</body>
</html>
The blocks themselves can contain default values or not (don’t use literal
...
). These blocks can be defined / overwritten at whatever level of scope
makes sense in a another template. So, for example,
layouts/_default/single.html
will just look like:
{{ define main }}
<!-- Templated html goes here -->
{{ end }}
baseof
template, with only the
main
block from this file.
A subtle point is the difference between partial templates and shortcode
templates. The main difference is that partials are invoked from other
templates, and shortcodes are invoked from content. Partials accept a single
context argument, often this is .
which refers to the current context of
the caller. Shortcodes have flexible, configurable arguments. See this
discussion
for more context.