long hugo doc

The documentation of the Hugo static site generator in one long page. NOT MAINTAINED. I can transfer this repo to you if you want to maintain it.

52
7
Python

This is the documentation of Hugo condensed into one long page. I did this to make the documentation easier to search and navigate. This page was automatically generated using a Python script using the documentation available at Hugo’s GitHub repository.

Index

about

getting-started

themes

content-management

templates

functions

variables

commands

troubleshooting

tools

hosting-and-deployment

contribute

About Hugo

Hugo is not your average static site generator.

What is Hugo

Hugo is a general-purpose website framework. Technically speaking, Hugo is a static site generator. Unlike systems that dynamically build a page with each visitor request, Hugo builds pages when you create or update your content. Since websites are viewed far more often than they are edited, Hugo is designed to provide an optimal viewing experience for your website’s end users and an ideal writing experience for website authors.

Websites built with Hugo are extremely fast and secure. Hugo sites can be hosted anywhere, including Netlify, Heroku, GoDaddy, DreamHost, GitHub Pages, Surge, Aerobatic, Firebase, Google Cloud Storage, Amazon S3, Rackspace, Azure, and CloudFront and work well with CDNs. Hugo sites run without the need for a database or dependencies on expensive runtimes like Ruby, Python, or PHP.

We think of Hugo as the ideal website creation tool with nearly instant build times, able to rebuild whenever a change is made.

How Fast is Hugo?

{{< youtube “CdiDYZ51a2o” >}}

What Does Hugo Do?

In technical terms, Hugo takes a source directory of files and templates and uses these as input to create a complete website.

Who Should Use Hugo?

Hugo is for people that prefer writing in a text editor over a browser.

Hugo is for people who want to hand code their own website without worrying about setting up complicated runtimes, dependencies and databases.

Hugo is for people building a blog, a company site, a portfolio site, documentation, a single landing page, or a website with thousands of pages.

Hugo Features

General

Organization

Content

Additional Features

See what’s coming next in the Hugo roadmap.

The Benefits of Static Site Generators

The purpose of website generators is to render content into HTML files. Most are “dynamic site generators.” That means the HTTP server—i.e., the program that sends files to the browser to be viewed—runs the generator to create a new HTML file every time an end user requests a page.

Over time, dynamic site generators were programmed to cache their HTML files to prevent unnecessary delays in delivering pages to end users. A cached page is a static version of a web page.

Hugo takes caching a step further and all HTML files are rendered on your computer. You can review the files locally before copying them to the computer hosting the HTTP server. Since the HTML files aren’t generated dynamically, we say that Hugo is a static site generator.

This has many benefits. The most noticeable is performance. HTTP servers are very good at sending files—so good, in fact, that you can effectively serve the same number of pages with a fraction of the memory and CPU needed for a dynamic site.

More on Static Site Generators

Roadmap

To track Hugo’s progress, see our GitHub Milestones.

In no particular order, here are some other features currently being worked on:

Contributions Welcome

Feel free to contribute to Hugo’s development, improve Hugo’s documentation, or open a new issue if you have an idea for a new feature.

Apache License

{{% note %}}
Hugo v0.15 and later are released under the Apache 2.0 license.
Earlier versions of Hugo were released under the Simple Public License.
{{% /note %}}

Version 2.0, January 2004

http://www.apache.org/licenses/LICENSE-2.0

Terms and Conditions for use, reproduction, and distribution

1. Definitions

“License” shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.

“Licensor” shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.

“Legal Entity” shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, “control” means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

“You” (or “Your”) shall mean an individual or Legal Entity exercising
permissions granted by this License.

“Source” form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.

“Object” form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.

“Work” shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).

“Derivative Works” shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.

“Contribution” shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
“submitted” means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as “Not a Contribution.”

“Contributor” shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.

2. Grant of Copyright License

Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.

3. Grant of Patent License

Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.

4. Redistribution

You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:

  • (a) You must give any other recipients of the Work or Derivative Works a copy of
    this License; and
  • (b) You must cause any modified files to carry prominent notices stating that You
    changed the files; and
  • © You must retain, in the Source form of any Derivative Works that You distribute,
    all copyright, patent, trademark, and attribution notices from the Source form
    of the Work, excluding those notices that do not pertain to any part of the
    Derivative Works; and
  • (d) If the Work includes a “NOTICE” text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.

You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.

5. Submission of Contributions

Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.

6. Trademarks

This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty

Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.

8. Limitation of Liability

In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability

While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work

To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets [] replaced with your own identifying information. (Don’t include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same “printed page” as the copyright notice for easier identification within third-party archives.

{{< code file=“apache-notice.txt” download=“apache-notice.txt” >}}
Copyright [yyyy] [name of copyright owner]

Licensed under the Apache License, Version 2.0 (the “License”);
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
{{< /code >}}

Get Started

If this is your first time using Hugo and you’ve already installed Hugo on your machine, we recommend the quick start.

Quick Start

{{% note %}}
This quick start uses macOS in the examples. For instructions about how to install Hugo on other operating systems, see install.

You also need Git installed to run this tutorial.
{{% /note %}}

Step 1: Install Hugo

{{% note %}}
Homebrew, a package manager for macOS, can be installed from brew.sh. See install if you are running Windows etc.
{{% /note %}}

brew install hugo

To verify your new install:

hugo version

{{< asciicast HDlKrUrbfT7yiWsbd6QoxzRTN >}}

Step 2: Create a New Site

hugo new site quickstart

The above will create a new Hugo site in a folder named quickstart.

{{< asciicast 1PH9A2fs14Dnyarx5v8OMYQer >}}

Step 3: Add a Theme

See themes.gohugo.io for a list of themes to consider. This quickstart uses the beautiful Ananke theme.

cd quickstart;\
git init;\
git submodule add https://github.com/budparr/gohugo-theme-ananke.git themes/ananke;\

# Edit your config.toml configuration file
# and add the Ananke theme.
echo 'theme = "ananke"' >> config.toml

{{< asciicast WJM2LEZQs8VRhNeuZ5NiGPp9I >}}

Step 4: Add Some Content

hugo new posts/my-first-post.md

Edit the newly created content file if you want. Now, start the Hugo server with drafts enabled:

▶ hugo server -D

Started building sites ...
Built site for language en:
1 of 1 draft rendered
0 future content
0 expired content
1 regular pages created
8 other pages created
0 non-page files copied
1 paginator pages created
0 categories created
0 tags created
total in 18 ms
Watching for changes in /Users/bep/sites/quickstart/{data,content,layouts,static,themes}
Serving pages from memory
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop

Navigate to your new site at http://localhost:1313/.

Step 5: Customize the Theme

Your new site already looks great, but you will want to tweak it a little before you release it to the public.

Site Configuration

Open up config.toml in a text editor:

baseURL = "http://example.org/"
languageCode = "en-us"
title = "My New Hugo Site"
theme = "ananke"

Replace the title above with something more personal. Also, if you already have a domain ready, set the baseURL. Note that this value is not needed when running the local development server.

{{% note %}}
Tip: Make the changes to the site configuration or any other file in your site while the Hugo server is running, and you will see the changes in the browser right away.
{{% /note %}}

For theme specific configuration options, see the theme site.

For further theme customization, see Customize a Theme.

Recapitulation

{{< asciicast pWp4uvyAkdWgQllD9RCfeBL5k >}}

Install Hugo

{{% note %}}
There is lots of talk about “Hugo being written in Go”, but you don’t need to install Go to enjoy Hugo. Just grab a precompiled binary!
{{% /note %}}

Hugo is written in Go with support for multiple platforms. The latest release can be found at Hugo Releases.

Hugo currently provides pre-built binaries for the following:

  • macOS (Darwin) for x64, i386, and ARM architectures
  • Windows
  • Linux
  • FreeBSD

Hugo may also be compiled from source wherever the Go compiler tool chain can run; e.g., on other operating systems such as DragonFly BSD, OpenBSD, Plan 9, Solaris, and others. See https://golang.org/doc/install/source for the full set of supported combinations of target operating systems and compilation architectures.

Quick Install

Binary (Cross-platform)

Download the appropriate version for your platform from Hugo Releases. Once downloaded, the binary can be run from anywhere. You don’t need to install it into a global location. This works well for shared hosts and other systems where you don’t have a privileged account.

Ideally, you should install it somewhere in your PATH for easy use. /usr/local/bin is the most probable location.

Homebrew (macOS)

If you are on macOS and using Homebrew, you can install Hugo with the following one-liner:

{{< code file=“install-with-homebrew.sh” >}}
brew install hugo
{{< /code >}}

For more detailed explanations, read the installation guides that follow for installing on macOS and Windows.

Chocolatey (Windows)

If you are on a Windows machine and use Chocolatey for package management, you can install Hugo with the following one-liner:

{{< code file=“install-with-chocolatey.ps1” >}}
choco install hugo -confirm
{{< /code >}}

Source

Prerequisite Tools

Vendored Dependencies

Hugo uses govendor to vendor dependencies, but we don’t commit the vendored packages themselves to the Hugo git repository. Therefore, a simple go get is not supported because the command is not vendor aware. You must use govendor to fetch Hugo’s dependencies.

Fetch from GitHub

{{< code file=“from-gh.sh” >}}
go get github.com/kardianos/govendor
govendor get github.com/gohugoio/hugo
go install github.com/gohugoio/hugo
{{< /code >}}

govendor get will fetch Hugo and all its dependent libraries to $GOPATH/src/github.com/gohugoio/hugo, and go install compiles everything into a final hugo (or hugo.exe) executable inside $GOPATH/bin/.

{{% note %}}
If you are a Windows user, substitute the $HOME environment variable above with %USERPROFILE%.
{{% /note %}}

macOS

Assumptions

  1. You know how to open the macOS terminal.
  2. You’re running a modern 64-bit Mac.
  3. You will use ~/Sites as the starting point for your site. (~/Sites is used for example purposes. If you are familiar enough with the command line and file system, you should have no issues following along with the instructions.)

Pick Your Method

There are three ways to install Hugo on your Mac

  1. The Homebrew brew utility
  2. Distribution (i.e., tarball)
  3. Building from Source

There is no “best” way to install Hugo on your Mac. You should use the method that works best for your use case.

Pros and Cons

There are pros and cons to each of the aforementioned methods:

  1. Homebrew. Homebrew is the simplest method and will require the least amount of work to maintain. The drawbacks aren’t severe. The default package will be for the most recent release, so it will not have bug fixes until the next release (i.e., unless you install it with the --HEAD option). Hugo brew releases may lag a few days behind because it has to be coordinated with another team. Nevertheless, brew is the recommended installation method if you want to work from a stable, widely used source. Brew works well and is easy to update.

  2. Tarball. Downloading and installing from the tarball is also easy, although it requires a few more command line skills than does Homebrew. Updates are easy as well: you just repeat the process with the new binary. This gives you the flexibility to have multiple versions on your computer. If you don’t want to use brew, then the tarball/binary is a good choice.

  3. Building from Source. Building from source is the most work. The advantage of building from source is that you don’t have to wait for a release to add features or bug fixes. The disadvantage is that you need to spend more time managing the setup, which is manageable but requires more time than the preceding two options.

{{% note %}}
Since building from source is appealing to more seasoned command line users, this guide will focus more on installing Hugo via Homebrew and Tarball.
{{% /note %}}

Install Hugo with Brew

Step 1: Install brew if you haven’t already

Go to the brew website, https://brew.sh/, and follow the directions there. The most important step is the installation from the command line:

{{< code file=“install-brew.sh” >}}
ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)”
{{< /code >}}

Step 2: Run the brew Command to Install hugo

Installing Hugo using brew is as easy as the following:

{{< code file=“install-brew.sh” >}}
brew install hugo
{{< /code >}}

If Homebrew is working properly, you should see something similar to the following:

==> Downloading https://homebrew.bintray.com/bottles/hugo-0.21.sierra.bottle.tar.gz
######################################################################### 100.0%
==> Pouring hugo-0.21.sierra.bottle.tar.gz
🍺  /usr/local/Cellar/hugo/0.21: 32 files, 17.4MB

{{% note “Installing the Latest Hugo with Brew” %}}
Replace brew install hugo with brew install hugo --HEAD if you want the absolute latest in-development version.
{{% /note %}}

brew should have updated your path to include Hugo. You can confirm by opening a new terminal window and running a few commands:

$ # show the location of the hugo executable
which hugo
/usr/local/bin/hugo

# show the installed version
ls -l $( which hugo )
lrwxr-xr-x  1 mdhender admin  30 Mar 28 22:19 /usr/local/bin/hugo -> ../Cellar/hugo/0.13_1/bin/hugo

# verify that hugo runs correctly
hugo version
Hugo Static Site Generator v0.13 BuildDate: 2015-03-09T21:34:47-05:00

Install Hugo from Tarball

Step 1: Decide on the location

When installing from the tarball, you have to decide if you’re going to install the binary in /usr/local/bin or in your home directory. There are three camps on this:

  1. Install it in /usr/local/bin so that all the users on your system have access to it. This is a good idea because it’s a fairly standard place for executables. The downside is that you may need elevated privileges to put software into that location. Also, if there are multiple users on your system, they will all run the same version. Sometimes this can be an issue if you want to try out a new release.

  2. Install it in ~/bin so that only you can execute it. This is a good idea because it’s easy to do, easy to maintain, and doesn’t require elevated privileges. The downside is that only you can run Hugo. If there are other users on your site, they have to maintain their own copies. That can lead to people running different versions. Of course, this does make it easier for you to experiment with different releases.

  3. Install it in your Sites directory. This is not a bad idea if you have only one site that you’re building. It keeps every thing in a single place. If you want to try out new releases, you can make a copy of the entire site and update the Hugo executable.

All three locations will work for you. In the interest of brevity, this guide focuses on option #2.

Step 2: Download the Tarball

  1. Open https://github.com/gohugoio/hugo/releases in your browser.

  2. Find the current release by scrolling down and looking for the green tag that reads “Latest Release.”

  3. Download the current tarball for the Mac. The name will be something like hugo_X.Y_osx-64bit.tgz, where X.YY is the release number.

  4. By default, the tarball will be saved to your ~/Downloads directory. If you choose to use a different location, you’ll need to change that in the following steps.

Step 3: Confirm your download

Verify that the tarball wasn’t corrupted during the download:

tar tvf ~/Downloads/hugo_X.Y_osx-64bit.tgz
-rwxrwxrwx  0 0      0           0 Feb 22 04:02 hugo_X.Y_osx-64bit/hugo_X.Y_osx-64bit.tgz
-rwxrwxrwx  0 0      0           0 Feb 22 03:24 hugo_X.Y_osx-64bit/README.md
-rwxrwxrwx  0 0      0           0 Jan 30 18:48 hugo_X.Y_osx-64bit/LICENSE.md

The .md files are documentation for Hugo. The other file is the executable.

Step 4: Install Into Your bin Directory

# create the directory if needed
mkdir -p ~/bin

# make it the working directory
cd ~/bin

# extract the tarball
tar -xvzf ~/Downloads/hugo_X.Y_osx-64bit.tgz
Archive:  hugo_X.Y_osx-64bit.tgz
  x ./
  x ./hugo
  x ./LICENSE.md
  x ./README.md

# verify that it runs
./hugo version
Hugo Static Site Generator v0.13 BuildDate: 2015-02-22T04:02:30-06:00

You may need to add your bin directory to your PATH variable. The which command will check for us. If it can find hugo, it will print the full path to it. Otherwise, it will not print anything.

# check if hugo is in the path
which hugo
/Users/USERNAME/bin/hugo

If hugo is not in your PATH, add it by updating your ~/.bash_profile file. First, start up an editor:

nano ~/.bash_profile

Add a line to update your PATH variable:

export PATH=$PATH:$HOME/bin

Then save the file by pressing Control-X, then Y to save the file and return to the prompt.

Close the terminal and open a new terminal to pick up the changes to your profile. Verify your success by running the which hugo command again.

You’ve successfully installed Hugo.

Build from Source on Mac

If you want to compile Hugo yourself, you’ll need to install Go (aka Golang). You can install Go directly from the Go website or via Homebrew using the following command:

brew install go

Step 1: Get the Source

If you want to compile a specific version of Hugo, go to https://github.com/gohugoio/hugo/releases and download the source code for the version of your choice. If you want to compile Hugo with all the latest changes (which might include bugs), clone the Hugo repository:

git clone https://github.com/gohugoio/hugo

{{% warning “Sometimes “Latest” = “Bugs””%}}
Cloning the Hugo repository directly means taking the good with the bad. By using the bleeding-edge version of Hugo, you make your development susceptible to the latest features, as well as the latest bugs. Your feedback is appreciated. If you find a bug in the latest release, please create an issue on GitHub.
{{% /warning %}}

Step 2: Compiling

Make the directory containing the source your working directory and then fetch Hugo’s dependencies:

mkdir -p src/github.com/gohugoio
ln -sf $(pwd) src/github.com/gohugoio/hugo

# set the build path for Go
export GOPATH=$(pwd)

go get

This will fetch the absolute latest version of the dependencies. If Hugo fails to build, it may be the result of a dependency’s author introducing a breaking change.

Once you have properly configured your directory, you can compile Hugo using the following command:

go build -o hugo main.go

Then place the hugo executable somewhere in your $PATH. You’re now ready to start using Hugo.

Windows

The following aims to be a complete guide to installing Hugo on your Windows PC.

Assumptions

  1. You will use C:\Hugo\Sites as the starting point for your new project.
  2. You will use C:\Hugo\bin to store executable files.

Set up Your Directories

You’ll need a place to store the Hugo executable, your content, and the generated Hugo website:

  1. Open Windows Explorer.
  2. Create a new folder: C:\Hugo, assuming you want Hugo on your C drive, although this can go anywhere
  3. Create a subfolder in the Hugo folder: C:\Hugo\bin
  4. Create another subfolder in Hugo: C:\Hugo\Sites

Technical Users

  1. Download the latest zipped Hugo executable from Hugo Releases.
  2. Extract all contents to your ..\Hugo\bin folder.
  3. The hugo executable will be named as hugo_hugo-version_platform_arch.exe. Rename the executable to hugo.exe for ease of use.
  4. In PowerShell or your preferred CLI, add the hugo.exe executable to your PATH by navigating to C:\Hugo\bin (or the location of your hugo.exe file) and use the command set PATH=%PATH%;C:\Hugo\bin. If the hugo command does not work after a reboot, you may have to run the command prompt as administrator.

Less-technical Users

  1. Go to the Hugo Releases page.
  2. The latest release is announced on top. Scroll to the bottom of the release announcement to see the downloads. They’re all ZIP files.
  3. Find the Windows files near the bottom (they’re in alphabetical order, so Windows is last) – download either the 32-bit or 64-bit file depending on whether you have 32-bit or 64-bit Windows. (If you don’t know, see here.)
  4. Move the ZIP file into your C:\Hugo\bin folder.
  5. Double-click on the ZIP file and extract its contents. Be sure to extract the contents into the same C:\Hugo\bin folder – Windows will do this by default unless you tell it to extract somewhere else.
  6. You should now have three new files: hugo executable (e.g. hugo_0.18_windows_amd64.exe), license.md, and readme.md. (You can delete the ZIP download now.) Rename that hugo executable (hugo_hugo-version_platform_arch.exe) to hugo.exe for ease of use.

Now you need to add Hugo to your Windows PATH settings:

For Windows 10 Users:

  • Right click on the Start button.
  • Click on System.
  • Click on Advanced System Settings on the left.
  • Click on the Environment Variables… button on the bottom.
  • In the User variables section, find the row that starts with PATH (PATH will be all caps).
  • Double-click on PATH.
  • Click the New… button.
  • Type in the folder where hugo.exe was extracted, which is C:\Hugo\bin if you went by the instructions above. The PATH entry should be the folder where Hugo lives and not the binary. Press Enter when you’re done typing.
  • Click OK at every window to exit.

{{% note “Path Editor in Windows 10”%}}
The path editor in Windows 10 was added in the large November 2015 Update. You’ll need to have that or a later update installed for the above steps to work. You can see what Windows 10 build you have by clicking on the  Start button → Settings → System → About. See here for more.)
{{% /note %}}

For Windows 7 and 8.x users:

Windows 7 and 8.1 do not include the easy path editor included in Windows 10, so non-technical users on those platforms are advised to install a free third-party path editor like Windows Environment Variables Editor or Path Editor.

Verify the Executable

Run a few commands to verify that the executable is ready to run, and then build a sample site to get started.

1. Open a Command Prompt

At the prompt, type hugo help and press the Enter key. You should see output that starts with:

hugo is the main command, used to build your Hugo site.

Hugo is a Fast and Flexible Static Site Generator
built with love by spf13 and friends in Go.

Complete documentation is available at https://gohugo.io/.

If you do, then the installation is complete. If you don’t, double-check the path that you placed the hugo.exe file in and that you typed that path correctly when you added it to your PATH variable. If you’re still not getting the output, search the Hugo discussion forum to see if others have already figured out our problem. If not, add a note—in the “Support” category—and be sure to include your command and the output.

At the prompt, change your directory to the Sites directory.

C:\Program Files> cd C:\Hugo\Sites
C:\Hugo\Sites>

2. Run the Command

Run the command to generate a new site. I’m using example.com as the name of the site.

C:\Hugo\Sites> hugo new site example.com

You should now have a directory at C:\Hugo\Sites\example.com. Change into that directory and list the contents. You should get output similar to the following:

C:\Hugo\Sites&gt;cd example.com
C:\Hugo\Sites\example.com&gt;dir
&nbsp;Directory of C:\hugo\sites\example.com
&nbsp;
04/13/2015  10:44 PM    <DIR>          .
04/13/2015  10:44 PM    <DIR>          ..
04/13/2015  10:44 PM    <DIR>          archetypes
04/13/2015  10:44 PM                83 config.toml
04/13/2015  10:44 PM    <DIR>          content
04/13/2015  10:44 PM    <DIR>          data
04/13/2015  10:44 PM    <DIR>          layouts
04/13/2015  10:44 PM    <DIR>          static
               1 File(s)             83 bytes
               7 Dir(s)   6,273,331,200 bytes free

Troubleshoot Windows Installation

@dhersam has created a nice video on common issues:

{{< youtube c8fJIRNChmU >}}

Linux

Snap Package

In any of the Linux distributions that support snaps:

snap install hugo

{{% note %}}
Hugo-as-a-snap can write only inside the user’s $HOME directory—and gvfs-mounted directories owned by the user—because of Snaps’ confinement and security model. More information is also available in this related GitHub issue.
{{% /note %}}

Debian and Ubuntu

Debian and Ubuntu provide a hugo version via apt-get:

sudo apt-get install hugo

Pros

  • Native Debian/Ubuntu package maintained by Debian Developers
  • Pre-installed bash completion script and man pages

Cons

  • Might not be the latest version, especially if you are using an older, stable version (e.g., Ubuntu 16.04 LTS). Until backports and PPA are available, you may consider installing the Hugo snap package to get the latest version of Hugo.

Arch

You can also install Hugo from the Arch user repository on Arch Linux or derivatives such as Manjaro.

Be aware that Hugo is built from source. This means that additional tools like Git and Go will be installed as well.

sudo pacman -S yaourt
yaourt -S hugo

Fedora, CentOS, and Red Hat

See the related discussion in the Hugo forums.

Upgrade Hugo

Upgrading Hugo is as easy as downloading and replacing the executable you’ve placed in your PATH.

Install Pygments (Optional)

The Hugo executable has one optional external dependency for source code highlighting (Pygments).

If you want to have source code highlighting using the highlight shortcode, you need to install the Python-based Pygments program. The procedure is outlined on the Pygments homepage.

Next Steps

Now that you’ve installed Hugo, read the Quick Start guide and explore the rest of the documentation. If you have questions, ask the Hugo community directly by visiting the Hugo Discussion Forum.

Basic Usage

The following is a description of the most common commands you will use while developing your Hugo project. See the Command Line Reference for a comprehensive view of Hugo’s CLI.

Test Installation

Once you have installed Hugo, make sure it is in your PATH. You can test that Hugo has been installed correctly via the help command:

hugo help

The output you see in your console should be similar to the following:

hugo is the main command, used to build your Hugo site.

Hugo is a Fast and Flexible Static Site Generator
built with love by spf13 and friends in Go.

Complete documentation is available at http://gohugo.io/.

Usage:
  hugo [flags]
  hugo [command]

Available Commands:
  benchmark   Benchmark Hugo by building a site a number of times.
  check       Contains some verification checks
  config      Print the site configuration
  convert     Convert your content to different formats
  env         Print Hugo version and environment info
  gen         A collection of several useful generators.
  help        Help about any command
  import      Import your site from others.
  list        Listing out various types of content
  new         Create new content for your site
  server      A high performance webserver
  undraft     Undraft changes the content's draft status from 'True' to 'False'
  version     Print the version number of Hugo

Flags:
  -b, --baseURL string             hostname (and path) to the root, e.g. http://spf13.com/
  -D, --buildDrafts                include content marked as draft
  -E, --buildExpired               include expired content
  -F, --buildFuture                include content with publishdate in the future
      --cacheDir string            filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/
      --canonifyURLs               if true, all relative URLs will be canonicalized using baseURL
      --cleanDestinationDir        remove files from destination not found in static directories
      --config string              config file (default is path/config.yaml|json|toml)
  -c, --contentDir string          filesystem path to content directory
  -d, --destination string         filesystem path to write files to
      --disable404                 do not render 404 page
      --disableKinds stringSlice   disable different kind of pages (home, RSS etc.)
      --disableRSS                 do not build RSS files
      --disableSitemap             do not build Sitemap file
      --enableGitInfo              add Git revision, date and author info to the pages
      --forceSyncStatic            copy all files when static is changed.
  -h, --help                       help for hugo
      --i18n-warnings              print missing translations
      --ignoreCache                ignores the cache directory
  -l, --layoutDir string           filesystem path to layout directory
      --log                        enable Logging
      --logFile string             log File path (if set, logging enabled automatically)
      --noChmod                    don't sync permission mode of files
      --noTimes                    don't sync modification time of files
      --pluralizeListTitles        pluralize titles in lists using inflect (default true)
      --preserveTaxonomyNames      preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu")
      --quiet                      build in quiet mode
      --renderToMemory             render to memory (only useful for benchmark testing)
  -s, --source string              filesystem path to read files relative from
      --stepAnalysis               display memory and timing of different steps of the program
  -t, --theme string               theme to use (located in /themes/THEMENAME/)
      --themesDir string           filesystem path to themes directory
      --uglyURLs                   if true, use /filename.html instead of /filename/
  -v, --verbose                    verbose output
      --verboseLog                 verbose logging
  -w, --watch                      watch filesystem for changes and recreate as needed

The hugo Command

The most common usage is probably to run hugo with your current directory being the input directory.

This generates your website to the public/ directory by default, although you can customize the output directory in your site configuration by changing the publishDir field.

The site Hugo renders into public/ is ready to be deployed to your web server:

hugo
0 draft content
0 future content
99 pages created
0 paginator pages created
16 tags created
0 groups created
in 90 ms

Draft, Future, and Expired Content

Hugo allows you to set draft, publishdate, and even expirydate in your content’s front matter. By default, Hugo will not publish:

  1. Content with a future publishdate value
  2. Content with draft: true status
  3. Content with a past expirydate value

All three of these can be overridden during both local development and deployment by adding the following flags to hugo and hugo server, respectively, or by changing the boolean values assigned to the fields of the same name (without --) in your configuration:

  1. --buildFuture
  2. --buildDrafts
  3. --buildExpired

LiveReload

Hugo comes with LiveReload built in. There are no additional packages to install. A common way to use Hugo while developing a site is to have Hugo run a server with the hugo server command and watch for changes:

hugo server
0 draft content
0 future content
99 pages created
0 paginator pages created
16 tags created
0 groups created
in 120 ms
Watching for changes in /Users/yourname/sites/yourhugosite/{data,content,layouts,static}
Serving pages from /Users/yourname/sites/yourhugosite/public
Web Server is available at http://localhost:1313/
Press Ctrl+C to stop

This will run a fully functioning web server while simultaneously watching your file system for additions, deletions, or changes within the following areas of your project organization:

  • /static/*
  • /content/*
  • /data/*
  • /i18n/*
  • /layouts/*
  • /themes/<CURRENT-THEME>/*
  • config

Whenever you make changes, Hugo will simultaneously rebuild the site and continue to serve content. As soon as the build is finished, LiveReload tells the browser to silently reload the page.

Most Hugo builds are so fast that you may not notice the change unless looking directly at the site in your browser. This means that keeping the site open on a second monitor (or another half of your current monitor) allows you to see the most up-to-date version of your website without the need to leave your text editor.

{{% note “Closing </body> Tag”%}}
Hugo injects the LiveReload <script> before the closing </body> in your templates and will therefore not work if this tag is not present…
{{% /note %}}

Disable LiveReload

LiveReload works by injecting JavaScript into the pages Hugo generates. The script creates a connection from the browser’s web socket client to the Hugo web socket server.

LiveReload is awesome for development. However, some Hugo users may use hugo server in production to instantly display updated content. The following methods make it easy to disable LiveReload:

hugo server --watch=false

Or…

hugo server --disableLiveReload

The latter flag can be omitted by adding the following key-value to your config.toml or config.yml file, respectively:

disableLiveReload = true
disableLiveReload: true

Deploy Your Website

After running hugo server for local web development, you need to do a final hugo run without the server part of the command to rebuild your site. You may then deploy your site by copying the public/ directory to your production web server.

Since Hugo generates a static website, your site can be hosted anywhere using any web server. See Hosting and Deployment for methods for hosting and automating deployments contributed by the Hugo community.

{{% warning “Generated Files are NOT Removed on Site Build” %}}
Running hugo does not remove generated files before building. This means that you should delete your public/ directory (or the publish directory you specified via flag or configuration file) before running the hugo command. If you do not remove these files, you run the risk of the wrong files (e.g., drafts or future posts) being left in the generated site.
{{% /warning %}}

Dev vs Deploy Destinations

Hugo does not remove generated files before building. An easy workaround is to use different directories for development and production.

To start a server that builds draft content (helpful for editing), you can specify a different destination; e.g., a dev/ directory:

hugo server -wDs ~/Code/hugo/docs -d dev

When the content is ready for publishing, use the default public/ dir:

hugo -s ~/Code/hugo/docs

This prevents draft content from accidentally becoming available.

Directory Structure

New Site Scaffolding

Running the hugo new site generator from the command line will create a directory structure with the following elements:

.
├── archetypes
├── config.toml
├── content
├── data
├── layouts
├── static
└── themes

Directory Structure Explained

The following is a high-level overview of each of the directories with links to each of their respective sections with in the Hugo docs.

archetypes
You can create new content files in Hugo using the hugo new command.
By default, hugo will create new content files with at least date, title (inferred from the file name), and draft = true. This saves time and promotes consistency for sites using multiple content types. You can create your own archetypes with custom preconfigured front matter fields as well.
config.toml
Every Hugo project should have a configuration file in TOML, YAML, or JSON format at the root. Many sites may need little to no configuration, but Hugo ships with a large number of configuration directives for more granular directions on how you want Hugo to build your website.
content
All content for your website will live inside this directory. Each top-level folder in Hugo is considered a content section. For example, if your site has three main sections—blog, articles, and tutorials—you will have three directories at content/blog, content/articles, and content/tutorials. Hugo uses sections to assign default content types.
data
This directory is used to store configuration files that can be
used by Hugo when generating your website. You can write these files in YAML, JSON, or TOML format. In addition to the files you add to this folder, you can also create data templates that pull from dynamic content.
layouts
Stores templates in the form of .html files that specify how views of your content will be rendered into a static website. Templates include list pages, your homepage, taxonomy templates, partials, single page templates, and more.
static
stores all the static content for your future website: images, CSS, JavaScript, etc. When Hugo builds your site, all assets inside your static directory are copied over as-is. A good example of using the static folder is for verifying site ownership on Google Search Console, where you want Hugo to copy over a complete HTML file without modifying its content.

{{% note %}}
Hugo does not currently ship with an asset pipeline (#3207). You can solicit support from the community in the Hugo forums or check out a few of the Hugo starter kits for examples of how Hugo developers are managing static assets.
{{% /note %}}

Configure Hugo

The directory structure of a Hugo website—or more precisely, the source organization of files containing the website’s content and templates—provides most of the configuration information that Hugo needs in order to generate a finished website.

Because of Hugo’s sensible defaults, many websites may not need a configuration file. Hugo is designed to recognize certain typical usage patterns.

Configuration Lookup Order

Similar to the template lookup order, Hugo has a default set of rules for searching for a configuration file in the root of your website’s source directory as a default behavior:

  1. ./config.toml
  2. ./config.yaml
  3. ./config.json

In your config file, you can direct Hugo as to how you want your website rendered, control your website’s menus, and arbitrarily define site-wide parameters specific to your project.

YAML Configuration

The following is a typical example of a YAML configuration file. Note the document opens with 3 hyphens and closes with 3 periods. The values nested under params: will populate the .Site.Params variable for use in templates:

{{< code file=“config.yml”>}}

baseURL: “https://yoursite.example.com/
title: “My Hugo Site”
footnoteReturnLinkContents: “↩”
permalinks:
post: /:year/:month/:title/
params:
Subtitle: “Hugo is Absurdly Fast!”
AuthorName: “Jon Doe”
GitHubUser: “spf13”
ListOfFoo:
- “foo1”
- “foo2”
SidebarRecentLimit: 5

{{< /code >}}

All Variables, YAML

The following is the full list of Hugo-defined variables in an example YAML file. The values provided in this example represent the default values used by Hugo.

{{< code file=“config.yml” download=“config.yml” >}}

archetypeDir: “archetypes”

hostname (and path) to the root, e.g. http://spf13.com/

baseURL: “”

include content marked as draft

buildDrafts: false

include content with publishdate in the future

buildFuture: false

include content already expired

buildExpired: false

enable this to make all relative URLs relative to content root. Note that this does not affect absolute URLs. See the “URL Management” page

relativeURLs: false
canonifyURLs: false

config file (default is path/config.yaml|json|toml)

config: “config.toml”
contentDir: “content”
dataDir: “data”
defaultExtension: “html”
defaultLayout: “post”

Missing translations will default to this content language

defaultContentLanguage: “en”

Renders the default content language in subdir, e.g. /en/. The root directory / will redirect to /en/

defaultContentLanguageInSubdir: false
disableLiveReload: false

Do not build RSS files

disableRSS: false

Do not build Sitemap file

disableSitemap: false

Enable GitInfo feature

enableGitInfo: false

Build robots.txt file

enableRobotsTXT: false

Do not render 404 page

disable404: false

Do not inject generator meta tag on homepage

disableHugoGeneratorInject: false

Allows you to disable all page types and will render nothing related to ‘kind’;

values = “page”, “home”, “section”, “taxonomy”, “taxonomyTerm”, “RSS”, “sitemap”, “robotsTXT”, “404”

disableKinds: []

Do not make the url/path to lowercase

disablePathToLower: false “”

Enable Emoji emoticons support for page content; see emoji-cheat-sheet.com

enableEmoji: false

Show a placeholder instead of the default value or an empty string if a translation is missing

enableMissingTranslationPlaceholders: false
footnoteAnchorPrefix: “”
footnoteReturnLinkContents: “”

google analytics tracking id

googleAnalytics: “”

if true, auto-detect Chinese/Japanese/Korean Languages in the content. (.Summary and .WordCount can work properly in CJKLanguage)

hasCJKLanguage: false
languageCode: “”
layoutDir: “layouts”

Enable Logging

log: false

Log File path (if set, logging enabled automatically)

logFile: “”

“toml”,“yaml”, or “json”

metaDataFormat: “toml”
newContentEditor: “”

Don’t sync permission mode of files

noChmod: false

Don’t sync modification time of files

noTimes: false

Pagination

paginate: 10
paginatePath: “page”

See “content-management/permalinks”

permalinks:

Pluralize titles in lists using inflect

pluralizeListTitles: true

Preserve special characters in taxonomy names (“Gérard Depardieu” vs “Gerard Depardieu”)

preserveTaxonomyNames: false

filesystem path to write files to

publishDir: “public”

enables syntax guessing for code fences without specified language

pygmentsCodeFencesGuessSyntax: false

color-codes for highlighting derived from this style

pygmentsStyle: “monokai”

true use pygments-css or false will color code directly

pygmentsUseClasses: false

maximum number of items in the RSS feed

rssLimit: 15

see “Section Menu for Lazy Bloggers”, /templates/menu-templates for more info

SectionPagesMenu: “”

default sitemap configuration map

sitemap:

filesystem path to read files relative from

source: “”
staticDir: “static”

display memory and timing of different steps of the program

stepAnalysis: false

theme to use (located by default in /themes/THEMENAME/)

themesDir: “themes”
theme: “”
title: “”

if true, use /filename.html instead of /filename/

uglyURLs: false

verbose output

verbose: false

verbose logging

verboseLog: false

watch filesystem for changes and recreate as needed

watch: true
taxonomies:

  • category: “categories”
  • tag: “tags”

{{< /code >}}

TOML Configuration

The following is an example of a TOML configuration file. The values under [params] will populate the .Site.Params variable for use in templates:

contentDir = "content"
layoutDir = "layouts"
publishDir = "public"
buildDrafts = false
baseURL = "https://yoursite.example.com/"
canonifyURLs = true
title = "My Hugo Site"

[taxonomies]
  category = "categories"
  tag = "tags"

[params]
  subtitle = "Hugo is Absurdly Fast!"
  author = "John Doe"

All Variables, TOML

The following is the full list of Hugo-defined variables in an example TOML file. The values provided in this example represent the default values used by Hugo.

{{< code file=“config.toml” download=“config.toml”>}}
+++
archetypeDir = “archetypes”

hostname (and path) to the root, e.g. http://spf13.com/

baseURL = “”

include content marked as draft

buildDrafts = false

include content with publishdate in the future

buildFuture = false

include content already expired

buildExpired = false

enable this to make all relative URLs relative to content root. Note that this does not affect absolute URLs.

relativeURLs = false
canonifyURLs = false

config file (default is path/config.yaml|json|toml)

config = “config.toml”
contentDir = “content”
dataDir = “data”
defaultExtension = “html”
defaultLayout = “post”

Missing translations will default to this content language

defaultContentLanguage = “en”

Renders the default content language in subdir, e.g. /en/. The root directory / will redirect to /en/

defaultContentLanguageInSubdir = false
disableLiveReload = false

Do not build RSS files

disableRSS = false

Do not build Sitemap file

disableSitemap = false

Enable GitInfo feature

enableGitInfo = false

Build robots.txt file

enableRobotsTXT = false

Do not render 404 page

disable404 = false

Do not inject generator meta tag on homepage

disableHugoGeneratorInject = false

Allows you to disable all page types and will render nothing related to ‘kind’;

values = “page”, “home”, “section”, “taxonomy”, “taxonomyTerm”, “RSS”, “sitemap”, “robotsTXT”, “404”

disableKinds = []

Do not make the url/path to lowercase

disablePathToLower = false

Enable Emoji emoticons support for page content; see emoji-cheat-sheet.com

enableEmoji = false

Show a placeholder instead of the default value or an empty string if a translation is missing

enableMissingTranslationPlaceholders = false
footnoteAnchorPrefix = “”
footnoteReturnLinkContents = “”

google analytics tracking id

googleAnalytics = “”

if true, auto-detect Chinese/Japanese/Korean Languages in the content. (.Summary and .WordCount can work properly in CJKLanguage)

hasCJKLanguage = false
languageCode = “”
layoutDir = “layouts”

Enable Logging

log = false

Log File path (if set, logging enabled automatically)

logFile =

maximum number of items in the RSS feed

rssLimit = 15

“toml”,“yaml”, or “json”

metaDataFormat = “toml”
newContentEditor = “”

Don’t sync permission mode of files

noChmod = false

Don’t sync modification time of files

noTimes = false

Pagination

paginate = 10
paginatePath = “page”

See “content-management/permalinks”

permalinks =

Pluralize titles in lists using inflect

pluralizeListTitles = true

Preserve special characters in taxonomy names (“Gérard Depardieu” vs “Gerard Depardieu”)

preserveTaxonomyNames = false

filesystem path to write files to

publishDir = “public”

enables syntax guessing for code fences without specified language

pygmentsCodeFencesGuessSyntax = false

color-codes for highlighting derived from this style

pygmentsStyle = “monokai”

true: use pygments-css or false: color-codes directly

pygmentsUseClasses = false

see “Section Menu for Lazy Bloggers”, /templates/menu-templates for more info

SectionPagesMenu =

default sitemap configuration map

sitemap =

filesystem path to read files relative from

source = “”
staticDir = “static”

display memory and timing of different steps of the program

stepAnalysis = false

theme to use (located by default in /themes/THEMENAME/)

themesDir = “themes”
theme = “”
title = “”

if true, use /filename.html instead of /filename/

uglyURLs = false

verbose output

verbose = false

verbose logging

verboseLog = false

watch filesystem for changes and recreate as needed

watch = true
taxonomies
category = “categories”
tag = “tags”
+++
{{< /code >}}

{{% note %}}
If you are developing your site on a *nix machine, here is a handy shortcut for finding a configuration option from the command line:

~/sites/yourhugosite
hugo config | grep emoji
enableemoji: true

{{% /note %}}

Environmental Variables

In addition to the 3 config options already mentioned, configuration key-values can be defined through operating system environment variables.

For example, the following command will effectively set a website’s title on Unix-like systems:

$ env HUGO_TITLE="Some Title" hugo

{{% note “Setting Environment Variables” %}}
Names must be prefixed with HUGO_ and the configuration key must be set in uppercase when setting operating system environment variables.
{{% /note %}}

Ignore Files When Rendering

The following statement inside ./config.toml will cause Hugo to ignore files ending with .foo and .boo when rendering:

ignoreFiles = [ "\\.foo$", "\\.boo$" ]

The above is a list of regular expressions. Note that the backslash (\) character is escaped in this example to keep TOML happy.

Configure Blackfriday

Blackfriday is Hugo’s built-in Markdown rendering engine.

Hugo typically configures Blackfriday with sane default values that should fit most use cases reasonably well.

However, if you have specific needs with respect to Markdown, Hugo exposes some of its Blackfriday behavior options for you to alter. The following table lists these Hugo options, paired with the corresponding flags from Blackfriday’s source code ( html.go and markdown.go).

{{< readfile file=“/content/readfiles/bfconfig.md” markdown=“true” >}}

{{% note %}}

  1. Blackfriday flags are case sensitive as of Hugo v0.15.
  2. Blackfriday flags must be grouped under the blackfriday key and can be set on both the site level and the page level. Any setting on a page will override its respective site setting.
    {{% /note %}}

{{< code file=“bf-config.toml” >}}
blackfriday
angledQuotes = true
fractions = false
plainIDAnchors = true
extensions = [“hardLineBreak”]
{{< /code >}}

{{< code file=“bf-config.yml” >}}
blackfriday:
angledQuotes: true
fractions: false
plainIDAnchors: true
extensions:
- hardLineBreak
{{< /code >}}

Configure Additional Output Formats

Hugo v0.20 introduced the ability to render your content to multiple output formats (e.g., to JSON, AMP html, or CSV). See Output Formats for information on how to add these values to your Hugo project’s configuration file.

Configuration Format Specs

yaml: http://yaml.org/spec/

Themes

Hugo provides a robust theming system that is easy to implement yet feature complete. You can view the themes created by the Hugo community on the Hugo themes website.

Hugo themes are powered by the excellent Go template library and are designed to reduce code duplication. They are easy to both customize and keep in synch with the upstream theme.

Install and Use Themes

{{% note “No Default Theme” %}}
Hugo currently doesn’t ship with a “default” theme. This decision is intentional. We leave it up to you to decide which theme best suits your Hugo project.
{{% /note %}}

Assumptions

  1. You have already installed Hugo on your development machine.
  2. You have git installed on your machine and you are familiar with basic git usage.

Install Themes

The community-contributed themes featured on themes.gohugo.io are hosted in a [centralized GitHub repository][themesrepo]. The Hugo Themes Repo at https://github.com/gohugoio/hugoThemes is really a meta repository that contains pointers to a set of contributed themes.

{{% warning “Get git First” %}}
Without Git installed on your computer, none of the following theme instructions will work. Git tutorials are beyond the scope of the Hugo docs, but GitHub and codecademy offer free, interactive courses for beginners.
{{% /warning %}}

Install All Themes

You can install all available Hugo themes by cloning the entire [Hugo Theme repository on GitHub][themesrepo] from within your working directory. Depending on your internet connection the download of all themes might take a while.

git clone --depth 1 --recursive https://github.com/gohugoio/hugoThemes.git themes

Before you use a theme, remove the .git folder in that theme’s root folder. Otherwise, this will cause problem if you deploy using Git.

Install a Single Theme

Change into the themes directory and download a theme by replacing URL_TO_THEME with the URL of the theme repository:

cd themes
git clone URL_TO_THEME

The following example shows how to use the “Hyde” theme, which has its source hosted at https://github.com/spf13/hyde:

{{< code file=“clone-theme.sh” >}}
cd themes
git clone https://github.com/spf13/hyde
{{< /code >}}

Alternatively, you can download the theme as a .zip file, unzip the theme contents, and then move the unzipped source into your themes directory.

{{% note “Read the README” %}}
Always review the README.md file that is shipped with a theme. Often, these files contain further instructions required for theme setup; e.g., copying values from an example configuration file.
{{% /note %}}

Theme Placement

Please make certain you have installed the themes you want to use in the
/themes directory. This is the default directory used by Hugo. Hugo comes with the ability to change the themes directory via the themesDir variable in your site configuration, but this is not recommended.

Use Themes

Hugo applies the decided theme first and then applies anything that is in the local directory. This allows for easier customization while retaining compatibility with the upstream version of the theme. To learn more, go to customizing themes.

Command Line

There are two different approaches to using a theme with your Hugo website: via the Hugo CLI or as part of your

To change a theme via the Hugo CLI, you can pass the -t flag when building your site:

hugo -t themename

Likely, you will want to add the theme when running the Hugo local server, especially if you are going to customize the theme:

hugo server -t themename

config File

If you’ve already decided on the theme for your site and do not want to fiddle with the command line, you can add the theme directly to your site configuration file:

theme: themename

{{% note “A Note on themename” %}}
The themename in the above examples must match the name of the specific theme directory inside /themes; i.e., the directory name (likely lowercase and urlized) rather than the name of the theme displayed in the Themes Showcase site.
{{% /note %}}

[themesrepo]: https://github.com/gohugoio/hugoThemes

Customize a Theme

The following are key concepts for Hugo site customization with themes. Hugo permits you to supplement or override any theme template or static file with files in your working directory.

{{% note %}}
When you use a theme cloned from its git repository, do not edit the theme’s files directly. Instead, theme customization in Hugo is a matter of overriding the templates made available to you in a theme. This provides the added flexibility of tweaking a theme to meet your needs while staying current with a theme’s upstream.
{{% /note %}}

Override Static Files

There are times where you want to include static assets that differ from versions of the same asset that ships with a theme.

For example, a theme may use jQuery 1.8 in the following location:

/themes/<THEME>/static/js/jquery.min.js

You want to replace the version of jQuery that ships with the theme with the newer jquery-3.1.1.js. The easiest way to do this is to replace the file with a file of the same name in the same relative path in your project’s root. Therefore, change jquery-3.1.1.js to jquery.min.js so that it is identical to the theme’s version and place the file here:

/static/js/jquery.min.js

Override Template Files

Anytime Hugo looks for a matching template, it will first check the working directory before looking in the theme directory. If you would like to modify a template, simply create that template in your local layouts directory.

The template lookup order explains the rules Hugo uses to determine which template to use for a given piece of content. Read and understand these rules carefully.

This is especially helpful when the theme creator used partial templates. These partial templates are perfect for easy injection into the theme with minimal maintenance to ensure future compatibility.

For example:

/themes/<THEME>/layouts/_default/single.html

Would be overwritten by

/layouts/_default/single.html

{{% warning %}}
This only works for templates that Hugo “knows about” (i.e., that follow its convention for folder structure and naming). If a theme imports template files in a creatively named directory, Hugo won’t know to look for the local /layouts first.
{{% /warning %}}

Override Archetypes

If the archetype that ships with the theme for a given content type (or all content types) doesn’t fit with how you are using the theme, feel free to copy it to your /archetypes directory and make modifications as you see fit.

{{% warning “Beware of layouts/_default” %}}
The _default directory is a very powerful force in Hugo, especially as it pertains to overwriting theme files. If a default file is located in the local archetypes or layout directory (i.e., archetypes/default.md or /layouts/_default/*.html, respectively), it will override the file of the same name in the corresponding theme directory (i.e., themes/<THEME>/archetypes/default.md or themes/<THEME>/layout/_defaults/*.html, respectively).

It is usually better to override specific files; i.e. rather than using layouts/_default/*.html in your working directory.
{{% /warning %}}

partials: /templates/partials/

Create a Theme

{{% warning “Use Relative Links” %}}
If you’re creating a theme with plans to share it with the community, use relative URLs since users of your theme may not publish from the root of their website. See relURL and absURL.
{{% /warning %}}

Hugo can initialize a new blank theme directory within your existing themes using the hugo new command:

hugo new theme [name]

Theme Components

A theme consists of templates and static assets such as javascript and css files. Themes can also provide archetypes, which are archetypal content types used by the hugo new command to scaffold new content files with preconfigured front matter.

{{% note “Use the Hugo Generator Tag” %}}
The .Hugo.Generator tag is included in all themes featured in the Hugo Themes Showcase. We ask that you include the generator tag in all sites and themes you create with Hugo to help the core team track Hugo’s usage and popularity.
{{% /note %}}

Layouts

Hugo is built around the concept that things should be as simple as possible.
Fundamentally, website content is displayed in two different ways, a single
piece of content and a list of content items. With Hugo, a theme layout starts
with the defaults. As additional layouts are defined, they are used for the
content type or section they apply to. This keeps layouts simple, but permits
a large amount of flexibility.

Single Content

The default single file layout is located at layouts/_default/single.html.

List of Contents

The default list file layout is located at layouts/_default/list.html.

Partial Templates

Theme creators should liberally use partial templates
throughout their theme files. Not only is a good DRY practice to include shared
code, but partials are a special template type that enables the themes end user
to be able to overwrite just a small piece of a file or inject code into the
theme from their local /layouts. These partial templates are perfect for easy
injection into the theme with minimal maintenance to ensure future
compatibility.

Static

Everything in the static directory will be copied directly into the final site
when rendered. No structure is provided here to enable complete freedom. It is
common to organize the static content into:

/css
/js
/img

The actual structure is entirely up to you, the theme creator, on how you would like to organize your files.

Archetypes

If your theme makes use of specific keys in the front matter, it is a good idea
to provide an archetype for each content type you have. Read more about archetypes.

Content Management

A static site generator needs to extend beyond front matter and a couple templates to be both scalable and manageable. Hugo was designed with not only developers in mind, but also content managers and authors.

Content Organization

{{% note %}}
This section is not updated with the new nested sections support in Hugo 0.24, see https://github.com/gohugoio/hugoDocs/issues/36
{{% /note %}}
{{% todo %}}
See above
{{% /todo %}}

Organization of Content Source

In Hugo, your content should be organized in a manner that reflects the rendered website.

While Hugo supports content nested at any level, the top levels (i.e. content/<DIRECTORIES>) are special in Hugo and are considered the content sections. Without any additional configuration, the following will just work:

.
└── content
    └── about
    |   └── _index.md  // <- http://example.com/about/
    ├── post
    |   ├── firstpost.md   // <- http://example.com/post/firstpost/
    |   ├── happy
    |   |   └── ness.md  // <- http://example.com/post/happy/ness/
    |   └── secondpost.md  // <- http://example.com/post/secondpost/
    └── quote
        ├── first.md       // <- http://example.com/quote/first/
        └── second.md      // <- http://example.com/quote/second/

Path Breakdown in Hugo

The following demonstrates the relationships between your content organization and the output URL structure for your Hugo website when it renders. These examples assume you are using pretty URLs, which is the default behavior for Hugo. The examples also assume a key-value of baseurl = "http://example.com" in your site’s configuration file.

Index Pages: _index.md

_index.md has a special role in Hugo. It allows you to add front matter and content to your list templates as of v0.18. These templates include those for section templates, taxonomy templates, taxonomy terms templates, and your homepage template. In your templates, you can grab information from _index.md using the .Site.GetPage function.

You can keep one _index.md for your homepage and one in each of your content sections, taxonomies, and taxonomy terms. The following shows typical placement of an _index.md that would contain content and front matter for a posts section list page on a Hugo website:

.         url
.       ⊢--^-⊣
.        path    slug
.       ⊢--^-⊣⊢---^---⊣
.           filepath
.       ⊢------^------⊣
content/posts/_index.md

At build, this will output to the following destination with the associated values:


                     url ("/posts/")
                    ⊢-^-⊣
       baseurl      section ("posts")
⊢--------^---------⊣⊢-^-⊣
        permalink
⊢----------^-------------⊣
http://example.com/posts/index.html

Single Pages in Sections

Single content files in each of your sections are going to be rendered as single page templates. Here is an example of a single post within posts:

                   path ("posts/my-first-hugo-post.md")
.       ⊢-----------^------------⊣
.      section        slug
.       ⊢-^-⊣⊢--------^----------⊣
content/posts/my-first-hugo-post.md

At the time Hugo builds your site, the content will be output to the following destination:


                               url ("/posts/my-first-hugo-post/")
                   ⊢------------^----------⊣
       baseurl     section     slug
⊢--------^--------⊣⊢-^--⊣⊢-------^---------⊣
                 permalink
⊢--------------------^---------------------⊣
http://example.com/posts/my-first-hugo-post/index.html

Section with Nested Directories

To continue the example, the following demonstrates destination paths for a file located at content/events/chicago/lollapalooza.md in the same site:

                    section
                    ⊢--^--⊣
                               url
                    ⊢-------------^------------⊣

      baseURL             path        slug
⊢--------^--------⊣ ⊢------^-----⊣⊢----^------⊣
                  permalink
⊢----------------------^-----------------------⊣
http://example.com/events/chicago/lollapalooza/

{{% note %}}
As of v0.20, Hugo does not recognize nested sections. While you can nest as many content directories as you’d like, any child directory of a section will still be considered the same section as that of its parents. Therefore, in the above example, {{.Section}} for lollapalooza.md is events and not chicago. See the related issue on GitHub.
{{% /note %}}

Paths Explained

The following concepts will provide more insight into the relationship between your project’s organization and the default behaviors of Hugo when building the output website.

section

A default content type is determined by a piece of content’s section. section is determined by the location within the project’s content directory. section cannot be specified or overridden in front matter.

slug

A content’s slug is either name.extension or name/. The value for slug is determined by

  • the name of the content file (e.g., lollapalooza.md) OR
  • front matter overrides

path

A content’s path is determined by the section’s path to the file. The file path

  • is based on the path to the content’s location AND
  • does not include the slug

url

The url is the relative URL for the piece of content. The url

  • is based on the content’s location within the directory structure OR
  • is defined in front matter and overrides all the above

Override Destination Paths via Front Matter

Hugo believes that you organize your content with a purpose. The same structure that works to organize your source content is used to organize the rendered site. As displayed above, the organization of the source content will be mirrored in the destination.

There are times where you may need more control over your content. In these cases, there are fields that can be specified in the front matter to determine the destination of a specific piece of content.

The following items are defined in this order for a specific reason: items explained further down in the list will override earlier items, and not all of these items can be defined in front matter:

filename

This isn’t in the front matter, but is the actual name of the file minus the extension. This will be the name of the file in the destination (e.g., content/posts/my-post.md becomes example.com/posts/my-post/).

slug

When defined in the front matter, the slug can take the place of the filename for the destination.

{{< code file=“content/posts/old-post.md” >}}

title: New Post
slug: “new-post”

{{< /code >}}

This will render to the following destination according to Hugo’s default behavior:

example.com/posts/new-post/

section

section is determined by a content’s location on disk and cannot be specified in the front matter. See sections for more information.

type

A content’s type is also determined by its location on disk but, unlike section, it can be specified in the front matter. See types. This can come in especially handy when you want a piece of content to render using a different layout. In the following example, you can create a layout at layouts/new/mylayout.html that Hugo will use to render this piece of content, even in the midst of many other posts.

{{< code file=“content/posts/my-post.md” >}}

title: My Post
type: new
layout: mylayout

{{< /code >}}

url

A complete URL can be provided. This will override all the above as it pertains to the end destination. This must be the path from the baseURL (starting with a /). url will be used exactly as it provided in the front matter and will ignore the --uglyURLs setting in your site configuration:

{{< code file=“content/posts/old-url.md” >}}

title: Old URL
url: /blog/new-url/

{{< /code >}}

Assuming your baseURL is configured to https://example.com, the addition of url to the front matter will make old-url.md render to the following destination:

https://example.com/blog/new-url/

You can see more information on how to control output paths in URL Management.

Supported Content Formats

Markdown is the main content format and comes in two flavours: The excellent Blackfriday project (name your files *.md or set markup = "markdown" in front matter) or its fork Mmark (name your files *.mmark or set markup = "mmark" in front matter), both very fast markdown engines written in Go.

For Emacs users, goorgeous provides built-in native support for Org-mode (name your files *.org or set markup = "org" in front matter)

{{% note “Deeply Nested Lists” %}}
Before you begin writing your content in markdown, Blackfriday has a known issue (#329) with handling deeply nested lists. Luckily, there is an easy workaround. Use 4-spaces (i.e., tab) rather than 2-space indentations.
{{% /note %}}

Configure BlackFriday Markdown Rendering

You can configure multiple aspects of Blackfriday as show in the following list. See the docs on Configuration for the full list of explicit directions you can give to Hugo when rendering your site.

{{< readfile file=“/content/readfiles/bfconfig.md” markdown=“true” >}}

Extend Markdown

Hugo provides some convenient methods for extending markdown.

Task Lists

Hugo supports GitHub-styled task lists (i.e., TODO lists) for the Blackfriday markdown renderer. If you do not want to use this feature, you can disable it in your configuration.

Example Task List Input

{{< code file=“content/my-to-do-list.md” >}}

  • [ ] a task list item
  • [ ] list syntax required
  • [ ] incomplete
  • [x] completed
    {{< /code >}}

Example Task List Output

The preceding markdown produces the following HTML in your rendered website:

<ul class="task-list">
    <li><input type="checkbox" disabled="" class="task-list-item"> a task list item</li>
    <li><input type="checkbox" disabled="" class="task-list-item"> list syntax required</li>
    <li><input type="checkbox" disabled="" class="task-list-item"> incomplete</li>
    <li><input type="checkbox" checked="" disabled="" class="task-list-item"> completed</li>
</ul>

Example Task List Display

The following shows how the example task list will look to the end users of your website. Note that visual styling of lists is up to you. This list has been styled according to the Hugo Docs stylesheet.

  • [ ] a task list item
  • [ ] list syntax required
  • [ ] incomplete
  • [x] completed

Emojis

To add emojis directly to content, set enableEmoji to true in your site configuration. To use emojis in templates or shortcodes, see emojify function.

For a full list of emojis, see the Emoji cheat sheet.

Shortcodes

If you write in Markdown and find yourself frequently embedding your content with raw HTML, Hugo provides built-in shortcodes functionality. This is one of the most powerful features in Hugo and allows you to create your own Markdown extensions very quickly.

See Shortcodes for usage, particularly for the built-in shortcodes that ship with Hugo, and Shortcode Templating to learn how to build your own.

Code Blocks

Hugo supports GitHub-flavored markdown’s use of triple back ticks, as well as provides a special highlight nested shortcode to render syntax highlighting via Pygments. For usage examples and a complete explanation, see the syntax highlighting documentation in developer tools.

Mmark

Mmark is a fork of BlackFriday and markdown superset that is well suited for writing IETF documentation. You can see examples of the syntax in the Mmark GitHub repository or the full syntax on Miek Gieben’s website.

Use Mmark

As Hugo ships with Mmark, using the syntax is as easy as changing the extension of your content files from .md to .mmark.

In the event that you want to only use Mmark in specific files, you can also define the Mmark syntax in your content’s front matter:

---
title: My Post
date: 2017-04-01
markup: mmark
---

{{% warning %}}
Thare are some features not available in Mmark; one example being that shortcodes are not translated when used in an included .mmark file (#3131), and EXTENSION_ABBREVIATION (#1970) and the aforementioned GFM todo lists (#2270) are not fully supported. Contributions are welcome.
{{% /warning %}}

MathJax with Hugo

MathJax is a JavaScript library that allows the display of mathematical expressions described via a LaTeX-style syntax in the HTML (or Markdown) source of a web page. As it is a pure a JavaScript library, getting it to work within Hugo is fairly straightforward, but does have some oddities that will be discussed here.

This is not an introduction into actually using MathJax to render typeset mathematics on your website. Instead, this page is a collection of tips and hints for one way to get MathJax working on a website built with Hugo.

Enable MathJax

The first step is to enable MathJax on pages that you would like to have typeset math. There are multiple ways to do this (adventurous readers can consult the Loading and Configuring section of the MathJax documentation for additional methods of including MathJax), but the easiest way is to use the secure MathJax CDN by include a <script> tag for the officially recommended secure CDN (cdn.js.com):

{{< code file=“add-mathjax-to-page.html” >}}

{{< /code >}}

One way to ensure that this code is included in all pages is to put it in one of the templates that live in the layouts/partials/ directory. For example, I have included this in the bottom of my template footer.html because I know that the footer will be included in every page of my website.

Options and Features

MathJax is a stable open-source library with many features. I encourage the interested reader to view the MathJax Documentation, specifically the sections on Basic Usage and MathJax Configuration Options.

Issues with Markdown

{{% note %}}
The following issues with Markdown assume you are using .md for content and BlackFriday for parsing. Using Mmark as your content format will obviate the need for the following workarounds.

When using Mmark with MathJax, use displayMath: [['$$','$$'], ['\\[','\\]']]. See the Mmark README.md for more information. In addition to MathJax, Mmark has been shown to work well with KaTeX. See this related blog post from a Hugo user.
{{% /note %}}

After enabling MathJax, any math entered between proper markers (see the MathJax documentation) will be processed and typeset in the web page. One issue that comes up, however, with Markdown is that the underscore character (_) is interpreted by Markdown as a way to wrap text in emph blocks while LaTeX (MathJax) interprets the underscore as a way to create a subscript. This “double speak” of the underscore can result in some unexpected and unwanted behavior.

Solution

There are multiple ways to remedy this problem. One solution is to simply escape each underscore in your math code by entering \_ instead of _. This can become quite tedious if the equations you are entering are full of subscripts.

Another option is to tell Markdown to treat the MathJax code as verbatim code and not process it. One way to do this is to wrap the math expression inside a <div> </div> block. Markdown would ignore these sections and they would get passed directly on to MathJax and processed correctly. This works great for display style mathematics, but for inline math expressions the line break induced by the <div> is not acceptable. The syntax for instructing Markdown to treat inline text as verbatim is by wrapping it in backticks (`). You might have noticed, however, that the text included in between backticks is rendered differently than standard text (on this site these are items highlighted in red). To get around this problem, we could create a new CSS entry that would apply standard styling to all inline verbatim text that includes MathJax code. Below I will show the HTML and CSS source that would accomplish this (note this solution was adapted from this blog post—all credit goes to the original author).

{{< code file=“mathjax-markdown-solution.html” >}}

{{< /code >}}

As before, this content should be included in the HTML source of each page that will be using MathJax. The next code snippet contains the CSS that is used to have verbatim MathJax blocks render with the same font style as the body of the page.

{{< code file=“mathjax-style.css” >}}
code.has-jax {
font: inherit;
font-size: 100%;
background: inherit;
border: inherit;
color: #515151;
}
{{< /code >}}

In the CSS snippet, notice the line color: #515151;. #515151 is the value assigned to the color attribute of the body class in my CSS. In order for the equations to fit in with the body of a web page, this value should be the same as the color of the body.

Usage

With this setup, everything is in place for a natural usage of MathJax on pages generated using Hugo. In order to include inline mathematics, just put LaTeX code in between `$ TeX Code $` or `\( TeX Code \)`. To include display style mathematics, just put LaTeX code in between <div>$$TeX Code$$</div>. All the math will be properly typeset and displayed within your Hugo generated web page!

Additional Formats Through External Helpers

Hugo has new concept called external helpers. It means that you can write your content using Asciidoc, reStructuredText. If you have files with associated extensions, Hugo will call external commands to generate the content. (See the Hugo source code for external helpers.)

For example, for Asciidoc files, Hugo will try to call the asciidoctor or asciidoc command. This means that you will have to install the associated tool on your machine to be able to use these formats. (See the Asciidoctor docs for installation instructions).

To use these formats, just use the standard extension and the front matter exactly as you would do with natively supported .md files.

{{% warning “Performance of External Helpers” %}}
Because additional formats are external commands generation performance will rely heavily on the performance of the external tool you are using. As this feature is still in its infancy, feedback is welcome.
{{% /warning %}}

Learn Markdown

Markdown syntax is simple enough to learn in a single sitting. The following are excellent resources to get you up and running:

Front Matter

Front matter allows you to keep metadata attached to an instance of a content type—i.e., embedded inside a content file—and is one of the many features that gives Hugo its strength.

Front Matter Formats

Hugo supports three formats for front matter, each with their own identifying tokens.

TOML
identified by opening and closing +++.
YAML
identified by opening and closing ---.
JSON
a single JSON object surrounded by ‘{’ and ‘}’, followed by a new line.

TOML Example

+++
title = "spf13-vim 3.0 release and new website"
description = "spf13-vim is a cross platform distribution of vim plugins and resources for Vim."
tags = [ ".vimrc", "plugins", "spf13-vim", "vim" ]
date = "2012-04-06"
categories = [
  "Development",
  "VIM"
]
slug = "spf13-vim-3-0-release-and-new-website"
+++

YAML Example

---
title: "spf13-vim 3.0 release and new website"
description: "spf13-vim is a cross platform distribution of vim plugins and resources for Vim."
#tags: [ ".vimrc", "plugins", "spf13-vim", "vim" ]
lastmod: 2015-12-23
date: "2012-04-06"
categories:
  - "Development"
  - "VIM"
slug: "spf13-vim-3-0-release-and-new-website"
---

JSON Example

{
    "title": "spf13-vim 3.0 release and new website",
    "description": "spf13-vim is a cross platform distribution of vim plugins and resources for Vim.",
    "tags": [ ".vimrc", "plugins", "spf13-vim", "vim" ],
    "date": "2012-04-06",
    "categories": [
        "Development",
        "VIM"
    ],
    "slug": "spf13-vim-3-0-release-and-new-website"
}

Front Matter Variables

Predefined

There are a few predefined variables that Hugo is aware of. See Page Variables for how to call many of these predefined variables in your templates.

aliases
an array of one or more aliases (e.g., old published paths of renamed content) that will be created in the output directory structure . See Aliases for details.
date
the datetime at which the content was created; note this value is auto-populated according to Hugo’s built-in archetype.
description
the description for the content.
draft
if true, the content will not be rendered unless the --buildDrafts flag is passed to the hugo command.
expiryDate
the datetime at which the content should no longer be published by Hugo; expired content will not be rendered unless the --buildExpired flag is passed to the hugo command.
isCJKLanguage
if true, Hugo will explicitly treat the content as a CJK language; both .Summary and .WordCount work properly in CJK languages.
keywords
the meta keywords for the content.
layout
the layout Hugo should select from the lookup order when rendering the content. If a type is not specified in the front matter, Hugo will look for the layout of the same name in the layout directory that corresponds with a content’s section. See “Defining a Content Type”
lastmod
the datetime at which the content was last modified.
linkTitle
used for creating links to content; if set, Hugo defaults to using the linktitle before the title. Hugo can also order lists of content by linktitle.
markup
experimental; specify "rst" for reStructuredText (requiresrst2html) or "md" (default) for Markdown.
outputs
allows you to specify output formats specific to the content. See output formats.
publishDate
if in the future, content will not be rendered unless the --buildFuture flag is passed to hugo.
slug
appears as the tail of the output URL. A value specified in front matter will override the segment of the URL based on the filename.
taxonomies
these will use the field name of the plural form of the index; see the tags and categories in the above front matter examples.
title
the title for the content.
type
the type of the content; this value will be automatically derived from the directory (i.e., the section) if not specified in front matter.
url
the full path to the content from the web root. It makes no assumptions about the path of the content file. It also ignores any language prefixes of
the multilingual feature.
weight
used for ordering your content in lists.

{{% note “Hugo’s Default URL Destinations” %}}
If neither slug nor url is present and permalinks are not configured otherwise in your site config file, Hugo will use the filename of your content to create the output URL. See Content Organization for an explanation of paths in Hugo and URL Management for ways to customize Hugo’s default behaviors.
{{% /note %}}

User-Defined

You can add fields to your front matter arbitrarily to meet your needs. These user-defined key-values are placed into a single .Params variable for use in your templates.

The following fields can be accessed via .Params.include_toc and .Params.show_comments, respectively. The Variables section provides more information on using Hugo’s page- and site-level variables in your templates.

include_toc: true
show_comments: false

These two user-defined fields can then be accessed via .Params.include_toc and .Params.show_comments, respectively. The Variables section provides more information on using Hugo’s page- and site-level variables in your templates.

Order Content Through Front Matter

You can assign content-specific weight in the front matter of your content. These values are especially useful for ordering in list views. You can use weight for ordering of content and the convention of <TAXONOMY>_weight for ordering content within a taxonomy. See Ordering and Grouping Hugo Lists to see how weight can be used to organize your content in list views.

Override Global Markdown Configuration

It’s possible to set some options for Markdown rendering in a content’s front matter as an override to the BlackFriday rendering options set in your project configuration.

Front Matter Format Specs

Shortcodes

What a Shortcode is

Hugo loves Markdown because of its simple content format, but there are times when Markdown falls short. Often, content authors are forced to add raw HTML (e.g., video <iframes>) to Markdown content. We think this contradicts the beautiful simplicity of Markdown’s syntax.

Hugo created shortcodes to circumvent these limitations.

A shortcode is a simple snippet inside a content file that Hugo will render using a predefined template. Note that shortcodes will not work in template files. If you need the type of drop-in functionality that shortcodes provide but in a template, you most likely want a partial template instead.

In addition to cleaner Markdown, shortcodes can be updated any time to reflect new classes, techniques, or standards. At the point of site generation, Hugo shortcodes will easily merge in your changes. You avoid a possibly complicated search and replace operation.

Use Shortcodes

In your content files, a shortcode can be called by calling {{%/* shortcodename parameters */%}}. Shortcode parameters are space delimited, and parameters with internal spaces can be quoted.

The first word in the shortcode declaration is always the name of the shortcode. Parameters follow the name. Depending upon how the shortcode is defined, the parameters may be named, positional, or both, although you can’t mix parameter types in a single call. The format for named parameters models that of HTML with the format name="value".

Some shortcodes use or require closing shortcodes. Again like HTML, the opening and closing shortcodes match (name only) with the closing declaration, which is prepended with a slash.

Here are two examples of paired shortcodes:

{{%/* mdshortcode */%}}Stuff to `process` in the *center*.{{%/* /mdshortcode */%}}
{{</* highlight go */>}} A bunch of code here {{</* /highlight */>}}

The examples above use two different delimiters, the difference being the % character in the first and the <> characters in the second.

Shortcodes with Markdown

The % character indicates that the shortcode’s inner content—called in the shortcode template with the .Inner variable—needs further processing by the page’s rendering processor (i.e. markdown via Blackfriday). In the following example, Blackfriday would convert **World** to <strong>World</strong>:

{{%/* myshortcode */%}}Hello **World!**{{%/* /myshortcode */%}}

Shortcodes Without Markdown

The < character indicates that the shortcode’s inner content does not need further rendering. Often shortcodes without markdown include internal HTML:

{{</* myshortcode */>}}<p>Hello <strong>World!</strong></p>{{</* /myshortcode */>}}

Nested Shortcodes

You can call shortcodes within other shortcodes by creating your own templates that leverage the .Parent variable. .Parent allows you to check the context in which the shortcode is being called. See Shortcode templates.

Use Hugo’s Built-in Shortcodes

Hugo ships with a set of predefined shortcodes that represent very common usage. These shortcodes are provided for author convenience and to keep your markdown content clean.

figure

figure is an extension of the image syntax in markdown, which does not provide a shorthand for the more semantic HTML5 <figure> element.

The figure shortcode can use the following named parameters:

  • src
  • link
  • title
  • caption
  • class
  • attr (i.e., attribution)
  • attrlink
  • alt

Example figure Input

{{< code file=“figure-input-example.md” >}}
{{</* figure src=“/media/spf13.jpg” title=“Steve Francia” */>}}
{{< /code >}}

Example figure Output

{{< output file=“figure-output-example.html” >}}

Steve Francia

{{< /output >}}

gist

Bloggers often want to include GitHub gists when writing posts. Let’s suppose we want to use the gist at the following url:

https://gist.github.com/spf13/7896402

We can embed the gist in our content via username and gist ID pulled from the URL:

{{</* gist spf13 7896402 */>}}

Example gist Input

If the gist contains several files and you want to quote just one of them, you can pass the filename (quoted) as an optional third argument:

{{< code file=“gist-input.md” >}}
{{</* gist spf13 7896402 “img.html” */>}}
{{< /code >}}

Example gist Output

{{< output file=“gist-output.html” >}}
{{< gist spf13 7896402 >}}
{{< /output >}}

Example gist Display

To demonstrate the remarkably efficiency of Hugo’s shortcode feature, we have embedded the spf13 gist example in this page. The following simulates the experience for visitors to your website. Naturally, the final display will be contingent on your stylesheets and surrounding markup.

{{< gist spf13 7896402 >}}

highlight

This shortcode will convert the source code provided into syntax-highlighted HTML. Read more on highlighting. highlight takes exactly one required language parameter and requires a closing shortcode.

Example highlight Input

{{< code file=“content/tutorials/learn-html.md” >}}
{{</* highlight html */>}}

{{ .Title }}

{{ range .Data.Pages }} {{ .Render "summary"}} {{ end }}
{{}} {{< /code >}}

Example highlight Output

The highlight shortcode example above would produce the following HTML when the site is rendered:

{{< output file=“tutorials/learn-html/index.html” >}}
<section id=“main”>
<div>
<h1 id=“title”>{{ .Title }}</h1>
{{ range .Data.Pages }}
{{ .Render “summary”}}
{{ end }}
</div>
</section>
{{< /output >}}

{{% note “More on Syntax Highlighting” %}}
To see even more options for adding syntax-highlighted code blocks to your website, see Syntax Highlighting in Developer Tools.
{{% /note %}}

instagram

If you’d like to embed a photo from Instagram, you only need the photo’s ID. You can discern an Instagram photo ID from the URL:

https://www.instagram.com/p/BWNjjyYFxVx/

Example instagram Input

{{< code file=“instagram-input.md” >}}
{{</* instagram BWNjjyYFxVx */>}}
{{< /code >}}

You also have the option to hide the caption:

{{< code file=“instagram-input-hide-caption.md” >}}
{{</* instagram BWNjjyYFxVx hidecaption */>}}
{{< /code >}}

Example instagram Output

By adding the preceding hidecaption example, the following HTML will be added to your rendered website’s markup:

{{< output file=“instagram-hide-caption-output.html” >}}
{{< instagram BWNjjyYFxVx hidecaption >}}
{{< /output >}}

Example instagram Display

Using the preceding instagram with hidecaption` example above, the following simulates the displayed experience for visitors to your website. Naturally, the final display will be contingent on your stylesheets and surrounding markup.

{{< instagram BWNjjyYFxVx hidecaption >}}

ref and relref

These shortcodes will look up the pages by their relative path (e.g., blog/post.md) or their logical name (post.md) and return the permalink (ref) or relative permalink (relref) for the found page.

ref and relref also make it possible to make fragmentary links that work for the header links generated by Hugo.

{{% note “More on Cross References” %}}
Read a more extensive description of ref and relref in the cross references documentation.
{{% /note %}}

ref and relref take exactly one required parameter of reference, quoted and in position 0.

Example ref and relref Input

[Neat]({{</* ref "blog/neat.md" */>}})
[Who]({{</* relref "about.md#who" */>}})

Example ref and relref Output

Assuming that standard Hugo pretty URLs are turned on.

<a href="/blog/neat">Neat</a>
<a href="/about/#who:c28654c202e73453784cfd2c5ab356c0">Who</a>

speakerdeck

To embed slides from Speaker Deck, click on “< /> Embed” (under Share right next to the template on Speaker Deck) and copy the URL:

<script async class="speakerdeck-embed" data-id="4e8126e72d853c0060001f97" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>

speakerdeck Example Input

Extract the value from the field data-id and pass it to the shortcode:

{{< code file=“speakerdeck-example-input.md” >}}
{{</* speakerdeck 4e8126e72d853c0060001f97 */>}}
{{< /code >}}

speakerdeck Example Output

{{< output file=“speakerdeck-example-input.md” >}}
{{< speakerdeck 4e8126e72d853c0060001f97 >}}
{{< /output >}}

speakerdeck Example Display

For the preceding speakerdeck example, the following simulates the displayed experience for visitors to your website. Naturally, the final display will be contingent on your stylesheets and surrounding markup.

{{< speakerdeck 4e8126e72d853c0060001f97 >}}

tweet

You want to include a single tweet into your blog post? Everything you need is the URL of the tweet:

https://twitter.com/spf13/status/877500564405444608

Example tweet Input

Pass the tweet’s ID from the URL as a parameter to the tweet shortcode:

{{< code file=“example-tweet-input.md” >}}
{{</* tweet 877500564405444608 */>}}
{{< /code >}}

Example tweet Output

Using the preceding tweet example, the following HTML will be added to your rendered website’s markup:

{{< output file=“example-tweet-output.html” >}}
{{< tweet 877500564405444608 >}}
{{< /output >}}

Example tweet Display

Using the preceding tweet example, the following simulates the displayed experience for visitors to your website. Naturally, the final display will be contingent on your stylesheets and surrounding markup.

{{< tweet 877500564405444608 >}}

vimeo

Adding a video from Vimeo is equivalent to the YouTube shortcode above.

https://vimeo.com/channels/staffpicks/146022717

Example vimeo Input

Extract the ID from the video’s URL and pass it to the vimeo shortcode:

{{< code file=“example-vimeo-input.md” >}}
{{</* vimeo 146022717 */>}}
{{< /code >}}

Example vimeo Output

Using the preceding vimeo example, the following HTML will be added to your rendered website’s markup:

{{< output file=“example-vimeo-output.html” >}}
{{< vimeo 146022717 >}}
{{< /output >}}

{{% tip %}}
If you want to further customize the visual styling of the YouTube or Vimeo output, add a class named parameter when calling the shortcode. The new class will be added to the <div> that wraps the <iframe> and will remove the inline styles. Note that you will need to call the id as a named parameter as well.

{{</* vimeo id="146022717" class="my-vimeo-wrapper-class" */>}}

{{% /tip %}}

Example vimeo Display

Using the preceding vimeo example, the following simulates the displayed experience for visitors to your website. Naturally, the final display will be contingent on your stylesheets and surrounding markup.

{{< vimeo 146022717 >}}

youtube

The youtube shortcode embeds a responsive video player for YouTube videos. Only the ID of the video is required, e.g.:

https://www.youtube.com/watch?v=w7Ft2ymGmfc

Example youtube Input

Copy the YouTube video ID that follows v= in the video’s URL and pass it to the youtube shortcode:

{{< code file=“example-youtube-input.md” >}}
{{</* youtube w7Ft2ymGmfc */>}}
{{< /code >}}

Furthermore, you can automatically start playback of the embedded video by setting the autoplay parameter to true. Remember that you can’t mix named an unnamed parameters, so you’ll need to assign the yet unnamed video id to the parameter id:

{{< code file=“example-youtube-input-with-autoplay.md” >}}
{{</* youtube id=“w7Ft2ymGmfc” autoplay=“true” */>}}
{{< /code >}}

Example youtube Output

Using the preceding youtube example, the following HTML will be added to your rendered website’s markup:

{{< code file=“example-youtube-output.html” >}}
{{< youtube id=“w7Ft2ymGmfc” autoplay=“true” >}}
{{< /code >}}

Example youtube Display

Using the preceding youtube example (without autoplay="true"), the following simulates the displayed experience for visitors to your website. Naturally, the final display will be contingent on your stylesheets and surrounding markup. The video is also include in the Quick Start of the Hugo documentation.

{{< youtube w7Ft2ymGmfc >}}

Create Custom Shortcodes

To learn more about creating custom shortcodes, see the shortcode template documentation.

Content Sections

{{% note %}}
This section is not updated with the new nested sections support in Hugo 0.24, see https://github.com/gohugoio/hugoDocs/issues/36
{{% /note %}}
{{% todo %}}
See above
{{% /todo %}}

Hugo believes that you organize your content with a purpose. The same structure that works to organize your source content is used to organize the rendered site (see directory structure).

Following this pattern, Hugo uses the top level of your content organization as the content section.

The following example shows a content directory structure for a website that has three sections: “authors,” “events,” and “posts”:

.
└── content
    ├── authors
    |   ├── _index.md     // <- example.com/authors/
    |   ├── john-doe.md   // <- example.com/authors/john-doe/
    |   └── jane-doe.md   // <- example.com/authors/jane-doe/
    └── events
    |   ├── _index.md     // <- example.com/events/
    |   ├── event-1.md    // <- example.com/events/event-1/
    |   ├── event-2.md    // <- example.com/events/event-2/
    |   └── event-3.md    // <- example.com/events/event-3/
    └── posts
    |   ├── _index.md     // <- example.com/posts/
    |   ├── event-1.md    // <- example.com/posts/event-1/
    |   ├── event-2.md    // <- example.com/posts/event-2/
    |   ├── event-3.md    // <- example.com/posts/event-3/
    |   ├── event-4.md    // <- example.com/posts/event-4/
    |   └── event-5.md    // <- example.com/posts/event-5/

Content Section Lists

Hugo will automatically create pages for each section root that list all of the content in that section. See the documentation on section templates for details on customizing the way these pages are rendered.

As of Hugo v0.18, section pages can also have a content file and front matter. These section content files must be placed in their corresponding section folder and named _index.md in order for Hugo to correctly render the front matter and content.

{{% warning “index.md vs _index.md” %}}
Hugo themes developed before v0.18 often used an index.md(i.e., without the leading underscore [_]) in a content section as a hack to emulate the behavior of _index.md. The hack may work…sometimes; however, the order of page rendering can be unpredictable in Hugo. What works now may fail to render appropriately as your site grows. It is strongly advised to use _index.md as content for your section index pages. Note: _index.md’s layout, as representative of a section, is a list page template and not a single page template. If you want to alter the new default behavior for _index.md, configure disableKinds accordingly in your site’s configuration.
{{% /warning %}}

Content Section vs Content Type

By default, everything created within a section will use the content type that matches the section name. For example, Hugo will assume that posts/post-1.md has a posts content type. If you are using an archetype for your posts section, Hugo will generate front matter according to what it finds in archetypes/posts.md.

Authors

Larger sites often have multiple content authors. Hugo provides standardized author profiles to organize relationships between content and content creators for sites operating under a distributed authorship model.

Author Profiles

You can create a profile containing metadata for each author on your website. These profiles have to be saved under data/_authors/. The filename of the profile will later be used as an identifier. This way Hugo can associate content with one or multiple authors. An author’s profile can be defined in the JSON, YAML, or TOML format.

Example: Author Profile

Let’s suppose Alice Allison is a blogger. A simple unique identifier would be alice. Now, we have to create a file called alice.toml in the data/_authors/ directory. The following example is the standardized template written in TOML:

{{< code file=“data/_authors/alice.toml” >}}
givenName = “Alice” # or firstName as alias
familyName = “Allison” # or lastName as alias
displayName = “Alice Allison”
thumbnail = “static/authors/alice-thumb.jpg”
image = “static/authors/alice-full.jpg”
shortBio = “My name is Alice and I’m a blogger.”
bio = “My name is Alice and I’m a blogger… some other stuff”
email = “[email protected]
weight = 10

[social]
facebook = “alice.allison”
twitter = “alice”
googleplus = “aliceallison1”
website = “www.example.com

[params]
random = “whatever you want”
{{< /code >}}

All variables are optional but it’s advised to fill all important ones (e.g. names and biography) because themes can vary in their usage.

You can store files for the thumbnail and image attributes in the static folder. Then add the path to the photos relative to static; e.g., /static/path/to/thumbnail.jpg.

weight allows you to define the order of an author in an .Authors list and can be accessed on list or via the .Site.Authors variable.

The social section contains all the links to the social network accounts of an author. Hugo is able to generate the account links for the most popular social networks automatically. This way, you only have to enter your username. You can find a list of all supported social networks here. All other variables, like website in the example above remain untouched.

The params section can contain arbitrary data much like the same-named section in the config file. What it contains is up to you.

Associate Content Through Identifiers

Earlier it was mentioned that content can be associated with an author through their corresponding identifier. In our case, blogger Alice has the identifier alice. In the front matter of a content file, you can create a list of identifiers and assign it to the authors variable. Here are examples for alice using YAML and TOML, respectively.

---
title: Why Hugo is so Awesome
date: 2016-08-22T14:27:502:00
authors: ["alice"]
---

Nothing to read here. Move along...
+++
title = Why Hugo is so Awesome
date = "2016-08-22T14:27:502:00"
authors: ["alice"]
+++

Nothing to read here. Move along...

Future authors who might work on this blog post can append their identifiers to the authors array in the front matter as well.

Work with Templates

After a successful setup it’s time to give some credit to the authors by showing them on the website. Within the templates Hugo provides a list of the author’s profiles if they are listed in the authors variable within the front matter.

The list is accessible via the .Authors template variable. Printing all authors of a the blog post is straight forward:

{{ range .Authors }}
    {{ .DisplayName }}
{{ end }}
=> Alice Allison

Even if there are co-authors you may only want to show the main author. For this case you can use the .Author template variable (note the singular form). The template variable contains the profile of the author that is first listed with his identifier in the front matter.

{{% note %}}
You can find a list of all template variables to access the profile information in Author Variables.
{{% /note %}}

Link Social Network Accounts

As aforementioned, Hugo is able to generate links to profiles of the most popular social networks. The following social networks with their corrersponding identifiers are supported: github, facebook, twitter, googleplus, pinterest, instagram, youtube and linkedin.

This is can be done with the .Social.URL function. Its only parameter is the name of the social network as they are defined in the profile (e.g. facebook, googleplus). Custom variables like website remain as they are.

Most articles feature a small section with information about the author at the end. Let’s create one containing the author’s name, a thumbnail, a (summarized) biography and links to all social networks:

{{< code file=“layouts/partials/author-info.html” download=“author-info.html” >}}
{{ with .Author }}

{{ .DisplayName }}


{{ .DisplayName }}

{{ .ShortBio }}



{{ end }}
{{< /code >}}

Who Published What?

That question can be answered with a list of all authors and another list containing all articles that they each have written. Now we have to translate this idea into templates. The taxonomy feature allows us to logically group content based on information that they have in common; e.g. a tag or a category. Well, many articles share the same author, so this should sound familiar, right?

In order to let Hugo know that we want to group content based on their author, we have to create a new taxonomy called author (the name corresponds to the variable in the front matter). Here is the snippet in a config.yaml and config.toml, respectively:

taxonomies:
    author: authors
[taxonomies]
    author = "authors"

List All Authors

In the next step we can create a template to list all authors of your website. Later, the list can be accessed at www.example.com/authors/. Create a new template in the layouts/taxonomy/ directory called authors.term.html. This template will be exclusively used for this taxonomy.

{{< code file=“layouts/taxonomy/author.term.html” download=“author.term.html” >}}

{{< /code >}}

.Data.Terms contains the identifiers of all authors and we can range over it to create a list with all author names. The $profile variable gives us access to the profile of the current author. This allows you to generate a nice info box with a thumbnail, a biography and social media links, like at the end of a blog post.

List Each Author’s Publications

Last but not least, we have to create the second list that contains all publications of an author. Each list will be shown in its own page and can be accessed at www.example.com/authors/<IDENTIFIER>. Replace <IDENTIFIER> with a valid author identifier like alice.

The layout for this page can be defined in the template layouts/taxonomy/author.html.

{{< code file=“layouts/taxonomy/author.html” download=“author.html” >}}
{{ range .Data.Pages }}

{{ .Title }}


written by {{ .Author.DisplayName }}
{{ .Summary }}
{{ end }}
{{< /code >}}

The example above generates a simple list of all posts written by a single author. Inside the loop you’ve access to the complete set of page variables. Therefore, you can add additional information about the current posts like the publishing date or the tags.

With a lot of content this list can quickly become very long. Consider to use the pagination feature. It splits the list into smaller chunks and spreads them over multiple pages.

Content Types

A content type can have a unique set of metadata (i.e., front matter) or customized template and can be created by the hugo new command via archetypes.

What is a Content Type

[Tumblr][] is a good example of a website with multiple content types. A piece of “content” could be a photo, quote, or a post, each with different sets of metadata and different visual rendering.

Assign a Content Type

Hugo assumes that your site will be organized into sections and each section represents a corresponding type. This is to reduce the amount of configuration necessary for new Hugo projects.

If you are taking advantage of this default behavior, each new piece of content you place into a section will automatically inherit the type. Therefore a new file created at content/posts/new-post.md will automatically be assigned the type posts. Alternatively, you can set the content type in a content file’s front matter in the field “type”.

Create New Content of a Specific Type

You can manually add files to your content directories, but Hugo can create and populate a new content file with preconfigured front matter via archetypes.

Define a Content Type

Creating a new content type is easy. You simply define the templates and archetype unique to your new content type, or Hugo will use defaults.

{{% note “Declaring Content Types” %}}
Remember, all of the following are optional. If you do not specifically declare content types in your front matter or develop specific layouts for content types, Hugo is smart enough to assume the content type from the file path and section. (See Content Sections for more information.)
{{% /note %}}

The following examples take you stepwise through creating a new type layout for a content file that contains the following front matter:

{{< code file=“content/events/my-first-event.md” copy=“false” >}}
+++
title = My First Event
date = “2016-06-24T19:20:04-07:00”
description = “Today is my 36th birthday. How time flies.”
type = “event”
layout = “birthday”
+++
{{< /code >}}

By default, Hugo assumes *.md under events is of the events content type. However, we have specified that this particular file at content/events/ my-first-event.md is of type event and should render using the birthday layout.

Create a Type Layout Directory

Create a directory with the name of the type in /layouts. For creating these custom layouts, type is always singular; e.g., events => event and posts => post.

For this example, you need to create layouts/event/birthday.html.

{{% note %}}
If you have multiple content files in your events directory that are of the special type and you don’t want to define the layout specifically for each piece of content, you can create a layout at layouts/special/single.html to observe the single page template lookup order.
{{% /note %}}

{{% warning %}}
With the “everything is a page” data model introduced in v0.18 (see Content Organization), you can use _index.md in content directories to add both content and front matter to list pages. However, type and layout declared in the front matter of _index.md are not currently respected at build time as of v0.19. This is a known issue (#3005).
{{% /warning %}}

Create Views

Many sites support rendering content in a few different ways; e.g., a single page view and a summary view to be used when displaying a list of section contents.

Hugo limits assumptions about how you want to display your content to an intuitive set of sane defaults and will support as many different views of a content type as your site requires. All that is required for these additional views is that a template exists in each /layouts/<TYPE> directory with the same name.

Custom Content Type Template Lookup Order

The lookup order for the content/events/my-first-event.md templates would be as follows:

  • layouts/event/birthday.html
  • layouts/event/single.html
  • layouts/events/single.html
  • layouts/_default/single.html

Create a Corresponding Archetype

We can then create a custom archetype with preconfigured front matter at event.md in the /archetypes directory; i.e. archetypes/event.md.

Read Archetypes for more information on archetype usage with hugo new.

[Tumblr]: https://www.tumblr.com/

Archetypes

{{% note %}}
This section is outdated, see https://github.com/gohugoio/hugoDocs/issues/11
{{% /note %}}
{{% todo %}}
See above
{{% /todo %}}

What are Archetypes?

Archetypes are content files in the archetypes directory of your project that contain preconfigured front matter for your website’s content types. Archetypes facilitate consistent metadata across your website content and allow content authors to quickly generate instances of a content type via the hugo new command.

{{< youtube S3Tj3UcTFz8 >}}

The hugo new generator for archetypes assumes your working directory is the content folder at the root of your project. Hugo is able to infer the appropriate archetype by assuming the content type from the content section passed to the CLI command:

hugo new <content-section>/<file-name.md>

We can use this pattern to create a new .md file in the posts section:

{{< code file=“archetype-example.sh” >}}
hugo new posts/my-first-post.md
{{< /code >}}

{{% note “Override Content Type in a New File” %}}
To override the content type Hugo infers from [content-section], add the --kind flag to the end of the hugo new command.
{{% /note %}}

Running this command in a new site that does not have default or custom archetypes will create the following file:

{{< output file=“content/posts/my-first-post.md” >}}
+++
date = “2017-02-01T19:20:04-07:00”
title = “my first post”
draft = true
+++
{{< /output >}}

{{% note %}}
In this example, if you do not already have a content/posts directory, Hugo will create both content/posts/ and content/posts/my-first-post.md for you.
{{% /note %}}

The auto-populated fields are worth examining:

  • title is generated from the new content’s filename (i.e. in this case, my-first-post becomes "my first post")
  • date and title are the variables that ship with Hugo and are therefore included in all content files created with the Hugo CLI. date is generated in RFC 3339 format by way of Go’s now() function, which returns the current time.
  • The third variable, draft = true, is not inherited by your default or custom archetypes but is included in Hugo’s automatically scaffolded default.md archetype for convenience.

Three variables per content file are often not enough for effective content management of larger websites. Luckily, Hugo provides a simple mechanism for extending the number of variables through custom archetypes, as well as default archetypes to keep content creation DRY.

Lookup Order for Archetypes

Similar to the lookup order for templates in your layouts directory, Hugo looks for a section- or type-specific archetype, then a default archetype, and finally an internal archetype that ships with Hugo. For example, Hugo will look for an archetype for content/posts/my-first-post.md in the following order:

  1. archetypes/posts.md
  2. archetypes/default.md
  3. themes/<THEME>/archetypes/posts.md
  4. themes/<THEME>/archetypes/default.md (Auto-generated with hugo new site)

{{% note “Using a Theme Archetype” %}}
If you wish to use archetypes that ship with a theme, the theme field must be specified in your configuration file.
{{% /note %}}

Choose Your Archetype’s Front Matter Format

By default, hugo new content files include front matter in the TOML format regardless of the format used in archetypes/*.md.

You can specify a different default format in your site configuration file file using the metaDataFormat directive. Possible values are toml, yaml, and json.

Default Archetypes

Default archetypes are convenient if your content’s front matter stays consistent across multiple content sections.

Create the Default Archetype

When you create a new Hugo project using hugo new site, you’ll notice that Hugo has already scaffolded a file at archetypes/default.md.

The following examples are from a site that’s using tags and categories as taxonomies. If we assume that all content files will require these two key-values, we can create a default.md archetype that extends Hugo’s base archetype. In this example, we are including “golang” and “hugo” as tags and “web development” as a category.

{{< code file=“archetypes/default.md” >}}
+++
tags = [“golang”, “hugo”]
categories = [“web development”]
+++
{{< /code >}}

{{% warning “EOL Characters in Text Editors”%}}
If you get an EOF error when using hugo new, add a carriage return after the closing +++ or --- for your TOML or YAML front matter, respectively. (See the troubleshooting article on EOF errors for more information.)
{{% /warning %}}

Use the Default Archetype

With an archetypes/default.md in place, we can use the CLI to create a new post in the posts content section:

{{< code file=“new-post-from-default.sh” >}}
$ hugo new posts/my-new-post.md
{{< /code >}}

Hugo then creates a new markdown file with the following front matter:

{{< output file=“content/posts/my-new-post.md” >}}
+++
categories = [“web development”]
date = “2017-02-01T19:20:04-07:00”
tags = [“golang”, “hugo”]
title = “my new post”
+++
{{< /output >}}

We see that the title and date key-values have been added in addition to the tags and categories key-values from archetypes/default.md.

{{% note “Ordering of Front Matter” %}}
You may notice that content files created with hugo new do not respect the order of the key-values specified in your archetype files. This is a known issue.
{{% /note %}}

Custom Archetypes

Suppose your site’s posts section requires more sophisticated front matter than what has been specified in archetypes/default.md. You can create a custom archetype for your posts at archetypes/posts.md that includes the full set of front matter to be added to the two default archetypes fields.

Create a Custom Archetype

{{< code file=“archetypes/posts.md”>}}
+++
description = “”
tags = “”
categories = “”
+++
{{< /code >}}

Use a Custom Archetype

With an archetypes/posts.md in place, you can use the Hugo CLI to create a new post with your preconfigured front matter in the posts content section:

{{< code file=“new-post-from-custom.sh” >}}
$ hugo new posts/post-from-custom.md
{{< /code >}}

This time, Hugo recognizes our custom archetypes/posts.md archetype and uses it instead of archetypes/default.md. The generated file will now include the full list of front matter parameters, as well as the base archetype’s title and date:

{{< output file=“content/posts/post-from-custom-archetype.md” >}}
+++
categories = “”
date = 2017-02-13T17:24:43-08:00
description = “”
tags = “”
title = “post from custom archetype”
+++
{{< /output >}}

Hugo Docs Custom Archetype

As an example of archetypes in practice, the following is the functions archetype from the Hugo docs:

{{< code file=“archetypes/functions.md” >}}
{{< readfile file=“/themes/gohugoioTheme/archetypes/functions.md” >}}
{{< /code >}}

{{% note %}}
The preceding archetype is kept up to date with every Hugo build by using Hugo’s readFile function. For similar examples, see Local File Templates.
{{% /note %}}

Taxonomies

What is a Taxonomy?

Hugo includes support for user-defined groupings of content called taxonomies. Taxonomies are classifications of logical relationships between content.

Definitions

Taxonomy
a categorization that can be used to classify content
Term
a key within the taxonomy
Value
a piece of content assigned to a term

{{< youtube “-np9GX6cL38” >}}

Example Taxonomy: Movie Website

Let’s assume you are making a website about movies. You may want to include the following taxonomies:

  • Actors
  • Directors
  • Studios
  • Genre
  • Year
  • Awards

Then, in each of the movies, you would specify terms for each of these taxonomies (i.e., in the front matter of each of your movie content files). From these terms, Hugo would automatically create pages for each Actor, Director, Studio, Genre, Year, and Award, with each listing all of the Movies that matched that specific Actor, Director, Studio, Genre, Year, and Award.

Movie Taxonomy Organization

To continue with the example of a movie site, the following demonstrates content relationships from the perspective of the taxonomy:

Actor                    <- Taxonomy
    Bruce Willis         <- Term
        The Sixth Sense    <- Content
        Unbreakable      <- Content
        Moonrise Kingdom <- Content
    Samuel L. Jackson    <- Term
        Unbreakable      <- Content
        The Avengers     <- Content
        xXx              <- Content

From the perspective of the content, the relationships would appear differently, although the data and labels used are the same:

Unbreakable                 <- Content
    Actors                  <- Taxonomy
        Bruce Willis        <- Term
        Samuel L. Jackson   <- Term
    Director                <- Taxonomy
        M. Night Shyamalan  <- Term
    ...
Moonrise Kingdom            <- Content
    Actors                  <- Taxonomy
        Bruce Willis        <- Term
        Bill Murray         <- Term
    Director                <- Taxonomy
        Wes Anderson        <- Term
    ...

Hugo Taxonomy Defaults

Hugo natively supports taxonomies.

Without adding a single line to your site’s configuration file, Hugo will automatically create taxonomies for tags and categories. If you do not want Hugo to create any taxonomies, set disableKinds in your site’s configuration to the following:

disableKinds = ["taxonomy","taxonomyTerm"]

Default Destinations

When taxonomies are used—and taxonomy templates are provided—Hugo will automatically create both a page listing all the taxonomy’s terms and individual pages with lists of content associated with each term. For example, a categories taxonomy declared in your configuration and used in your content front matter will create the following pages:

Configure Taxonomies

Taxonomies must be defined in your website configuration before they can be used throughout the site. You need to provide both the plural and singular labels for each taxonomy. For example, singular key = "plural value" for TOML and singular key: "plural value" for YAML.

Example: TOML Taxonomy Configuration

[taxonomies]
  tag = "tags"
  category = "categories"
  series = "series"

Example: YAML Taxonomy Configuration

taxonomies:
  tag: "tags"
  category: "categories"
  series: "series"

Preserve Taxonomy Values

By default, taxonomy names are normalized.

Therefore, if you want to have a taxonomy term with special characters such as Gérard Depardieu instead of Gerard Depardieu, set the value for preserveTaxonomyNames to true in your site configuration. Hugo will then preserve special characters in taxonomy values but will still title-ize the values for titles and normalize them in URLs.

Note that if you use preserveTaxonomyNames and intend to manually construct URLs to the archive pages, you will need to pass the taxonomy values through the urlize template function.

{{% note %}}
You can add content and front matter to your taxonomy list and taxonomy terms pages. See Content Organization for more information on how to add an _index.md for this purpose.

Note also that taxonomy permalinks are not configurable.
{{% /note %}}

Add Taxonomies to Content

Once a taxonomy is defined at the site level, any piece of content can be assigned to it, regardless of content type or content section.

Assigning content to a taxonomy is done in the front matter. Simply create a variable with the plural name of the taxonomy and assign all terms you want to apply to the instance of the content type.

{{% note %}}
If you would like the ability to quickly generate content files with preconfigured taxonomies or terms, read the docs on Hugo archetypes.
{{% /note %}}

Example: TOML Front Matter with Taxonomies

+++
title = "Hugo: A fast and flexible static site generator"
tags = [ "Development", "Go", "fast", "Blogging" ]
categories = [ "Development" ]
series = [ "Go Web Dev" ]
slug = "hugo"
project_url = "https://github.com/gohugoio/hugo"
+++

Example: YAML Front Matter with Taxonomies

---
title: "Hugo: A fast and flexible static site generator"
#tags: ["Development", "Go", "fast", "Blogging"]
categories: ["Development"]
series: ["Go Web Dev"]
slug: "hugo"
project_url: "https://github.com/gohugoio/hugo"
---

Example: JSON Front Matter with Taxonomies

{
    "title": "Hugo: A fast and flexible static site generator",
    "tags": [
        "Development",
        "Go",
        "fast",
        "Blogging"
    ],
    "categories" : [
        "Development"
    ],
    "series" : [
        "Go Web Dev"
    ],
    "slug": "hugo",
    "project_url": "https://github.com/gohugoio/hugo"
}

Order Taxonomies

A content file can assign weight for each of its associate taxonomies. Taxonomic weight can be used for sorting or ordering content in taxonomy list templates and is declared in a content file’s front matter. The convention for declaring taxonomic weight is taxonomyname_weight.

The following TOML and YAML examples show a piece of content that has a weight of 22, which can be used for ordering purposes when rendering the pages assigned to the “a”, “b” and “c” values of the tags taxonomy. It has also been assigned the weight of 44 when rendering the “d” category page.

Example: TOML Taxonomic weight

+++
title = "foo"
tags = [ "a", "b", "c" ]
tags_weight = 22
categories = ["d"]
categories_weight = 44
+++

Example: YAML Taxonomic weight

---
title: foo
#tags: [ "a", "b", "c" ]
tags_weight: 22
categories: ["d"]
categories_weight: 44
---

By using taxonomic weight, the same piece of content can appear in different positions in different taxonomies.

{{% note “Limits to Ordering Taxonomies” %}}
Currently taxonomies only support the default weight => date ordering of list content. For more information, see the documentation on taxonomy templates.
{{% /note %}}

Content Summaries

With the use of the .Summary page variable, Hugo generates summaries of content to use as a short version in summary views.

Summary Splitting Options

  • Hugo-defined Summary Split
  • User-defined Summary Split

It is natural to accompany the summary with links to the original content, and a common design pattern is to see this link in the form of a “Read More …” button. See the .RelPermalink, .Permalink, and .Truncated page variables.

Hugo-defined: Automatic Summary Splitting

By default, Hugo automatically takes the first 70 words of your content as its summary and stores it into the .Summary page variable for use in your templates. Taking the Hugo-defined approach to summaries may save time, but it has pros and cons:

  • Pros: Automatic, no additional work on your part.
  • Cons: All HTML tags are stripped from the summary, and the first 70 words, whether they belong to a heading or to different paragraphs, are all put into one paragraph.

{{% note %}}
The Hugo-defined summaries are set to use word count calculated by splitting the text by one or more consecutive white space characters. If you are creating content in a CJK language and want to use Hugo’s automatic summary splitting, set hasCJKLanguage to true in you site configuration.
{{% /note %}}

User-defined: Manual Summary Splitting

Alternatively, you may add the <!--more--> summary divider where you want to split the article. For org content, use # more where you want to split the article. Content that comes before the summary divider will be used as that content’s summary and stored in the .Summary page variable with all HTML formatting intact.

{{% note “Summary Divider”%}}
The concept of a summary divider is not unique to Hugo. It is also called the “more tag” or “excerpt separator” in other literature.
{{% /note %}}

  • Pros: Freedom, precision, and improved rendering. All HTML tags and formatting are preserved.
  • Cons: Extra work for content authors, since they need to remember to type <!--more--> (or # more for org content) in each content file. This can be automated by adding the summary divider below the front matter of an archetype.

{{% warning “Be Precise with the Summary Divider” %}}
Be careful to enter <!--more--> exactly; i.e., all lowercase and with no whitespace.
{{% /warning %}}

Example: First 10 Articles with Summaries

You can show content summaries with the following code. You could use the following snippet, for example, in a [section template][].

{{< code file=“page-list-with-summaries.html” >}}
{{ range first 10 .Data.Pages }}


{{ end }}
{{< /code >}}

Note how the .Truncated boolean valuable may be used to hide the “Read More…” link when the content is not truncated; i.e., when the summary contains the entire article.

[section template]: /templates/section-templates/

Cross References

The ref and relref shortcodes link documents together, both of which are built-in Hugo shortcodes. These shortcodes are also used to provide links to headings inside of your content, whether across documents or within a document. The only difference between ref and relref is whether the resulting URL is absolute (http://1.com/about/) or relative (/about/), respectively.

Use ref and relref

{{</* ref "document" */>}}
{{</* ref "#anchor" */>}}
{{</* ref "document#anchor" */>}}
{{</* relref "document" */>}}
{{</* relref "#anchor" */>}}
{{</* relref "document#anchor" */>}}

The single parameter to ref is a string with a content documentname (e.g., about.md) with or without an appended in-document anchor (#who) without spaces.

Document Names

The documentname is the name of a document, including the format extension; this may be just the filename, or the relative path from the content/ directory. With a document content/blog/post.md, either format will produce the same result:

{{</* relref "blog/post.md" */>}} => `/blog/post/`
{{</* relref "post.md" */>}} => `/blog/post/`

If you have the same filename used across multiple sections, you should only use the relative path format; otherwise, the behavior will be undefined. This is best illustrated with an example content directory:

.
└── content
    ├── events
    │   └── my-birthday.md
    ├── galleries
    │   └── my-birthday.md
    ├── meta
    │   └── my-article.md
    └── posts
        └── my-birthday.md

To be sure to get the correct reference in this case, use the full path:

{{< code file=“content/meta/my-article.md” copy=“false” >}}
{{</* relref “events/my-birthday.md” */>}} => /events/my-birthday/
{{< /code >}}

{{< todo >}}Remove this warning when https://github.com/gohugoio/hugo/issues/3703 is released.{{< /todo >}}

A relative document name must not begin with a slash (/).

{{</* relref "/events/my-birthday.md" */>}} => ""

With Multiple Output Formats

If the page exists in multiple output formats, ref or relref can be used with a output format name:

 [Neat]({{</* ref "blog/neat.md" "amp" */>}})

Anchors

When an anchor is provided by itself, the current page’s unique identifier will be appended; when an anchor is provided appended to documentname, the found page’s unique identifier will be appended:

{{</* relref "#anchors" */>}} => #anchors:9decaf7
{{</* relref "about-hugo/hugo-features.md#content" */>}} => /blog/post/#who:badcafe

The above examples render as follows for this very page as well as a reference to the “Content” heading in the Hugo docs features pageyoursite

{{</* relref "#who" */>}} => #who:9decaf7
{{</* relref "blog/post.md#who" */>}} => /blog/post/#who:badcafe

More information about document unique identifiers and headings can be found [below]({{< ref “#hugo-heading-anchors” >}}).

Examples

  • {{</* ref "blog/post.md" */>}} => http://example.com/blog/post/
  • {{</* ref "post.md#tldr" */>}} => http://example.com/blog/post/#tldr:caffebad
  • {{</* relref "post.md" */>}} => /blog/post/
  • {{</* relref "blog/post.md#tldr" */>}} => /blog/post/#tldr:caffebad
  • {{</* ref "#tldr" */>}} => #tldr:badcaffe
  • {{</* relref "#tldr" */>}} => #tldr:badcaffe

Hugo Heading Anchors

When using Markdown document types, Hugo generates heading anchors automatically. The generated anchor for this section is hugo-heading-anchors. Because the heading anchors are generated automatically, Hugo takes some effort to ensure that heading anchors are unique both inside a document and across the entire site.

Ensuring heading uniqueness across the site is accomplished with a unique identifier for each document based on its path. Unless a document is renamed or moved between sections in the filesystem, the unique identifier for the document will not change: blog/post.md will always have a unique identifier of 81df004c333b392d34a49fd3a91ba720.

ref and relref were added so you can make these reference links without having to know the document’s unique identifier. (The links in document tables of contents are automatically up-to-date with this value.)

{{</* relref "content-management/cross-references.md#hugo-heading-anchors" */>}}
/content-management/cross-references/#hugo-heading-anchors:77cd9ea530577debf4ce0f28c8dca242

[shortcode]: /content-management/shortcodes/

URL Management

Permalinks

The default Hugo target directory for your built website is public/. However, you can change this value by specifying a different publishDir in your site configuration. The directories created at build time for a section reflect the position of the content’s directory within the content folder and namespace matching its layout within the contentdir hierarchy.

The permalinks option in your site configuration allows you to adjust the directory paths (i.e., the URLs) on a per-section basis. This will change where the files are written to and will change the page’s internal “canonical” location, such that template references to .RelPermalink will honor the adjustments made as a result of the mappings in this option.

{{% note “Default Publish and Content Folders” %}}
These examples use the default values for publishDir and contentDir; i.e., publish and content, respectively. You can override the default values in your site’s config file.
{{% /note %}}

For example, if one of your sections is called post and you want to adjust the canonical path to be hierarchical based on the year, month, and post title, you could set up the following configurations in YAML and TOML, respectively.

YAML Permalinks Configuration Example

{{< code file=“config.yml” copy=“false” >}}
permalinks:
post: /:year/:month/:title/
{{< /code >}}

TOML Permalinks Configuration Example

{{< code file=“config.toml” copy=“false” >}}
[permalinks]
post = “/:year/:month/:title/”
{{< /code >}}

Only the content under post/ will have the new URL structure. For example, the file content/post/sample-entry.md with date: 2017-02-27T19:20:00-05:00 in its front matter will render to public/2017/02/sample-entry/index.html at build time and therefore be reachable at http://example.com/2013/11/sample-entry/.

Permalink Configuration Values

The following is a list of values that can be used in a permalink definition in your site config file. All references to time are dependent on the content’s date.

:year
the 4-digit year
:month
the 2-digit month
:monthname
the name of the month
:day
the 2-digit day
:weekday
the 1-digit day of the week (Sunday = 0)
:weekdayname
the name of the day of the week
:yearday
the 1- to 3-digit day of the year
:section
the content’s section
:title
the content’s title
:slug
the content’s slug (or title if no slug is provided in the front matter)
:filename
the content’s filename (without extension)

Aliases

For people migrating existing published content to Hugo, there’s a good chance you need a mechanism to handle redirecting old URLs.

Luckily, redirects can be handled easily with aliases in Hugo.

Example: Aliases

Let’s assume you create a new piece of content at content/posts/my-awesome-blog-post.md. The content is a revision of your previous post at content/posts/my-original-url.md. You can create an aliases field in the front matter of your new my-awesome-blog-post.md where you can add previous paths. The following examples show how to create this filed in TOML and YAML front matter, respectively.

TOML Front Matter

{{< code file=“content/posts/my-awesome-post.md” copy=“false” >}}
+++
aliases = [
“/posts/my-original-url/”,
“/2010/01/01/even-earlier-url.html”
]
+++
{{< /code >}}

YAML Front Matter

{{< code file=“content/posts/my-awesome-post.md” copy=“false” >}}

aliases:
- /posts/my-original-url/
- /2010/01/01/even-earlier-url.html

{{< /code >}}

Now when you visit any of the locations specified in aliases—i.e., assuming the same site domain—you’ll be redirected to the page they are specified on. For example, a visitor to example.com/posts/my-original-url/ will be immediately redirected to example.com/posts/my-awesome-blog-post/.

Example: Aliases in Multilingual

On multilingual sites, each translation of a post can have unique aliases. To use the same alias across multiple languages, prefix it with the language code.

In /posts/my-new-post.es.md:

---
aliases:
    - /es/posts/my-original-post/
---

How Hugo Aliases Work

When aliases are specified, Hugo creates a directory to match the alias entry. Inside the directory, Hugo creates an .html file specifying the canonical URL for the page and the new redirect target.

For example, a content file at posts/my-intended-url.md with the following in the front matter:

---
title: My New post
aliases: [/posts/my-old-url/]
---

Assuming a baseURL of example.com, the contents of the auto-generated alias .html found at https://example.com/posts/my-old-url/ will contain the following:

<!DOCTYPE html>
<html>
  <head>
    <title>http://example.com/posts/my-intended-url</title>
    <link rel="canonical" href="http://example.com/posts/my-intended-url"/>
    <meta name=\"robots\" content=\"noindex\">
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <meta http-equiv="refresh" content="0; url=http://example.com/posts/my-intended-url"/>
  </head>
</html>

The http-equiv="refresh" line is what performs the redirect, in 0 seconds in this case. If an end user of your website goes to https://example.com/posts/my-old-url, they will now be automatically redirected to the newer, correct URL. The addition of <meta name=\"robots\" content=\"noindex\"> lets search engine bots know they they should not crawl and index your new alias page.

Customize

You may customize this alias page by creating an alias.html template in the
layouts folder of your site (i.e., layouts/alias.html). In this case, the data passed to the template is

Permalink
the link to the page being aliased
Page
the Page data for the page being aliased

Important Behaviors of Aliases

  1. Hugo makes no assumptions about aliases. They also do not change based
    on your UglyURLs setting. You need to provide absolute paths to your web root
    and the complete filename or directory.
  2. Aliases are rendered before any content are rendered and therefore will be overwritten by any content with the same location.

Pretty URLs

Hugo’s default behavior is to render your content with “pretty” URLs. No non-standard server-side configuration is required for these pretty URLs to work.

The following demonstrates the concept:

content/posts/_index.md
=> example.com/posts/index.html
content/posts/post-1.md
=> example.com/posts/post-1/

Ugly URLs

If you would like to have what are often referred to as “ugly URLs” (e.g., example.com/urls.html), set uglyurls = true or uglyurls: true in your site’s config.toml or config.yaml, respectively. You can also use the --uglyURLs=true flag from the command line with hugo or hugo server

If you want a specific piece of content to have an exact URL, you can specify this in the front matter under the url key. The following are examples of the same content directory and what the eventual URL structure will be when Hugo runs with its default behavior.

See Content Organization for more details on paths.

.
└── content
    └── about
    |   └── _index.md  // <- http://example.com/about/
    ├── post
    |   ├── firstpost.md   // <- http://example.com/post/firstpost/
    |   ├── happy
    |   |   └── ness.md  // <- http://example.com/post/happy/ness/
    |   └── secondpost.md  // <- http://example.com/post/secondpost/
    └── quote
        ├── first.md       // <- http://example.com/quote/first/
        └── second.md      // <- http://example.com/quote/second/

Here’s the same organization run with hugo --uglyURLs:

.
└── content
    └── about
    |   └── _index.md  // <- http://example.com/about/index.html
    ├── post
    |   ├── firstpost.md   // <- http://example.com/post/firstpost.html
    |   ├── happy
    |   |   └── ness.md    // <- http://example.com/post/happy/ness.html
    |   └── secondpost.md  // <- http://example.com/post/secondpost.html
    └── quote
        ├── first.md       // <- http://example.com/quote/first.html
        └── second.md      // <- http://example.com/quote/second.html

Canonicalization

By default, all relative URLs encountered in the input are left unmodified, e.g. /css/foo.css would stay as /css/foo.css. The canonifyURLs field in your site config has a default value of false.

By setting canonifyURLs to true, all relative URLs would instead be canonicalized using baseURL. For example, assuming you have baseURL = https://example.com/, the relative URL /css/foo.css would be turned into the absolute URL http://example.com/css/foo.css.

Benefits of canonicalization include fixing all URLs to be absolute, which may aid with some parsing tasks. Note, however, that all modern browsers handle this on the client without issue.

Benefits of non-canonicalization include being able to have scheme-relative resource inclusion; e.g., so that http vs https can be decided according to how the page was retrieved.

{{% note “canonifyURLs default change” %}}
In the May 2014 release of Hugo v0.11, the default value of canonifyURLs was switched from true to false, which we think is the better default and should continue to be the case going forward. Please verify and adjust your website accordingly if you are upgrading from v0.10 or older versions.
{{% /note %}}

To find out the current value of canonifyURLs for your website, you may use the handy hugo config command added in v0.13.

hugo config | grep -i canon

Or, if you are on Windows and do not have grep installed:

hugo config | FINDSTR /I canon

Override URLS with Front Matter

In addition to specifying permalink values in your site configuration for different content sections, Hugo provides even more granular control for individual pieces of content.

Both slug and url can be defined in individual front matter. For more information on content destinations at build time, see Content Organization.

Relative URLs

By default, all relative URLs are left unchanged by Hugo, which can be problematic when you want to make your site browsable from a local file system.

Setting relativeURLs to true in your site configuration will cause Hugo to rewrite all relative URLs to be relative to the current content.

For example, if your /post/first/ page contains a link to /about/, Hugo will rewrite the URL to ../../about/.

Menus

{{% note “Lazy Blogger”%}}
If all you want is a simple menu for your sections, see the “Section Menu for Lazy Bloggers” in Menu Templates.
{{% /note %}}

You can do this:

  • Place content in one or many menus
  • Handle nested menus with unlimited depth
  • Create menu entries without being attached to any content
  • Distinguish active element (and active branch)

What is a Menu in Hugo?

A menu is a named array of menu entries accessible by name via the .Site.Menus site variable. For example, you can access your site’s main menu via .Site.Menus.main.

{{% note “Menus on Multilingual Sites” %}}
If you make use of the multilingual feature, you can define language-independent menus.
{{% /note %}}

A menu entry has the following properties (i.e., variables) available to it:

.URL
string
.Name
string
.Menu
string
.Identifier
string
.Pre
template.HTML
.Post
template.HTML
.Weight
int
.Parent
string
.Children
Menu

Note that menus also have the following functions available as well:

.HasChildren
boolean

Additionally, there are some relevant functions available to menus on a page:

.IsMenuCurrent
(menu string, menuEntry *MenuEntry ) boolean
.HasMenuCurrent
(menu string, menuEntry *MenuEntry) boolean

Add content to menus

Hugo allows you to add content to a menu via the content’s front matter.

Simple

If all you need to do is add an entry to a menu, the simple form works well.

A Single Menu

---
menu: "main"
---

Multiple Menus

---
menu: ["main", "footer"]
---

Advanced

---
menu:
  docs:
    parent: 'extras'
    weight: 20
---

Add Non-content Entries to a Menu

You can also add entries to menus that aren’t attached to a piece of content. This takes place in your Hugo project’s config file.

Here’s an example snippet pulled from a config.toml:

{{< code file=“config.toml” >}}
[[menu.main]]
name = “about hugo”
pre = “
weight = -110
identifier = “about”
url = “/about/”
[[menu.main]]
name = “getting started”
pre = “
weight = -100
url = “/getting-started/”
{{< /code >}}

Here’s the equivalent snippet in a config.yaml:

{{< code file=“config.yml” >}}

menu:
docs:
- Name: “about hugo”
Pre: “
Weight: -110
Identifier: “about”
URL: “/about/”
- Name: “getting started”
Pre: “
Weight: -100
URL: “/getting-started/”

{{< /code >}}

{{% note %}}
The URLs must be relative to the context root. If the baseURL is http://example.com/mysite/, then the URLs in the menu must not include the context root mysite. Using an absolute URL will overide the baseURL. If the value used for URL in the above example is http://subdomain.example.com/, the output will be http://subdomain.example.com.
{{% /note %}}

Nesting

All nesting of content is done via the parent field.

The parent of an entry should be the identifier of another entry. The identifier should be unique (within a menu).

The following order is used to determine an Identifier:

.Name > .LinkTitle > .Title

This means that .Title will be used unless .LinkTitle is present, etc. In practice, .Name and .Identifier are only used to structure relationships and therefore never displayed.

In this example, the top level of the menu is defined in your site config file). All content entries are attached to one of these entries via the .Parent field.

Render Menus

See Menu Templates for information on how to render your site menus within your templates.

Table of Contents

{{% note “TOC Heading Levels are Fixed” %}}
Currently, the {{.TableOfContents}} page variable does not allow you to specify which heading levels you want the TOC to render. See the related GitHub discussion (#1778). As such, the resulting <nav id="TableOfContents"><ul></ul></nav> is going to start at <h1> when pulling from {{.Content}}.
{{% /note %}}

Usage

Create your markdown the way you normally would with the appropriate headings. Here is some example content:

<!-- Your front matter up here -->

## Introduction

One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.

## My Heading

He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment.

### My Subheading

A collection of textile samples lay spread out on the table - Samsa was a travelling salesman - and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. It showed a lady fitted out with a fur hat and fur boa who sat upright, raising a heavy fur muff that covered the whole of her lower arm towards the viewer. Gregor then turned to look out the window at the dull weather. Drops

Hugo will take this Markdown and create a table of contents from ## Introduction, ## My Heading, and ### My Subheading and then store it in the page variable.TableOfContents.

The built-in .TableOfContents variables outputs a <nav id="TableOfContents"> element with a child <ul>, whose child <li> elements begin with any <h1>‘s (i.e., # in markdown) inside your content.’

Template Example: Basic TOC

The following is an example of a very basic single page template:

{{< code file=“layout/_default/single.html” download=“single.html” >}}
{{ define “main” }}

{{ .Title }}

{{ .Content }}
{{ end }} {{< /code >}}

Template Example: TOC Partial

The following is a partial template that adds slightly more logic for page-level control over your table of contents. It assumes you are using a toc field in your content’s front matter that, unless specifically set to false, will add a TOC to any page with a .WordCount (see Page Variables) greater than 400. This example also demonstrates how to use conditionals in your templating:

{{< code file=“layouts/partials/toc.html” download=“toc.html” >}}
{{ if and (gt .WordCount 400 ) (ne .Params.toc “false”) }}

{{ end }} {{< /code >}}

{{% note %}}
With the preceding example, even pages with > 400 words and toc not set to false will not render a table of contents if there are no headings in the page for the {{.TableOfContents}} variable to pull from.
{{% /note %}}

single page template: /templates/single-page-templates/

Comments

Hugo ships with support for Disqus, a third-party service that provides comment and community capabilities to websites via JavaScript.

Your theme may already support Disqus, but if not, it is easy to add to your templates via Hugo’s built-in Disqus partial.

Add Disqus

Hugo comes with all the code you need to load Disqus into your templates. Before adding Disqus to your site, you’ll need to set up an account.

Configure Disqus

Disqus comments require you set a single value in your site’s configuration file. The following show the configuration variable in a config.toml and config.yml, respectively:

disqusShortname = "yourdiscussshortname"
disqusShortname: "yourdiscussshortname"

For many websites, this is enough configuration. However, you also have the option to set the following in the front matter of a single content file:

  • disqus_identifier
  • disqus_title
  • disqus_url

Render Hugo’s Built-in Disqus Partial Template

See Partial Templates to learn how to add the Disqus partial to your Hugo website’s templates.

Comments Alternatives

There are a few alternatives to commenting on static sites for those who do not want to use Disqus:

Multilingual Mode

You should define the available languages in a Languages section in your site configuration.

Configure Languages

The following is an example of a TOML site configuration for a multilingual Hugo project:

{{< code file=“config.toml” download=“config.toml” >}}
DefaultContentLanguage = “en”
copyright = “Everything is mine”

[params.navigation]
help = “Help”

[Languages]
[Languages.en]
title = “My blog”
weight = 1
[Languages.en.params]
linkedin = “english-link”

[Languages.fr]
copyright = “Tout est à moi”
title = “Mon blog”
weight = 2
[Languages.fr.params]
linkedin = “lien-francais”
[Languages.fr.navigation]
help = “Aide”
{{< /code >}}

Anything not defined in a [Languages] block will fall back to the global
value for that key (e.g., copyright for the English [en] language).

With the configuration above, all content, sitemap, RSS feeds, paginations,
and taxonomy pages will be rendered below / in English (your default content language) and then below /fr in French.

When working with front matter Params in single page templates, omit the params in the key for the translation.

If you want all of the languages to be put below their respective language code, enable defaultContentLanguageInSubdir: true.

Only the obvious non-global options can be overridden per language. Examples of global options are baseURL, buildDrafts, etc.

Taxonomies and Blackfriday

Taxonomies and Blackfriday configuration can also be set per language:

{{< code file=“bf-config.toml” >}}
Taxonomies
tag = “tags”

blackfriday
angledQuotes = true
hrefTargetBlank = true

[Languages]
[Languages.en]
weight = 1
title = “English”
[Languages.en.blackfriday]
angledQuotes = false

[Languages.fr]
weight = 2
title = “Français”
[Languages.fr.Taxonomies]
plaque = “plaques”
{{< /code >}}

Translate Your Content

Translated articles are identified by the name of the content file.

Examples of Translated Articles

  1. /content/about.en.md
  2. /content/about.fr.md

In this example, the about.md will be assigned the configured defaultContentLanguage.

  1. /content/about.md
  2. /content/about.fr.md

This way, you can slowly start to translate your current content without having to rename everything. If left unspecified, the default value for defaultContentLanguage is en.

By having the same base filename, the content pieces are linked together as translated pieces.

If you need distinct URLs per language, you can set the slug in the non-default language file. For example, you can define a custom slug for a French translation in the front matter of content/about.fr.md as follows:

slug: "a-propos"

At render, Hugo will build both /about/ and /a-propos/ as properly linked translated pages.

{{%note %}}
Hugo currently uses the base filename as the translation key, which can be an issue with identical filenames in different sections.
We will fix this in https://github.com/gohugoio/hugo/issues/2699
{{% /note %}}
{{< todo >}}Rewrite/remove the above one issue is fixed.{{< /todo >}}

Link to Translated Content

To create a list of links to translated content, use a template similar to the following:

{{< code file=“layouts/partials/i18nlist.html” >}}
{{ if .IsTranslated }}

{{ i18n "translations" }}

{{ end }} {{< /code >}}

The above can be put in a partial (i.e., inside layouts/partials/) and included in any template, be it for a single content page or the homepage. It will not print anything if there are no translations for a given page, or if there are translations—in the case of the homepage, section listing, etc.—a site with only render one language.

The above also uses the i18n function described in the next section.

Translation of Strings

Hugo uses go-i18n to support string translations. See the project’s source repository to find tools that will help you manage your translation workflows.

Translations are collected from the themes/<THEME>/i18n/ folder (built into the theme), as well as translations present in i18n/ at the root of your project. In the i18n, the translations will be merged and take precedence over what is in the theme folder. Language files should be named according to RFC 5646 with names such as en-US.toml, fr.toml, etc.

From within your templates, use the i18n function like this:

{{ i18n "home" }}

This uses a definition like this one in i18n/en-US.toml:

[home]
other = "Home"

Often you will want to use to the page variables in the translations strings. To do that, pass on the “.” context when calling i18n:

{{ i18n "wordCount" . }}

This uses a definition like this one in i18n/en-US.toml:

[wordCount]
other = "This article has {{ .WordCount }} words."

An example of singular and plural form:

[readingTime]
one = "One minute read"
other = "{{.Count}} minutes read"

And then in the template:

{{ i18n "readingTime" .ReadingTime }}

To track down missing translation strings, run Hugo with the --i18n-warnings flag:

 hugo --i18n-warnings | grep i18n
i18n|MISSING_TRANSLATION|en|wordCount

Customize Dates

At the time of this writing, Golang does not yet have support for internationalized locales, but if you do some work, you can simulate it. For example, if you want to use French month names, you can add a data file like data/mois.yaml with this content:

1: "janvier"
2: "février"
3: "mars"
4: "avril"
5: "mai"
6: "juin"
7: "juillet"
8: "août"
9: "septembre"
10: "octobre"
11: "novembre"
12: "décembre"

… then index the non-English date names in your templates like so:

<time class="post-date" datetime="{{ .Date.Format "2006-01-02T15:04:05Z07:00" | safeHTML }}">
  Article publié le {{ .Date.Day }} {{ index $.Site.Data.mois (printf "%d" .Date.Month) }} {{ .Date.Year }} (dernière modification le {{ .Lastmod.Day }} {{ index $.Site.Data.mois (printf "%d" .Lastmod.Month) }} {{ .Lastmod.Year }})
</time>

This technique extracts the day, month and year by specifying .Date.Day, .Date.Month, and .Date.Year, and uses the month number as a key, when indexing the month name data file.

Menus

You can define your menus for each language independently. The creation of a menu works analogous to earlier versions of Hugo, except that they have to be defined in their language-specific block in the configuration file:

defaultContentLanguage = "en"

[languages.en]
weight = 0
languageName = "English"

[[languages.en.menu.main]]
url    = "/"
name   = "Home"
weight = 0


[languages.de]
weight = 10
languageName = "Deutsch"

[[languages.de.menu.main]]
url    = "/"
name   = "Startseite"
weight = 0

The rendering of the main navigation works as usual. .Site.Menus will just contain the menu of the current language. Pay attention to the generation of the menu links. absLangURL takes care that you link to the correct locale of your website. Otherwise, both menu entries would link to the English version as the default content language that resides in the root directory.

<ul>
    {{- $currentPage := . -}}
    {{ range .Site.Menus.main -}}
    <li class="{{ if $currentPage.IsMenuCurrent "main" . }}active{{ end }}">
        <a href="{{ .URL | absLangURL }}">{{ .Name }}</a>
    </li>
    {{- end }}
</ul>

Missing translations

If a string does not have a translation for the current language, Hugo will use the value from the default language. If no default value is set, an empty string will be shown.

While translating a Hugo website, it can be handy to have a visual indicator of missing translations. The enableMissingTranslationPlaceholders configuration option will flag all untranslated strings with the placeholder [i18n] identifier, where identifier is the id of the missing translation.

{{% note %}}
Hugo will generate your website with these missing translation placeholders. It might not be suited for production environments.
{{% /note %}}

Multilingual Themes support

To support Multilingual mode in your themes, some considerations must be taken for the URLs in the templates. If there is more than one language, URLs must meet the following criteria:

If there is more than one language defined, the LanguagePrefix variable will equal /en (or whatever your CurrentLanguage is). If not enabled, it will be an empty string and is therefore harmless for single-language Hugo websites.

Templates

Introduction to Hugo Templating

{{% note %}}
The following is only a primer on Go templates. For an in-depth look into Go templates, check the official Go docs.
{{% /note %}}

Go templates provide an extremely simple template language that adheres to the belief that only the most basic of logic belongs in the template or view layer.

Basic Syntax

Golang templates are HTML files with the addition of variables and functions. Golang template variables and functions are accessible within {{ }}.

Access a Predefined Variable

{{ foo }}

Parameters for functions are separated using spaces. The following example calls the add function with inputs of 1 and 2:

{{ add 1 2 }}

Methods and Fields are Accessed via dot Notation

Accessing the Page Parameter bar defined in a piece of content’s front matter.

{{ .Params.bar }}

Parentheses Can be Used to Group Items Together

{{ if or (isset .Params "alt") (isset .Params "caption") }} Caption {{ end }}

Variables

Each Go template gets a data object. In Hugo, each template is passed a Page. See variables for more information.

This is how you access a Page variable from a template:

<title>{{ .Title }}</title>

Values can also be stored in custom variables and referenced later:

{{ $address := "123 Main St."}}
{{ $address }}

{{% warning %}}
Variables defined inside if conditionals and similar are not visible on the outside. See https://github.com/golang/go/issues/10608.

Hugo has created a workaround for this issue in Scratch.

{{% /warning %}}

Functions

Go templates only ship with a few basic functions but also provide a mechanism for applications to extend the original set.

Hugo template functions provide additional functionality specific to building websites. Functions are called by using their name followed by the required parameters separated by spaces. Template functions cannot be added without recompiling Hugo.

Example 1: Adding Numbers

{{ add 1 2 }}
=> 3

Example 2: Comparing Numbers

{{ lt 1 2 }}
=> true (i.e., since 1 is less than 2)

Note that both examples make us of Go template’s math functions.

{{% note “Additional Boolean Operators” %}}
There are more boolean operators than those listed in the Hugo docs in the Golang template documentation.
{{% /note %}}

Includes

When including another template, you will pass to it the data it will be
able to access. To pass along the current context, please remember to
include a trailing dot. The templates location will always be starting at
the /layout/ directory within Hugo.

Template and Partial Examples

{{ template "partials/header.html" . }}

Starting with Hugo v0.12, you may also use the partial call
for partial templates:

{{ partial "header.html" . }}

Logic

Go templates provide the most basic iteration and conditional logic.

Iteration

Just like in Go, the Go templates make heavy use of range to iterate over
a map, array, or slice. The following are different examples of how to use
range.

Example 1: Using Context

{{ range array }}
    {{ . }}
{{ end }}

Example 2: Declaring Value => Variable name

{{range $element := array}}
    {{ $element }}
{{ end }}

Example 3: Declaring Key-Value Variable Name

{{range $index, $element := array}}
   {{ $index }}
   {{ $element }}
{{ end }}

Conditionals

if, else, with, or, and and provide the framework for handling conditional logic in Go Templates. Like range, each statement is closed with an {{end}}.

Go Templates treat the following values as false:

  • false
  • 0
  • any zero-length array, slice, map, or string

Example 1: if

{{ if isset .Params "title" }}<h4>{{ index .Params "title" }}</h4>{{ end }}

Example 2: ifelse

{{ if isset .Params "alt" }}
    {{ index .Params "alt" }}
{{else}}
    {{ index .Params "caption" }}
{{ end }}

Example 3: and & or

{{ if and (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}}

Example 4: with

An alternative way of writing “if” and then referencing the same value
is to use “with” instead. with rebinds the context . within its scope
and skips the block if the variable is absent.

The first example above could be simplified as:

{{ with .Params.title }}<h4>{{ . }}</h4>{{ end }}

Example 5: ifelse if

{{ if isset .Params "alt" }}
    {{ index .Params "alt" }}
{{ else if isset .Params "caption" }}
    {{ index .Params "caption" }}
{{ end }}

Pipes

One of the most powerful components of Go templates is the ability to stack actions one after another. This is done by using pipes. Borrowed from Unix pipes, the concept is simple: each pipeline’s output becomes the input of the following pipe.

Because of the very simple syntax of Go templates, the pipe is essential to being able to chain together function calls. One limitation of the pipes is that they can only work with a single value and that value becomes the last parameter of the next pipeline.

A few simple examples should help convey how to use the pipe.

Example 1: shuffle

The following two examples are functionally the same:

{{ shuffle (seq 1 5) }}
{{ (seq 1 5) | shuffle }}

Example 2: index

The following accesses the page parameter called “disqus_url” and escapes the HTML. This example also uses the index function, which is built into Go templates:

{{ index .Params "disqus_url" | html }}

Example 3: or with isset

{{ if or (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr") }}
Stuff Here
{{ end }}

Could be rewritten as

{{ if isset .Params "caption" | or isset .Params "title" | or isset .Params "attr" }}
Stuff Here
{{ end }}

Example 4: Internet Explorer Conditional Comments

By default, Go Templates remove HTML comments from output. This has the unfortunate side effect of removing Internet Explorer conditional comments. As a workaround, use something like this:

{{ "<!--[if lt IE 9]>" | safeHTML }}
  <script src="html5shiv.js"></script>
{{ "<![endif]-->" | safeHTML }}

Alternatively, you can use the backtick (`) to quote the IE conditional comments, avoiding the tedious task of escaping every double quotes (") inside, as demonstrated in the examples in the Go text/template documentation:

{{ `<!--[if lt IE 7]><html class="no-js lt-ie9 lt-ie8 lt-ie7"><![endif]-->` | safeHTML }}

Context (aka “the dot”)

The most easily overlooked concept to understand about Go templates is that {{ . }} always refers to the current context. In the top level of your template, this will be the data set made available to it. Inside of an iteration, however, it will have the value of the current item in the loop; i.e., {{ . }} will no longer refer to the data available to the entire page. If you need to access page-level data (e.g., page params set in front matter) from within the loop, you will likely want to do one of the following:

1. Define a Variable Independent of Context

The following shows how to define a variable independent of the context.

{{< code file=“tags-range-with-page-variable.html” >}}
{{ $title := .Site.Title }}

    {{ range .Params.tags }}
  • {{ . }} - {{ $title }}
  • {{ end }}
{{< /code >}}

{{% note %}}
Notice how once we have entered the loop (i.e. range), the value of {{ . }} has changed. We have defined a variable outside of the loop ({{$title}}) that we’ve assigned a value so that we have access to the value from within the loop as well.
{{% /note %}}

2. Use $. to Access the Global Context

$ has special significance in your templates. $ is set to the starting value of . (“the dot”) by default. This is a documented feature of Go text/template. This means you have access to the global context from anywhere. Here is an equivalent example of the preceding code block but now using $ to grab .Site.Title from the global context:

{{< code file=“range-through-tags-w-global.html” >}}

    {{ range .Params.tags }}
  • {{ . }} - {{ $.Site.Title }}
  • {{ end }}
{{< /code >}}

{{% warning “Don’t Redefine the Dot” %}}
The built-in magic of $ would cease to work if someone were to mischievously redefine the special character; e.g. {{ $ := .Site }}. Don’t do it. You may, of course, recover from this mischief by using {{ $ := . }} in a global context to reset $ to its default value.
{{% /warning %}}

Whitespace

Go 1.6 includes the ability to trim the whitespace from either side of a Go tag by including a hyphen (-) and space immediately beside the corresponding {{ or }} delimiter.

For instance, the following Go template will include the newlines and horizontal tab in its HTML output:

<div>
  {{ .Title }}
</div>

Which will output:

<div>
  Hello, World!
</div>

Leveraging the - in the following example will remove the extra white space surrounding the .Title variable and remove the newline:

<div>
  {{- .Title -}}
</div>

Which then outputs:

<div>Hello, World!</div>

Go considers the following characters whitespace:

  • space
  • horizontal tab
  • carriage return
  • newline

Hugo Parameters

Hugo provides the option of passing values to your template layer through your site configuration (i.e. for site-wide values) or through the metadata of each specific piece of content (i.e. the front matter). You can define any values of any type and use them however you want in your templates, as long as the values are supported by the front matter format specified via metaDataFormat in your configuration file.

Use Content (Page) Parameters

You can provide variables to be used by templates in individual content’s front matter.

An example of this is used in the Hugo docs. Most of the pages benefit from having the table of contents provided, but sometimes the table of contents doesn’t make a lot of sense. We’ve defined a notoc variable in our front matter that will prevent a table of contents from rendering when specifically set to true.

Here is the example front matter:

---
title: Roadmap
lastmod: 2017-03-05
date: 2013-11-18
notoc: true
---

Here is an example of corresponding code that could be used inside a toc.html partial template:

{{< code file=“layouts/partials/toc.html” download=“toc.html” >}}
{{ if not .Params.notoc }}

{{end}} {{< /code >}}

We want the default behavior to be for pages to include a TOC unless otherwise specified. This template checks to make sure that the notoc: field in this page’s front matter is not true.

Use Site Configuration Parameters

You can arbitrarily define as many site-level parameters as you want in your site’s configuration file. These parameters are globally available in your templates.

For instance, you might declare the following:

{{< code file=“config.yaml” >}}
params:
copyrighthtml: “Copyright © 2017 John Doe. All Rights Reserved.”
twitteruser: “spf13”
sidebarrecentlimit: 5
{{< /code >}}

Within a footer layout, you might then declare a <footer> that is only rendered if the copyrighthtml parameter is provided. If it is provided, you will then need to declare the string is safe to use via the safeHTML function so that the HTML entity is not escaped again. This would let you easily update just your top-level config file each January 1st, instead of hunting through your templates.

{{if .Site.Params.copyrighthtml}}<footer>
<div class="text-center">{{.Site.Params.CopyrightHTML | safeHTML}}</div>
</footer>{{end}}

An alternative way of writing the “if” and then referencing the same value is to use with instead. with rebinds the context (.) within its scope and skips the block if the variable is absent:

{{< code file=“layouts/partials/twitter.html” >}}
{{with .Site.Params.twitteruser}}

{{end}} {{< /code >}}

Finally, you can pull “magic constants” out of your layouts as well. The following uses the first function, as well as the .RelPermalink page variable and the .Site.Pages site variable.

<nav>
  <h1>Recent Posts</h1>
  <ul>
  {{- range first .Site.Params.SidebarRecentLimit .Site.Pages -}}
    <li><a href="{{.RelPermalink}}">{{.Title}}</a></li>
  {{- end -}}
  </ul>
</nav>

Example: Show Only Upcoming Events

Go allows you to do more than what’s shown here. Using Hugo’s where function and Go built-ins, we can list only the items from content/events/ whose date (set in a content file’s front matter) is in the future. The following is an example partial template:

{{< code file=“layouts/partials/upcoming-events.html” download=“upcoming-events.html” >}}

Upcoming Events

    {{ range where .Data.Pages.ByDate "Section" "events" }} {{ if ge .Date.Unix .Now.Unix }}
  • {{ .Type | title }} — {{ .Title }} on {{ .Date.Format "2 January at 3:04pm" }} at {{ .Params.place }}
  • {{ end }} {{ end }}
{{< /code >}}

Hugo’s Lookup Order

Before creating your templates, it’s important to know how Hugo looks for files within your project’s directory structure.

Hugo uses a prioritized list called the lookup order as it traverses your layouts folder in your Hugo project looking for the appropriate template to render your content.

The template lookup order is an inverted cascade: if template A isn’t present or specified, Hugo will look to template B. If template B isn’t present or specified, Hugo will look for template C…and so on until it reaches the _default/ directory for your project or theme. In many ways, the lookup order is similar to the programming concept of a switch statement without fallthrough.

The power of the lookup order is that it enables you to craft specific layouts and keep your templating DRY.

{{% note %}}
Most Hugo websites will only need the default template files at the end of the lookup order (i.e. _default/*.html).
{{% /note %}}

Lookup Orders

The respective lookup order for each of Hugo’s templates has been defined throughout the Hugo docs:

Template Lookup Examples

The lookup order is best illustrated through examples. The following shows you the process Hugo uses for finding the appropriate template to render your single page templates, but the concept holds true for all templates in Hugo.

  1. The project is using the theme mytheme (specified in the project’s configuration).
  2. The layouts and content directories for the project are as follows:
.
├── content
│   ├── events
│   │   ├── _index.md
│   │   └── my-first-event.md
│   └── posts
│       ├── my-first-post.md
│       └── my-second-post.md
├── layouts
│   ├── _default
│   │   └── single.html
│   ├── posts
│   │   └── single.html
│   └── reviews
│       └── reviewarticle.html
└── themes
    └── mytheme
        └── layouts
            ├── _default
            │   ├── list.html
            │   └── single.html
            └── posts
                ├── list.html
                └── single.html

Now we can look at the front matter for the three content (i.e..md) files.

{{% note %}}
Only three of the four markdown files in the above project are subject to the single page lookup order. _index.md is a specific kind in Hugo. Whereas my-first-post.md, my-second-post.md, and my-first-event.md are all of kind page, all _index.md files in a Hugo project are used to add content and front matter to list pages. In this example, events/_index.md will render according to its section template and respective lookup order.
{{% /note %}}

Example: my-first-post.md

{{< code file=“content/posts/my-first-post.md” copy=“false” >}}

title: My First Post
date: 2017-02-19
description: This is my first post.

{{< /code >}}

When building your site, Hugo will go through the lookup order until it finds what it needs for my-first-post.md:

  1. /layouts/UNSPECIFIED/UNSPECIFIED.html
  2. /layouts/posts/UNSPECIFIED.html
  3. /layouts/UNSPECIFIED/single.html
  4. /layouts/posts/single.html

    BREAK
  5. /layouts/_default/single.html
  6. /themes/<THEME>/layouts/UNSPECIFIED/UNSPECIFIED.html
  7. /themes/<THEME>/layouts/posts/UNSPECIFIED.html
  8. /themes/<THEME>/layouts/UNSPECIFIED/single.html
  9. /themes/<THEME>/layouts/posts/single.html
  10. /themes/<THEME>/layouts/_default/single.html

Notice the term UNSPECIFIED rather than UNDEFINED. If you don’t tell Hugo the specific type and layout, it makes assumptions based on sane defaults. my-first-post.md does not specify a content type in its front matter. Therefore, Hugo assumes the content type and section (i.e. posts, which is defined by file location) are one in the same. (Read more on sections.)

my-first-post.md also does not specify a layout in its front matter. Therefore, Hugo assumes that my-first-post.md, which is of type page and a single piece of content, should default to the next occurrence of a single.html template in the lookup (#4).

Example: my-second-post.md

{{< code file=“content/posts/my-second-post.md” copy=“false” >}}

title: My Second Post
date: 2017-02-21
description: This is my second post.
type: review
layout: reviewarticle

{{< /code >}}

Here is the way Hugo traverses the single-page lookup order for my-second-post.md:

  1. /layouts/review/reviewarticle.html

    BREAK
  2. /layouts/posts/reviewarticle.html
  3. /layouts/review/single.html
  4. /layouts/posts/single.html
  5. /layouts/_default/single.html
  6. /themes/<THEME>/layouts/review/reviewarticle.html
  7. /themes/<THEME>/layouts/posts/reviewarticle.html
  8. /themes/<THEME>/layouts/review/single.html
  9. /themes/<THEME>/layouts/posts/single.html
  10. /themes/<THEME>/layouts/_default/single.html

The front matter in my-second-post.md specifies the content type (i.e. review) as well as the layout (i.e. reviewarticle). Hugo finds the layout it needs at the top level of the lookup (#1) and does not continue to search through the other templates.

{{% note “Type and not Types” %}}
Notice that the directory for the template for my-second-post.md is review and not reviews. This is because type is always singular when defined in front matter.
{{% /note%}}

Example: my-first-event.md

{{< code file=“content/events/my-first-event.md” copy=“false” >}}

title: My First
date: 2017-02-21
description: This is an upcoming event…

{{< /code >}}

Here is the way Hugo traverses the single-page lookup order for my-first-event.md:

  1. /layouts/UNSPECIFIED/UNSPECIFIED.html
  2. /layouts/events/UNSPECIFIED.html
  3. /layouts/UNSPECIFIED/single.html
  4. /layouts/events/single.html
  5. /layouts/_default/single.html

    BREAK
  6. /themes/<THEME>/layouts/UNSPECIFIED/UNSPECIFIED.html
  7. /themes/<THEME>/layouts/events/UNSPECIFIED.html
  8. /themes/<THEME>/layouts/UNSPECIFIED/single.html
  9. /themes/<THEME>/layouts/events/single.html
  10. /themes/<THEME>/layouts/_default/single.html

{{% note %}}
my-first-event.md is significant because it demonstrates the role of the lookup order in Hugo themes. Both the root project directory and the mytheme themes directory have a file at _default/single.html. Understanding this order allows you to customize Hugo themes by creating template files with identical names in your project directory that step in front of theme template files in the lookup. This allows you to customize the look and feel of your website while maintaining compatibility with the theme’s upstream.
{{% /note %}}

Custom Output Formats

This page describes how to properly configure your site with the media types and output formats, as well as where to create your templates for your custom outputs.

Media Types

A media type (also known as MIME type and content type) is a two-part identifier for file formats and format contents transmitted on the Internet.

This is the full set of built-in media types in Hugo:

{{< datatable “media” “types” “type” “suffix” >}}

Note:

  • It is possible to add custom media types or change the defaults; e.g., if you want to change the suffix for text/html to asp.
  • The Suffix is the value that will be used for URLs and filenames for that media type in Hugo.
  • The Type is the identifier that must be used when defining new/custom Output Formats (see below).
  • The full set of media types will be registered in Hugo’s built-in development server to make sure they are recognized by the browser.

To add or modify a media type, define it in a mediaTypes section in your site configuration, either for all sites or for a given language.

Example in config.toml:

[mediaTypes]
  [mediaTypes."text/enriched"]
  suffix = "enr"
  [mediaTypes."text/html"]
  suffix = "asp"

The above example adds one new media type, text/enriched, and changes the suffix for the built-in text/html media type.

Output Formats

Given a media type and some additional configuration, you get an Output Format:

This is the full set of Hugo’s built-in output formats:

{{< datatable “output” “formats” “name” “mediaType” “path” “baseName” “rel” “protocol” “isPlainText” “isHTML” “noUgly”>}}

  • A page can be output in as many output formats as you want, and you can have an infinite amount of output formats defined as long as they resolve to a unique path on the file system. In the above table, the best example of this is AMP vs. HTML. AMP has the value amp for Path so it doesn’t overwrite the HTML version; e.g. we can now have both /index.html and /amp/index.html.
  • The MediaType must match the Type of an already defined media type.
  • You can define new output formats or redefine built-in output formats; e.g., if you want to put AMP pages in a different path.

To add or modify an output format, define it in an outputFormats section in your site’s configuration file, either for all sites or for a given language.

[outputFormats.MyEnrichedFormat]
mediaType = "text/enriched"
baseName = "myindex"
isPlainText = true
protocol = "bep://"

The above example is fictional, but if used for the homepage on a site with baseURL http://example.org, it will produce a plain text homepage with the URL bep://example.org/myindex.enr.

Configure Output Formats

The following is the full list of configuration options for output formats and their default values:

name
the output format identifier. This is used to define what output format(s) you want for your pages.
mediaType
this must match the Type of a defined media type.
path
sub path to save the output files.
baseName
the base filename for the list filenames (homepage, etc.). Default: index.
rel
can be used to create rel values in link tags. Default: alternate.
protocol
will replace the “http://” or “https://” in your baseURL for this output format.
isPlainText
use Go’s plain text templates parser for the templates. Default: false.
isHTML
used in situations only relevant for HTML-type formats; e.g., page aliases.
noUgly
used to turn off ugly URLs If uglyURLs is set to true in your site. Default: false.
notAlternative
enable if it doesn’t make sense to include this format in an AlternativeOutputFormats format listing on Page (e.g., with CSS). Note that we use the term alternative and not alternate here, as it does not necessarily replace the other format. Default: false.

Output Formats for Pages

A Page in Hugo can be rendered to multiple representations on the file system. By default, all pages will render as HTML with some of them also as RSS (homepage, sections, etc.).

This can be changed by defining an outputs list of output formats in either the Page front matter or in the site configuration (either for all sites or per language).

Example from site config.toml:

[outputs]
  home = ["HTML", "AMP", "RSS"]
  page = ["HTML"]

Example from site config.yml:

outputs:
  home: ["HTML", "AMP", "RSS"]
  page: ["HTML"]
  • The output definition is per Page Kind (i.e, page, home, section, taxonomy, or taxonomyTerm).
  • The names used must match the Name of a defined Output Format.
  • Any Kind without a definition will default to HTML.
  • These can be overridden per Page in the front matter of content files.
  • Output formats are case insensitive.

The following is an example of YAML front matter in a content file that defines output formats for the rendered Page:

---
date: "2016-03-19"
outputs:
- html
- amp
- json
---

Link to Output Formats

Each Page has both an .OutputFormats (all formats, including the current) and an .AlternativeOutputFormats variable, the latter of which is useful for creating a link rel list in your site’s <head>:

{{ range .AlternativeOutputFormats -}}
<link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}">
{{ end -}}

Note that .Permalink and .RelPermalink on Page will return the first output format defined for that page (usually HTML if nothing else is defined).

This is how you link to a given output format:

{{ with  .OutputFormats.Get "json" -}}
<a href="{{ .Permalink }}">{{ .Name }}</a>
{{- end }}

From content files, you can use the ref or relref shortcodes:

[Neat]({{</* ref "blog/neat.md" "amp" */>}})
[Who]({{</* relref "about.md#who" "amp" */>}})

Templates for Your Output Formats

A new output format needs a corresponding template in order to render anything useful.

{{% note %}}
The key distinction for Hugo versions 0.20 and newer is that Hugo looks at an output format’s Name and MediaType’s Suffix when choosing the template used to render a given Page.
{{% /note %}}

The following table shows examples of different output formats, the suffix used, and Hugo’s respective template lookup order. All of the examples in the table can:

{{< datatable “output” “layouts” “Example” “OutputFormat” “Suffix” “Template Lookup Order” >}}

Hugo will now also detect the media type and output format of partials, if possible, and use that information to decide if the partial should be parsed as a plain text template or not.

Hugo will look for the name given, so you can name it whatever you want. But if you want it treated as plain text, you should use the file suffix and, if needed, the name of the Output Format. The pattern is as follows:

[partial name].[OutputFormat].[suffix]

The partial below is a plain text template (Outpuf Format is CSV, and since this is the only output format with the suffix csv, we don’t need to include the Output Format’s Name):

{{ partial "mytextpartial.csv" . }}

Base Templates and Blocks

The block keyword allows you to define the outer shell of your pages’ one or more master template(s) and then fill in or override portions as necessary.

Base Template Lookup Order

The lookup order for base templates is as follows:

  1. /layouts/section/<TYPE>-baseof.html
  2. /themes/<THEME>/layouts/section/<TYPE>-baseof.html
  3. /layouts/<TYPE>/baseof.html
  4. /themes/<THEME>/layouts/<TYPE>/baseof.html
  5. /layouts/section/baseof.html
  6. /themes/<THEME>/layouts/section/baseof.html
  7. /layouts/_default/post-baseof.html
  8. /themes/<THEME>/layouts/_default/post-baseof.html
  9. /layouts/_default/baseof.html
  10. /themes/<THEME>/layouts/_default/baseof.html

Variables are denoted by capitalized text set within <>. Note that Hugo’s default behavior is for type to inherit from section unless otherwise specified.

Example Base Template Lookup Order

As an example, let’s assume your site is using a theme called “mytheme” when rendering the section list for a post section. Hugo picks layout/section/post.html as the template for rendering the section. The {{define}} block in this template tells Hugo that the template is an extension of a base template.

Here is the lookup order for the post base template:

  1. /layouts/section/post-baseof.html
  2. /themes/mytheme/layouts/section/post-baseof.html
  3. /layouts/post/baseof.html
  4. /themes/mytheme/layouts/post/baseof.html
  5. /layouts/section/baseof.html
  6. /themes/mytheme/layouts/section/baseof.html
  7. /layouts/_default/post-baseof.html
  8. /themes/mytheme/layouts/_default/post-baseof.html
  9. /layouts/_default/baseof.html
  10. /themes/mytheme/layouts/_default/baseof.html

Define the Base Template

The following defines a simple base template at _default/baseof.html. As a default template, it is the shell from which all your pages will be rendered unless you specify another *baseof.html closer to the beginning of the lookup order.

{{< code file=“layouts/_default/baseof.html” download=“baseof.html” >}}

{{ block "title" . }} <!-- Blocks may include default content. --> {{ .Site.Title }} {{ end }} {{ block "main" . }} {{ end }} {{ block "footer" . }} {{ end }} {{< /code >}}

Override the Base Template

From the above base template, you can define a default list template. The default list template will inherit all of the code defined above and can then implement its own "main" block from:

{{< code file=“layouts/_default/list.html” download=“list.html” >}}
{{ define “main” }}

Posts

{{ range .Data.Pages }}

{{ .Title }}

{{ .Content }}
{{ end }} {{ end }} {{< /code >}}

This replaces the contents of our (basically empty) “main” block with something useful for the list template. In this case, we didn’t define a "title" block, so the contents from our base template remain unchanged in lists.

{{% warning %}}
Code that you put outside the block definitions can break your layout. This even includes HTML comments. For example:

<!-- Seemingly harmless HTML comment..that will break your layout at build -->
{{ define "main" }}
...your code here
{{ end }}

See this thread from the Hugo discussion forums.
{{% /warning %}}

The following shows how you can override both the "main" and "title" block areas from the base template with code unique to your default single page template:

{{< code file=“layouts/_default/single.html” download=“single.html” >}}
{{ define “title” }}

{{ .Title }} – {{ .Site.Title }}
{{ end }}
{{ define “main” }}

{{ .Title }}

{{ .Content }} {{ end }} {{< /code >}}

Lists of Content in Hugo

What is a List Page Template?

A list page template is a template used to render multiple pieces of content in a single HTML page. The exception to this rule is the homepage, which is still a list but has its own dedicated template.

Hugo uses the term list in its truest sense; i.e. a sequential arrangement of material, especially in alphabetical or numerical order. Hugo uses list templates on any output HTML page where content is traditionally listed:

The idea of a list page comes from the hierarchical mental model of the web and is best demonstrated visually:

Image demonstrating a hierarchical website sitemap.

List Defaults

Default Templates

Since section lists and taxonomy lists (N.B., not taxonomy terms lists) are both lists with regards to their templates, both have the same terminating default of _default/list.html or themes/<THEME>/layouts/_default/list.html in their lookup order. In addition, both section lists and taxonomy lists have their own default list templates in _default:

Default Section Templates

  1. layouts/_default/section.html
  2. layouts/_default/list.html

Default Taxonomy List Templates

  1. layouts/_default/taxonomy.html
  2. themes/<THEME>/layouts/_default/taxonomy.html

Add Content and Front Matter to List Pages

Since v0.18, everything in Hugo is a Page. This means list pages and the homepage can have associated content files (i.e. _index.md) that contain page metadata (i.e., front matter) and content.

This new model allows you to include list-specific front matter via .Params and also means that list templates (e.g., layouts/_default/list.html) have access to all page variables.

{{% note %}}
It is important to note that all _index.md content files will render according to a list template and not according to a single page template.
{{% /note %}}

Example Project Directory

The following is an example of a typical Hugo project directory’s content:

.
...
├── content
|   ├── post
|   |   ├── _index.md
|   |   ├── post-01.md
|   |   └── post-02.md
|   └── quote
|   |   ├── quote-01.md
|   |   └── quote-02.md
...

Using the above example, let’s assume you have the following in content/post/_index.md:

{{< code file=“content/post/_index.md” >}}

title: My Golang Journey
date: 2017-03-23
publishdate: 2017-03-24

I decided to start learning Golang in March 2017.

Follow my journey through this new blog.
{{< /code >}}

You can now access this _index.md’s’ content in your list template:

{{< code file=“layouts/_default/list.html” download=“list.html” >}}
{{ define “main” }}

{{.Title}}

{{.Content}}
{{ end }} {{< /code >}}

This above will output the following HTML:

{{< code file=“example.com/post/index.html” copy=“false” >}}

My Golang Journey

I decided to start learning Golang in March 2017.

Follow my journey through this new blog.

{{< /code >}}

List Pages Without _index.md

You do not have to create an _index.md file for every list page (i.e. section, taxonomy, taxonomy terms, etc) or the homepage. If Hugo does not find an _index.md within the respective content section when rendering a list template, the page will be created but with no {{.Content}} and only the default values for .Title etc.

Using this same layouts/_default/list.html template and applying it to the the quotes section above will render the following output. Note that quotes does not have an _index.md file to pull from:

{{< code file=“example.com/quote/index.html” copy=“false” >}}

Quotes

{{< /code >}}

{{% note %}}
The default behavior of Hugo is to pluralize list titles; hence the inflection of the quote section to “Quotes” when called with the .Title page variable. You can change this via the pluralizeListTitles directive in your site configuration.
{{% /note %}}

Example List Templates

Section Template

This list template has been modified slightly from a template originally used in spf13.com. It makes use of partial templates for the chrome of the rendered page rather than using a base template The examples that follow also use the content view templates li.html or summary.html.

{{< code file=“layouts/section/post.html” >}}
{{ partial “header.html” . }}
{{ partial “subheader.html” . }}

{{ .Title }}

    {{ range .Data.Pages }} {{ .Render "li"}} {{ end }}
{{ partial "footer.html" . }} {{< /code >}}

Taxonomy Template

{{< code file=“layouts/_default/taxonomies.html” download=“taxonomies.html” >}}
{{ define “main” }}

{{ .Title }}

{{ range .Data.Pages }} {{ .Render "summary"}} {{ end }}
{{ end }} {{< /code >}}

Order Content

Hugo lists render the content based on metadata you provide in front matter. In addition to sane defaults, Hugo also ships with multiple methods to make quick work of ordering content inside list templates:

Default: Weight > Date > LinkTitle > FilePath

{{< code file=“layouts/partials/default-order.html” >}}

    {{ range .Data.Pages }}
  • {{ .Title }}

  • {{ end }}
{{< /code >}}

By Weight

{{< code file=“layouts/partials/by-weight.html” >}}

    {{ range .Data.Pages.ByWeight }}
  • {{ .Title }}

  • {{ end }}
{{< /code >}}

By Date

{{< code file=“layouts/partials/by-date.html” >}}

    {{ range .Data.Pages.ByDate }}
  • {{ .Title }}

  • {{ end }}
{{< /code >}}

By Publish Date

{{< code file=“layouts/partials/by-publish-date.html” >}}

    {{ range .Data.Pages.ByPublishDate }}
  • {{ .Title }}

  • {{ end }}
{{< /code >}}

By Expiration Date

{{< code file=“layouts/partials/by-expiry-date.html” >}}

    {{ range .Data.Pages.ByExpiryDate }}
  • {{ .Title }}

  • {{ end }}
{{< /code >}}

By Last Modified Date

{{< code file=“layouts/partials/by-last-mod.html” >}}

    {{ range .Data.Pages.ByLastmod }}
  • {{ .Title }}

  • {{ end }}
{{< /code >}}

By Length

{{< code file=“layouts/partials/by-length.html” >}}

    {{ range .Data.Pages.ByLength }}
  • {{ .Title }}

  • {{ end }}
{{< /code >}}

By Title

{{< code file=“layouts/partials/by-title.html” >}}

    {{ range .Data.Pages.ByTitle }}
  • {{ .Title }}

  • {{ end }}
{{< /code >}}

By Link Title

{{< code file=“layouts/partials/by-link-title.html” >}}

    {{ range .Data.Pages.ByLinkTitle }}
  • {{ .LinkTitle }}

  • {{ end }}
{{< /code >}}

By Parameter

Order based on the specified front matter parameter. Content that does not have the specified front matter field will use the site’s .Site.Params default. If the parameter is not found at all in some entries, those entries will appear together at the end of the ordering.

{{< code file=“layouts/partials/by-rating.html” >}}

{{ range (.Data.Pages.ByParam “rating”) }}

{{ end }}
{{< /code >}}

If the targeted front matter field is nested beneath another field, you can access the field using dot notation.

{{< code file=“layouts/partials/by-nested-param.html” >}}
{{ range (.Data.Pages.ByParam “author.last_name”) }}

{{ end }}
{{< /code >}}

Reverse Order

Reversing order can be applied to any of the above methods. The following uses ByDate as an example:

{{< code file=“layouts/partials/by-date-reverse.html” >}}

    {{ range .Data.Pages.ByDate.Reverse }}
  • {{ .Title }}

  • {{ end }}
{{< /code >}}

Group Content

Hugo provides some functions for grouping pages by Section, Type, Date, etc.

By Page Field

{{< code file=“layouts/partials/by-page-field.html” >}}

{{ range .Data.Pages.GroupBy “Section” }}

{{ .Key }}

    {{ range .Pages }}
  • {{ .Title }}
    {{ .Date.Format "Mon, Jan 2, 2006" }}
  • {{ end }}
{{ end }} {{< /code >}}

In the above example, you may want {{.Title}} to point the title field you have added to your _index.md file instead. You can access this value using the .GetPage function:

{{< code file=“layouts/partials/by-page-field.html” >}}

{{ range .Data.Pages.GroupBy “Section” }}

{{ with $.Site.GetPage “section” .Key }}

{{.Title}}

{{ else }}

{{ .Key | title }}

{{ end }}
    {{ range .Pages }}
  • {{ .Title }}
    {{ .Date.Format "Mon, Jan 2, 2006" }}
  • {{ end }}
{{ end }} {{< /code >}}

By Date

{{< code file=“layouts/partials/by-page-date.html” >}}

{{ range .Data.Pages.GroupByDate “2006-01” }}

{{ .Key }}

    {{ range .Pages }}
  • {{ .Title }}
    {{ .Date.Format "Mon, Jan 2, 2006" }}
  • {{ end }}
{{ end }} {{< /code >}}

By Publish Date

{{< code file=“layouts/partials/by-page-publish-date.html” >}}

{{ range .Data.Pages.GroupByPublishDate “2006-01” }}

{{ .Key }}

    {{ range .Pages }}
  • {{ .Title }}
    {{ .PublishDate.Format "Mon, Jan 2, 2006" }}
  • {{ end }}
{{ end }} {{< /code >}}

By Page Parameter

{{< code file=“layouts/partials/by-page-param.html” >}}

{{ range .Data.Pages.GroupByParam “param_key” }}

{{ .Key }}

    {{ range .Pages }}
  • {{ .Title }}
    {{ .Date.Format "Mon, Jan 2, 2006" }}
  • {{ end }}
{{ end }} {{< /code >}}

By Page Parameter in Date Format

The following template takes grouping by date a step further and uses Golang’s layout string. See the Format function for more examples of how to use Golang’s layout string to format dates in Hugo.

{{< code file=“layouts/partials/by-page-param-as-date.html” >}}

{{ range .Data.Pages.GroupByParamDate “param_key” “2006-01” }}

{{ .Key }}

    {{ range .Pages }}
  • {{ .Title }}
    {{ .Date.Format "Mon, Jan 2, 2006" }}
  • {{ end }}
{{ end }} {{< /code >}}

Reverse Key Order

Ordering of groups is performed by keys in alphanumeric order (A–Z, 1–100) and in reverse chronological order (i.e., with the newest first) for dates.

While these are logical defaults, they are not always the desired order. There are two different syntaxes to change Hugo’s default ordering for groups, both of which work the same way.

1. Adding the Reverse Method

{{ range (.Data.Pages.GroupBy "Section").Reverse }}
{{ range (.Data.Pages.GroupByDate "2006-01").Reverse }}

2. Providing the Alternate Direction

{{ range .Data.Pages.GroupByDate "2006-01" "asc" }}
{{ range .Data.Pages.GroupBy "Section" "desc" }}

Order Within Groups

Because Grouping returns a {{.Key}} and a slice of pages, all of the ordering methods listed above are available.

Here is the ordering for the example that follows:

  1. Content is grouped by month according to the date field in front matter.
  2. Groups are listed in ascending order (i.e., the oldest groups first)
  3. Pages within each respective group are ordered alphabetically according to the title.

{{< code file=“layouts/partials/by-group-by-page.html” >}}
{{ range .Data.Pages.GroupByDate “2006-01” “asc” }}

{{ .Key }}

    {{ range .Pages.ByTitle }}
  • {{ .Title }}
    {{ .Date.Format "Mon, Jan 2, 2006" }}
  • {{ end }}
{{ end }} {{< /code >}}

Filter and Limiting Lists

Sometimes you only want to list a subset of the available content. A common is to only display “Posts” on blog’s homepage. You can accomplish this with the where function.

where

where works in a similar manner to the where keyword in SQL. It selects all elements of the array or slice that match the provided field and value. where takes three arguments:

  1. array or slice of maps or structs
  2. key or field name
  3. match value

{{< code file=“layouts/_default/.html” >}}
{{ range where .Data.Pages “Section” “post” }}
{{ .Content }}
{{ end }}
{{< /code >}}

You can see more examples in the functions documentation for where.

first

first works in a similar manner to the limit keyword in SQL. It reduces the array to only the first N elements. It takes the array and number of elements as input. first takes two arguments:

  1. array or slice of maps or structs
  2. number of elements

{{< code file=“layout/_default/section.html” >}}
{{ range first 10 .Data.Pages }}
{{ .Render “summary” }}
{{ end }}
{{< /code >}}

first and where Together

Using first and where together can be very powerful:

{{< code file=“first-and-where-together.html” >}}

{{ range first 5 (where .Data.Pages “Section” “post”).ByTitle }}
{{ .Content }}
{{ end }}
{{< /code >}}

Ordere and Grouping Hugo Lists

In Hugo, A list template is any template that will be used to render multiple pieces of content in a single HTML page.

Example List Templates

Section Template

This list template is used for spf13.com. It makes use of partial templates. All examples use a view called either “li” or “summary.”

{{< code file=“layouts/section/post.html” >}}
{{ partial “header.html” . }}
{{ partial “subheader.html” . }}

{{ .Title }}

    {{ range .Data.Pages }} {{ .Render "li"}} {{ end }}
{{ partial "footer.html" . }} {{< /code >}}

Taxonomy Template

{{< code file=“layouts/_default/taxonomies.html” download=“taxonomies.html” >}}
{{ define “main” }}

{{ .Title }}

{{ range .Data.Pages }} {{ .Render "summary"}} {{ end }}
{{ end }} {{< /code >}}

Order Content

Hugo lists render the content based on metadata provided in the front matter

Here are a variety of different ways you can order the content items in
your list templates:

Default: Weight > Date

{{< code file=“layouts/partials/order-default.html” >}}

    {{ range .Data.Pages }}
  • {{ .Title }}

  • {{ end }}
{{< /code >}}

By Weight

{{< code file=“layouts/partials/by-weight.html” >}}
{{ range .Data.Pages.ByWeight }}


  • {{ .Title }}
    {{ .Date.Format “Mon, Jan 2, 2006” }}


  • {{ end }}
    {{< /code >}}

    By Date

    {{< code file=“layouts/partials/by-date.html” >}}
    {{ range .Data.Pages.ByDate }}


  • {{ .Title }}
    {{ .Date.Format “Mon, Jan 2, 2006” }}


  • {{ end }}
    {{< /code >}}

    By Publish Date

    {{< code file=“layouts/partials/by-publish-date.html” >}}
    {{ range .Data.Pages.ByPublishDate }}


  • {{ .Title }}
    {{ .PublishDate.Format “Mon, Jan 2, 2006” }}


  • {{ end }}
    {{< /code >}}

    By Expiration Date

    {{< code file=“layouts/partials/by-expiry-date.html” >}}
    {{ range .Data.Pages.ByExpiryDate }}


  • {{ .Title }}
    {{ .ExpiryDate.Format “Mon, Jan 2, 2006” }}


  • {{ end }}
    {{< /code >}}

    By Last Modified Date

    {{< code file=“layouts/partials/by-last-mod.html” >}}
    {{ range .Data.Pages.ByLastmod }}


  • {{ .Title }}
    {{ .Date.Format “Mon, Jan 2, 2006” }}


  • {{ end }}
    {{< /code >}}

    By Length

    {{< code file=“layouts/partials/by-length.html” >}}
    {{ range .Data.Pages.ByLength }}


  • {{ .Title }}
    {{ .Date.Format “Mon, Jan 2, 2006” }}


  • {{ end }}
    {{< /code >}}

    By Title

    {{< code file=“layouts/partials/by-title.html” >}}
    {{ range .Data.Pages.ByTitle }}


  • {{ .Title }}
    {{ .Date.Format “Mon, Jan 2, 2006” }}


  • {{ end }}
    {{< /code >}}

    By Link Title

    {{< code file=“layouts/partials/by-link-title.html” >}}
    {{ range .Data.Pages.ByLinkTitle }}


  • {{ .LinkTitle }}
    {{ .Date.Format “Mon, Jan 2, 2006” }}


  • {{ end }}
    {{< /code >}}

    By Parameter

    Order based on the specified front matter parameter. Content that does not have the specified front matter field will use the site’s .Site.Params default. If the parameter is not found at all in some entries, those entries will appear together at the end of the ordering.

    The below example sorts a list of posts by their rating.

    {{< code file=“layouts/partials/by-rating.html” >}}
    {{ range (.Data.Pages.ByParam “rating”) }}

    {{ end }}
    {{< /code >}}

    If the front matter field of interest is nested beneath another field, you can
    also get it:

    {{< code file=“layouts/partials/by-nested-param.html” >}}
    {{ range (.Data.Pages.ByParam “author.last_name”) }}

    {{ end }}
    {{< /code >}}

    Reverse Order

    Reversing order can be applied to any of the above methods. The following uses ByDate as an example:

    {{< code file=“layouts/partials/by-date-reverse.html” >}}
    {{ range .Data.Pages.ByDate.Reverse }}

  • {{ .Title }}
    {{ .Date.Format "Mon, Jan 2, 2006" }}
  • {{ end }} {{< /code >}}

    Group Content

    Hugo provides some functions for grouping pages by Section, Type, Date, etc.

    By Page Field

    {{< code file=“layouts/partials/by-page-field.html” >}}
    {{ range .Data.Pages.GroupBy “Section” }}

    {{ .Key }}

      {{ range .Pages }}
    • {{ .Title }}
      {{ .Date.Format "Mon, Jan 2, 2006" }}
    • {{ end }}
    {{ end }} {{< /code >}}

    By Page date

    {{< code file=“layouts/partials/by-page-date.html” >}}
    {{ range .Data.Pages.GroupByDate “2006-01” }}

    {{ .Key }}

      {{ range .Pages }}
    • {{ .Title }}
      {{ .Date.Format "Mon, Jan 2, 2006" }}
    • {{ end }}
    {{ end }} {{< /code >}}

    By Page publish date

    {{< code file=“layouts/partials/by-page-publish-date.html” >}}
    {{ range .Data.Pages.GroupByPublishDate “2006-01” }}

    {{ .Key }}

      {{ range .Pages }}
    • {{ .Title }}
      {{ .PublishDate.Format "Mon, Jan 2, 2006" }}
    • {{ end }}
    {{ end }} {{< /code >}}

    By Page Param

    {{< code file=“layouts/partials/by-page-param.html” >}}
    {{ range .Data.Pages.GroupByParam “param_key” }}

    {{ .Key }}

      {{ range .Pages }}
    • {{ .Title }}
      {{ .Date.Format "Mon, Jan 2, 2006" }}
    • {{ end }}
    {{ end }} {{< /code >}}

    By Page Param in Date Format

    {{< code file=“layouts/partials/by-page-param-as-date.html” >}}
    {{ range .Data.Pages.GroupByParamDate “param_key” “2006-01” }}

    {{ .Key }}

      {{ range .Pages }}
    • {{ .Title }}
      {{ .Date.Format "Mon, Jan 2, 2006" }}
    • {{ end }}
    {{ end }} {{< /code >}}

    Reverse Key Order

    The ordering of the groups is performed by keys in alphanumeric order (A–Z, 1–100) and in reverse chronological order (newest first) for dates.

    While these are logical defaults, they are not always the desired order. There are two different syntaxes to change the order, both of which work the same way. You can use your preferred syntax.

    Reverse Method

    {{ range (.Data.Pages.GroupBy "Section").Reverse }}
    
    {{ range (.Data.Pages.GroupByDate "2006-01").Reverse }}
    

    Provide the Alternate Direction

    {{ range .Data.Pages.GroupByDate "2006-01" "asc" }}
    
    {{ range .Data.Pages.GroupBy "Section" "desc" }}
    

    Order Within Groups

    Because Grouping returns a {{.Key}} and a slice of pages, all of the ordering methods listed above are available.

    In the following example, groups are ordered chronologically and then content
    within each group is ordered alphabetically by title.

    {{< code file=“layouts/partials/by-group-by-page.html” >}}
    {{ range .Data.Pages.GroupByDate “2006-01” “asc” }}

    {{ .Key }}

      {{ range .Pages.ByTitle }}
    • {{ .Title }}
      {{ .Date.Format "Mon, Jan 2, 2006" }}
    • {{ end }}
    {{ end }} {{< /code >}}

    Filter and Limiting Lists

    Sometimes you only want to list a subset of the available content. A common request is to only display “Posts” on the homepage. You can accomplish this with the where function.

    where

    where works in a similar manner to the where keyword in SQL. It selects all elements of the array or slice that match the provided field and value. where takes three arguments:

    1. array or a slice of maps or structs
    2. key or field name
    3. match value

    {{< code file=“layouts/_default/.html” >}}
    {{ range where .Data.Pages “Section” “post” }}
    {{ .Content }}
    {{ end }}
    {{< /code >}}

    first

    first works in a similar manner to the limit keyword in SQL. It reduces the array to only the first N elements. It takes the array and number of elements as input. first takes two arguments:

    1. array or slice of maps or structs
    2. number of elements

    {{< code file=“layout/_default/section.html” >}}
    {{ range first 10 .Data.Pages }}
    {{ .Render “summary” }}
    {{ end }}
    {{< /code >}}

    first and where Together

    Using first and where together can be very powerful:

    {{< code file=“first-and-where-together.html” >}}
    {{ range first 5 (where .Data.Pages “Section” “post”) }}
    {{ .Content }}
    {{ end }}
    {{< /code >}}

    Homepage Template

    Homepage is a Page and therefore has all the page variables and site variables available for use.

    {{% note “The Only Required Template” %}}
    The homepage template is the only required template for building a site and therefore useful when bootstrapping a new site and template. It is also the only required template if you are developing a single-page website.
    {{% /note %}}

    Homepage Template Lookup Order

    The lookup order for the homepage template is as follows:

    1. /layouts/index.html
    2. /layouts/_default/list.html
    3. /themes/<THEME>/layouts/index.html
    4. /themes/<THEME>/layouts/_default/list.html

    Add Content and Front Matter to the Homepage

    The homepage, similar to other list pages in Hugo, accepts content and front matter from an _index.md file. This file should live at the root of your content folder (i.e., content/_index.md). You can then add body copy and metadata to your homepage the way you would any other content file.

    See the homepage template below or Content Organization for more information on the role of _index.md in adding content and front matter to list pages.

    .Data.Pages on the Homepage

    In addition to the standard page variables, the homepage template has access to all site content via .Data.Pages.

    Example Homepage Template

    The following is an example of a homepage template that uses partial, base templates, and a content file at content/_index.md to populate the {{.Title}} and {{Content}} page variables.

    {{< code file=“layouts/index.html” download=“index.html” >}}
    {{ define “main” }}



    {{.Title}}


    {{ with .Params.subtitle }}
    {{.}}
    {{ end }}



    {{.Content}}



    {{ range first 10 .Data.Pages }}
    {{ .Render “summary”}}
    {{ end }}


    {{ end }}
    {{< /code >}}

    Section Page Templates

    Add Content and Front Matter to Section Templates

    To effectively leverage section page templates, you should first understand Hugo’s content organization and, specifically, the purpose of _index.md for adding content and front matter to section and other list pages.

    Section Template Lookup Order

    The lookup order for section templates is as follows:

    1. /layouts/section/<SECTION>.html
    2. /layouts/<SECTION>/list.html
    3. /layouts/_default/section.html
    4. /layouts/_default/list.html
    5. /themes/<THEME>/layouts/section/<SECTION>.html
    6. /themes/<THEME>/layouts/<SECTION>/list.html
    7. /themes/<THEME>/layouts/_default/section.html
    8. /themes/<THEME>/layouts/_default/list.html

    .Site.GetPage with Sections

    Every Page in Hugo has a .Kind attribute. Kind can easily be combined with the where function in your templates to create kind-specific lists of content. This method is ideal for creating lists, but there are times where you may want to fetch just the index page of a single section via the section’s path.

    The .GetPage function looks up an index page of a given Kind and path.

    {{% note %}}
    .GetPage is not currently supported to grab single content files but may be supported in the future.
    {{% /note %}}

    You can call .Site.GetPage with two arguments: kind and kind value.

    These are the valid values for ‘kind’:

    1. home
    2. section
    3. taxonomy
    4. taxonomyTerm

    Example: Creating a Default Section Template

    {{< code file=“layouts/_default/section.html” download=“section.html” >}}
    {{ define “main” }}

    {{ .Content }}
      {{ range .Paginator.Pages }}
    • {{.Title}}
      {{ partial "summary.html" . }}
    • {{ end }}
    {{ partial "pagination.html" . }}
    {{ end }} {{< /code >}}

    Example: Using .Site.GetPage

    The .Site.GetPage example that follows assumes the following project directory structure:

    .
    └── content
        ├── blog
        │   ├── _index.md # "title: My Hugo Blog" in the front matter
        │   ├── post-1.md
        │   ├── post-2.md
        │   └── post-3.md
        └── events #Note there is no _index.md file in "events"
            ├── event-1.md
            └── event-2.md
    

    .Site.GetPage will return nil if no _index.md page is found. Therefore, if content/blog/_index.md does not exist, the template will output the section name:

    <h1>{{ with .Site.GetPage "section" "blog" }}{{ .Title }}{{ end }}</h1>
    

    Since blog has a section index page with front matter at content/blog/_index.md, the above code will return the following result:

    <h1>My Hugo Blog</h1>
    

    If we try the same code with the events section, however, Hugo will default to the section title because there is no content/events/_index.md from which to pull content and front matter:

    <h1>{{ with .Site.GetPage "section" "events" }}{{ .Title }}{{ end }}</h1>
    

    Which then returns the following:

    <h1>Events</h1>
    

    Taxonomy Templates

    Hugo includes support for user-defined groupings of content called taxonomies. Taxonomies are classifications that demonstrate logical relationships between content. See Taxonomies under Content Management if you are unfamiliar with how Hugo leverages this powerful feature.

    Hugo provides multiple ways to use taxonomies throughout your project templates:

    Taxonomy List Templates

    Taxonomy list page templates are lists and therefore have all the variables and methods available to list pages.

    Taxonomy List Template Lookup Order

    A taxonomy will be rendered at /PLURAL/TERM/ (e.g., http://spf13.com/topics/golang/) according to the following lookup order:

    1. /layouts/taxonomy/<SINGULAR>.html
    2. /layouts/_default/taxonomy.html
    3. /layouts/_default/list.html
    4. /themes/<THEME>/layouts/taxonomy/<SINGULAR>.html
    5. /themes/<THEME>/layouts/_default/taxonomy.html
    6. /themes/<THEME>/layouts/_default/list.html

    Taxonomy Terms Template

    Taxonomy Terms Templates Lookup Order

    A taxonomy terms page will be rendered at example.com/<PLURALTAXONOMYNAME>/ (e.g., http://spf13.com/topics/) according to the following lookup order:

    1. /layouts/taxonomy/<SINGULAR>.terms.html
    2. /layouts/_default/terms.html
    3. /themes/<THEME>/layouts/taxonomy/<SINGULAR>.terms.html
    4. /themes/<THEME>/layouts/_default/terms.html

    {{% warning “The Taxonomy Terms Template has a Unique Lookup Order” %}}
    If Hugo does not find a terms template in layout/ or /themes/<THEME>/layouts/, Hugo will not render a taxonomy terms page.
    {{% /warning %}}

    Hugo makes a set of values and methods available on the various Taxonomy structures.

    Taxonomy Methods

    A Taxonomy is a map[string]WeightedPages.

    .Get(term)
    Returns the WeightedPages for a term.
    .Count(term)
    The number of pieces of content assigned to this term.
    .Alphabetical
    Returns an OrderedTaxonomy (slice) ordered by Term.
    .ByCount
    Returns an OrderedTaxonomy (slice) ordered by number of entries.

    OrderedTaxonomy

    Since Maps are unordered, an OrderedTaxonomy is a special structure that has a defined order.

    []struct {
        Name          string
        WeightedPages WeightedPages
    }
    

    Each element of the slice has:

    .Term
    The Term used.
    .WeightedPages
    A slice of Weighted Pages.
    .Count
    The number of pieces of content assigned to this term.
    .Pages
    All Pages assigned to this term. All list methods are available to this.

    WeightedPages

    WeightedPages is simply a slice of WeightedPage.

    type WeightedPages []WeightedPage
    
    .Count(term)
    The number of pieces of content assigned to this term.
    .Pages
    Returns a slice of pages, which then can be ordered using any of the list methods.

    Order Taxonomies

    Taxonomies can be ordered by either alphabetical key or by the number of content pieces assigned to that key.

    Order Alphabetically Example

    <ul>
      {{ $data := .Data }}
      {{ range $key, $value := .Data.Taxonomy.Alphabetical }}
      <li><a href="{{ $.Site.LanguagePrefix }}/{{ $data.Plural }}/{{ $value.Name | urlize }}"> {{ $value.Name }} </a> {{ $value.Count }} </li>
      {{ end }}
    </ul>
    

    Order by Popularity Example

    <ul>
      {{ $data := .Data }}
      {{ range $key, $value := .Data.Taxonomy.ByCount }}
      <li><a href="{{ $.Site.LanguagePrefix }}/{{ $data.Plural }}/{{ $value.Name | urlize }}"> {{ $value.Name }} </a> {{ $value.Count }} </li>
      {{ end }}
    </ul>
    

    Order Content within Taxonomies

    Hugo uses both date and weight to order content within taxonomies.

    Each piece of content in Hugo can optionally be assigned a date. It can also be assigned a weight for each taxonomy it is assigned to.

    When iterating over content within taxonomies, the default sort is the same as that used for section and list pages first by weight then by date. This means that if the weights for two pieces of content are the same, than the more recent content will be displayed first. The default weight for any piece of content is 0.

    Assign Weight

    Content can be assigned weight for each taxonomy that it’s assigned to.

    +++
    tags = [ "a", "b", "c" ]
    tags_weight = 22
    categories = ["d"]
    title = "foo"
    categories_weight = 44
    +++
    Front Matter with weighted tags and categories
    

    The convention is taxonomyname_weight.

    In the above example, this piece of content has a weight of 22 which applies to the sorting when rendering the pages assigned to the “a”, “b” and “c” values of the ‘tag’ taxonomy.

    It has also been assigned the weight of 44 when rendering the ‘d’ category.

    With this the same piece of content can appear in different positions in different taxonomies.

    Currently taxonomies only support the default ordering of content which is weight -> date.

    There are two different templates that the use of taxonomies will require you to provide.

    Both templates are covered in detail in the templates section.

    A list template is any template that will be used to render multiple pieces of content in a single html page. This template will be used to generate all the automatically created taxonomy pages.

    A taxonomy terms template is a template used to
    generate the list of terms for a given template.

    There are four common ways you can display the data in your
    taxonomies in addition to the automatic taxonomy pages created by hugo
    using the list templates:

    1. For a given piece of content, you can list the terms attached
    2. For a given piece of content, you can list other content with the same
      term
    3. You can list all terms for a taxonomy
    4. You can list all taxonomies (with their terms)

    Display a Single Piece of Content’s Taxonomies

    Within your content templates, you may wish to display the taxonomies that piece of content is assigned to.

    Because we are leveraging the front matter system to define taxonomies for content, the taxonomies assigned to each content piece are located in the usual place (i.e., .Params.<TAXONOMYPLURAL>).

    Example: List Tags in a Single Page Template

    <ul id="tags">
      {{ range .Params.tags }}
        <li><a href="{{ "/tags/" | relLangURL }}{{ . | urlize }}">{{ . }}</a> </li>
      {{ end }}
    </ul>
    

    If you want to list taxonomies inline, you will have to take care of optional plural endings in the title (if multiple taxonomies), as well as commas. Let’s say we have a taxonomy “directors” such as directors: [ "Joel Coen", "Ethan Coen" ] in the TOML-format front matter.

    To list such taxonomies, use the following:

    Example: Comma-delimit Tags in a Single Page Template

    {{ if .Params.directors }}
      <strong>Director{{ if gt (len .Params.directors) 1 }}s{{ end }}:</strong>
      {{ range $index, $director := .Params.directors }}{{ if gt $index 0 }}, {{ end }}<a href="{{ "directors/" | relURL }}{{ . | urlize }}">{{ . }}</a>{{ end }}
    {{ end }}
    

    Alternatively, you may use the delimit template function as a shortcut if the taxonomies should just be listed with a separator. See {{< gh 2143 >}} on GitHub for discussion.

    List Content with the Same Taxonomy Term

    If you are using a taxonomy for something like a series of posts, you can list individual pages associated with the same taxonomy. This is also a quick and dirty method for showing related content:

    Example: Showing Content in Same Series

    <ul>
      {{ range .Site.Taxonomies.series.golang }}
        <li><a href="{{ .Page.RelPermalink }}">{{ .Page.Title }}</a></li>
      {{ end }}
    </ul>
    

    List All content in a Given taxonomy

    This would be very useful in a sidebar as “featured content”. You could even have different sections of “featured content” by assigning different terms to the content.

    Example: Grouping “Featured” Content

    <section id="menu">
        <ul>
            {{ range $key, $taxonomy := .Site.Taxonomies.featured }}
            <li> {{ $key }} </li>
            <ul>
                {{ range $taxonomy.Pages }}
                <li hugo-nav="{{ .RelPermalink}}"><a href="{{ .Permalink}}"> {{ .LinkTitle }} </a> </li>
                {{ end }}
            </ul>
            {{ end }}
        </ul>
    </section>
    

    Render a Site’s Taxonomies

    If you wish to display the list of all keys for your site’s taxonomy, you can retrieve them from the .Site variable available on every page.

    This may take the form of a tag cloud, a menu, or simply a list.

    The following example displays all terms in a site’s tags taxonomy:

    Example: List All Site Tags

    <ul id="all-tags">
      {{ range $name, $taxonomy := .Site.Taxonomies.tags }}
        <li><a href="{{ "/tags/" | relLangURL }}{{ $name | urlize }}">{{ $name }}</a></li>
      {{ end }}
    </ul>
    

    Example: List All Taxonomies, Terms, and Assigned Content

    This example will list all taxonomies and their terms, as well as all the content assigned to each of the terms.

    {{< code file=“layouts/partials/all-taxonomies.html” download=“all-taxonomies.html” download=“all-taxonomies.html” >}}

      {{ range $taxonomyname, $taxonomy := .Site.Taxonomies }}
    • {{ $taxonomyname }}
        {{ range $key, $value := $taxonomy }}
      • {{ $key }}
      • {{ end }}
    • {{ end }}
    {{< /code >}}

    .Site.GetPage for Taxonomies

    Because taxonomies are lists, the .GetPage function can be used to get all the pages associated with a particular taxonomy term using a terse syntax. The following ranges over the full list of tags on your site and links to each of the individual taxonomy pages for each term without having to use the more fragile URL construction of the “List All Site Tags” example above:

    {{< code file=“links-to-all-tags” >}}

      {{ range ($.Site.GetPage "taxonomyTerm" "tags").Pages }}
    • {{ .Title}}
    • {{ end }}
    {{< /code >}}

    Single Page Templates

    Single Page Template Lookup Order

    You can specify a content’s type and layout in a single content file’s front matter. However, you cannot specify section because this is determined based on file location (see content section).

    Hugo assumes your content section and content type are the same unless you tell Hugo otherwise by providing a type directly in the front matter of a content file. This is why #1 and #3 come before #2 and #4, respectively, in the following lookup order. Values in angle brackets (<>) are variable.

    1. /layouts/<TYPE>/<LAYOUT>.html
    2. /layouts/<SECTION>>/<LAYOUT>.html
    3. /layouts/<TYPE>/single.html
    4. /layouts/<SECTION>/single.html
    5. /layouts/_default/single.html
    6. /themes/<THEME>/layouts/<TYPE>/<LAYOUT>.html
    7. /themes/<THEME>/layouts/<SECTION>/<LAYOUT>.html
    8. /themes/<THEME>/layouts/<TYPE>/single.html
    9. /themes/<THEME>/layouts/<SECTION>/single.html
    10. /themes/<THEME>/layouts/_default/single.html

    Example Single Page Templates

    Content pages are of the type page and will therefore have all the page variables and site variables available to use in their templates.

    post/single.html

    This single page template makes use of Hugo base templates, the .Format function for dates, the .WordCount page variable, and ranges through the single content’s specific taxonomies. [with][] is also used to check whether the taxonomies are set in the front matter.

    {{< code file=“layouts/post/single.html” download=“single.html” >}}
    {{ define “main” }}

    {{ .Title }}

    {{ .Content }}
    {{ end }} {{< /code >}}

    To easily generate new instances of a content type (e.g., new .md files in a section like project/) with preconfigured front matter, use content archetypes.

    [with]: /functions/with/

    Content View Templates

    These alternative content views are especially useful in list templates.

    The following are common use cases for content views:

    • You want content of every type to be shown on the homepage but only with limited summary views.
    • You only want a bulleted list of your content on a [taxonomy list page][taxonomylists]. Views make this very straightforward by delegating the rendering of each different type of content to the content itself.

    Create a Content View

    To create a new view, create a template in each of your different content type directories with the view name. The following example contains an “li” view and a “summary” view for the post and project content types. As you can see, these sit next to the single content view template, single.html. You can even provide a specific view for a given type and continue to use the _default/single.html` for the primary view.

      ▾ layouts/
        ▾ post/
            li.html
            single.html
            summary.html
        ▾ project/
            li.html
            single.html
            summary.html
    

    Hugo also has support for a default content template to be used in the event that a specific content view template has not been provided for that type. Content views can also be defined in the _default directory and will work the same as list and single templates who eventually trickle down to the _default directory as a matter of the lookup order.

    ▾ layouts/
      ▾ _default/
          li.html
          single.html
          summary.html
    

    Which Template Will be Rendered?

    The following is the lookup order for content views:

    1. /layouts/<TYPE>/<VIEW>.html
    2. /layouts/_default/<VIEW>.html
    3. /themes/<THEME>/layouts/<TYPE>/<VIEW>.html
    4. /themes/<THEME>/layouts/_default/<VIEW>.html

    Example: Content View Inside a List

    The following example demonstrates how to use content views inside of your list templates.

    list.html

    In this example, .Render is passed into the template to call the render function. .Render is a special function that instructs content to render itself with the view template provided as the first argument. In this case, the template is going to render the summary.html view that follows:

    {{< code file=“layouts/_default/list.html” download=“list.html” >}}

    {{ .Title }}

    {{ range .Data.Pages }} {{ .Render "summary"}} {{ end }}
    {{< /code >}}

    summary.html

    Hugo will pass the entire page object to the following summary.html view template. (See Page Variables for a complete list.)

    {{< code file=“layouts/_default/summary.html” download=“summary.html” >}}

    {{< /code >}}

    li.html

    Continuing on the previous example, we can change our render function to use a smaller li.html view by changing the argument in the call to the .Render function (i.e., {{ .Render "li" }}).

    {{< code file=“layouts/_default/li.html” download=“li.html” >}}

  • {{ .Title }}
    {{ .Date.Format "Mon, Jan 2, 2006" }}
  • {{< /code >}}

    [taxonomylists]: /templates/taxonomy-templates/

    Data Templates

    Hugo supports loading data from YAML, JSON, and TOML files located in the data directory in the root of your Hugo project.

    The Data Folder

    The data folder is where you can store additional data for Hugo to use when generating your site. Data files aren’t used to generate standalone pages; rather, they’re meant to be supplemental to content files. This feature can extend the content in case your front matter fields grow out of control. Or perhaps you want to show a larger dataset in a template (see example below). In both cases, it’s a good idea to outsource the data in their own files.

    These files must be YAML, JSON, or TOML files (using the .yml, .yaml, .json, or .toml extension). The data will be accessible as a map in the .Site.Data variable.

    Data Files in Themes

    Data Files can also be used in Hugo themes but note that theme data files follow the same logic as other template files in the Hugo lookup order (i.e., given two files with the same name and relative path, the file in the root project data directory will override the file in the themes/<THEME>/data directory).

    Therefore, theme authors should take care to not include data files that could be easily overwritten by a user who decides to customize a theme. For theme-specific data items that shouldn’t be overridden, it can be wise to prefix the folder structure with a namespace; e.g. mytheme/data/<THEME>/somekey/.... To check if any such duplicate exists, run hugo with the -v flag.

    The keys in the map created with data templates from data files will be a dot-chained set of path, filename, and key in file (if applicable).

    This is best explained with an example:

    Example: Jaco Pastorius’ Solo Discography

    Jaco Pastorius was a great bass player, but his solo discography is short enough to use as an example. John Patitucci is another bass giant.

    The example below is a bit contrived, but it illustrates the flexibility of data Files. This example uses TOML as its file format with the two following data files:

    • data/jazz/bass/jacopastorius.toml
    • data/jazz/bass/johnpatitucci.toml

    jacopastorius.toml contains the content below. johnpatitucci.toml contains a similar list:

    discography = [
    "1974 – Modern American Music … Period! The Criteria Sessions",
    "1974 – Jaco",
    "1976 - Jaco Pastorius",
    "1981 - Word of Mouth",
    "1981 - The Birthday Concert (released in 1995)",
    "1982 - Twins I & II (released in 1999)",
    "1983 - Invitation",
    "1986 - Broadway Blues (released in 1998)",
    "1986 - Honestly Solo Live (released in 1990)",
    "1986 - Live In Italy (released in 1991)",
    "1986 - Heavy'n Jazz (released in 1992)",
    "1991 - Live In New York City, Volumes 1-7.",
    "1999 - Rare Collection (compilation)",
    "2003 - Punk Jazz: The Jaco Pastorius Anthology (compilation)",
    "2007 - The Essential Jaco Pastorius (compilation)"
    ]
    

    The list of bass players can be accessed via .Site.Data.jazz.bass, a single bass player by adding the filename without the suffix, e.g. .Site.Data.jazz.bass.jacopastorius.

    You can now render the list of recordings for all the bass players in a template:

    {{ range $.Site.Data.jazz.bass }}
       {{ partial "artist.html" . }}
    {{ end }}
    

    And then in the partial/artist.html:

    <ul>
    {{ range .discography }}
      <li>{{ . }}</li>
    {{ end }}
    </ul>
    

    Discover a new favorite bass player? Just add another .toml file in the same directory.

    Example: Accessing Named Values in a Data File

    Assume you have the following YAML structure in your User0123.yml data file located directly in data/:

    Name: User0123
    "Short Description": "He is a **jolly good** fellow."
    Achievements:
      - "Can create a Key, Value list from Data File"
      - "Learns Hugo"
      - "Reads documentation"
    

    You can use the following code to render the Short Description in your layout::

    <div>Short Description of {{.Site.Data.User0123.Name}}: <p>{{ index .Site.Data.User0123 "Short Description" | markdownify }}</p></div>
    

    Note the use of the markdownify template function. This will send the description through the Blackfriday Markdown rendering engine.

    Data-Driven Content

    In addition to the data files feature, Hugo also a “data-driven content” feature, which lets you load any JSON or CSV file from nearly any resource.

    Data-driven content currently consists of two functions, getJSON and getCSV, which are available in all template files.

    Implementation details

    Call the Functions with a URL

    In your template, call the functions like this:

    {{ $dataJ := getJSON "url" }}
    {{ $dataC := getCSV "separator" "url" }}
    

    If you use a prefix or postfix for the URL, the functions accept variadic arguments:

    {{ $dataJ := getJSON "url prefix" "arg1" "arg2" "arg n" }}
    {{ $dataC := getCSV  "separator" "url prefix" "arg1" "arg2" "arg n" }}
    

    The separator for getCSV must be put in the first position and can only be one character long.

    All passed arguments will be joined to the final URL:

    {{ $urlPre := "https://api.github.com" }}
    {{ $gistJ := getJSON $urlPre "/users/GITHUB_USERNAME/gists" }}
    

    This will resolve internally to the following:

    {{ $gistJ := getJSON "https://api.github.com/users/GITHUB_USERNAME/gists" }}
    

    Finally, you can range over an array. This example will output the
    first 5 gists for a GitHub user:

    <ul>
      {{ $urlPre := "https://api.github.com" }}
      {{ $gistJ := getJSON $urlPre "/users/GITHUB_USERNAME/gists" }}
      {{ range first 5 $gistJ }}
        {{ if .public }}
          <li><a href="{{ .html_url }}" target="_blank">{{ .description }}</a></li>
        {{ end }}
      {{ end }}
    </ul>
    

    Example for CSV files

    For getCSV, the one-character-long separator must be placed in the first position followed by the URL. The following is an example of creating an HTML table in a partial template from a published CSV:

    {{< code file=“layouts/partials/get-csv.html” >}}

    {{ $url := "http://a-big-corp.com/finance/employee-salaries.csv" }} {{ $sep := "," }} {{ range $i, $r := getCSV $sep $url }} {{ end }}
    Name Position Salary
    {{ index $r 0 }} {{ index $r 1 }} {{ index $r 2 }}
    {{< /code >}}

    The expression {{index $r number}} must be used to output the nth-column from the current row.

    Cache URLs

    Each downloaded URL will be cached in the default folder $TMPDIR/hugo_cache/. The variable $TMPDIR will be resolved to your system-dependent temporary directory.

    With the command-line flag --cacheDir, you can specify any folder on your system as a caching directory.

    You can also set cacheDir in the main configuration file.

    If you don’t like caching at all, you can fully disable caching with the command line flag --ignoreCache.

    Authentication When Using REST URLs

    Currently, you can only use those authentication methods that can be put into an URL. OAuth and other authentication methods are not implemented.

    Load Local files

    To load local files with getJSON and getCSV, the source files must reside within Hugo’s working directory. The file extension does not matter, but the content does.

    It applies the same output logic as above in Calling the Functions with a URL.

    LiveReload with Data Files

    There is no chance to trigger a LiveReload when the content of a URL changes. However, when a local file changes (i.e., data/* and themes/<THEME>/data/*), a LiveReload will be triggered. Symlinks are not supported. Note too that because downloading of data takes a while, Hugo stops processing your Markdown files until the data download has completed.

    {{% warning “URL Data and LiveReload” %}}
    If you change any local file and the LiveReload is triggered, Hugo will read the data-driven (URL) content from the cache. If you have disabled the cache (i.e., by running the server with hugo server --ignoreCache), Hugo will re-download the content every time LiveReload triggers. This can create huge traffic. You may reach API limits quickly.
    {{% /warning %}}

    Examples of Data-driven Content

    Specs for Data Formats

    Partial Templates

    Partial Template Lookup Order

    Partial templates—like single page templates and list page templates—have a specific lookup order. However, partials are simpler in that Hugo will only check in two places:

    1. layouts/partials/*<PARTIALNAME>.html
    2. themes/<THEME>/layouts/partials/*<PARTIALNAME>.html

    This allows a theme’s end user to copy a partial’s contents into a file of the same name for further customization.

    Use Partials in your Templates

    All partials for your Hugo project are located in a single layouts/partials directory. For better organization, you can create multiple subdirectories within partials as well:

    .
    └── layouts
        └── partials
            ├── footer
            │   ├── scripts.html
            │   └── site-footer.html
            ├── head
            │   ├── favicons.html
            │   ├── metadata.html
            │   ├── prerender.html
            │   └── twitter.html
            └── header
                ├── site-header.html
                └── site-nav.html
    

    All partials are called within your templates using the following pattern:

    {{ partial "<PATH>/<PARTIAL>.html" . }}
    

    {{% note %}}
    One of the most common mistakes with new Hugo users is failing to pass a context to the partial call. In the pattern above, note how “the dot” (.) is required as the second argument to give the partial context. You can read more about “the dot” in the Hugo templating introduction.
    {{% /note %}}

    As shown in the above example directory structure, you can nest your directories within partials for better source organization. You only need to call the nested partial’s path relative to the partials directory:

    {{ partial "header/site-header.html" . }}
    {{ partial "footer/scripts.html" . }}
    

    {{% note %}}
    Before v0.12, Hugo used the template call to include partial templates. When using Hugo v0.12 and newer, be sure to use the {{ partial "<PATH>/<PARTIAL>.html" . }} syntax. The old approach will still work but has fewer benefits.
    {{% /note %}}

    Variable Scoping

    The second argument in a partial call is the variable being passed down. The above examples are passing the ., which tells the template receiving the partial to apply the current context.

    This means the partial will only be able to access those variables. The partial is isolated and has no access to the outer scope. From within the partial, $.Var is equivalent to .Var.

    Cached Partials

    The partialCached template function can offer significant performance gains for complex templates that don’t need to be re-rendered on every invocation. The simplest usage is as follows:

    {{ partialCached "footer.html" . }}
    

    You can also pass additional parameters to partialCached to create variants of the cached partial.

    For example, you can tell Hugo to only render the partial footer.html once per section:

    {{ partialCached "footer.html" . .Section }}
    

    If you need to pass additional parameters to create unique variants, you can pass as many variant parameters as you need:

    {{ partialCached "footer.html" . .Params.country .Params.province }}
    

    Note that the variant parameters are not made available to the underlying partial template. They are only use to create a unique cache key.

    Example header.html

    The following header.html partial template is used for spf13.com:

    {{< code file=“layouts/partials/header.html” download=“header.html” >}}

    {{ partial "meta.html" . }}
    
    <base href="{{ .Site.BaseURL }}">
    <title> {{ .Title }} : spf13.com </title>
    <link rel="canonical" href="{{ .Permalink }}">
    {{ if .RSSLink }}<link href="{{ .RSSLink }}" rel="alternate" type="application/rss+xml" title="{{ .Title }}" />{{ end }}
    
    {{ partial "head_includes.html" . }}
    
    {{< /code >}}

    {{% note %}}
    The header.html example partial was built before the introduction of block templates to Hugo. Read more on base templates and blocks for defining the outer chrome or shell of your master templates (i.e., your site’s head, header, and footer). You can even combine blocks and partials for added flexibility.
    {{% /note %}}

    Example footer.html

    The following footer.html partial template is used for spf13.com:

    {{< code file=“layouts/partials/footer.html” download=“footer.html” >}}

    {{< /code >}}

    themes: /themes/

    Create Your Own Shortcodes

    Shortcodes are a means to consolidate templating into small, reusable snippets that you can embed directly inside of your content. In this sense, you can think of shortcodes as the intermediary between page and list templates and basic content files.

    {{% note %}}
    Hugo also ships with built-in shortcodes for common use cases. (See Content Management: Shortcodes.)
    {{% /note %}}

    Create Custom Shortcodes

    Hugo’s built-in shortcodes cover many common, but not all, use cases. Luckily, Hugo provides the ability to easily create custom shortcodes to meet your website’s needs.

    File Placement

    To create a shortcode, place an HTML template in the layouts/shortcodes directory of your source organization. Consider the file name carefully since the shortcode name will mirror that of the file but without the .html extension. For example, layouts/shortcodes/myshortcode.html will be called with either {{</* myshortcode /*/>}} or {{%/* myshortcode /*/%}} depending on the type of parameters you choose.

    Shortcode Template Lookup Order

    Shortcode templates have a simple lookup order:

    1. /layouts/shortcodes/<SHORTCODE>.html
    2. /themes/<THEME>/layouts/shortcodes/<SHORTCODE>.html

    Positional vs Named Parameters

    You can create shortcodes using the following types of parameters:

    • Positional parameters
    • Named parameters
    • Positional or named parameters (i.e, “flexible”)

    In shortcodes with positional parameters, the order of the parameters is important. If a shortcode has a single required value (e.g., the youtube shortcode below), positional parameters work very well and require less typing from content authors.

    For more complex layouts with multiple or optional parameters, named parameters work best. While less terse, named parameters require less memorization from a content author and can be added in a shortcode declaration in any order.

    Allowing both types of parameters (i.e., a “flexible” shortcode) is useful for complex layouts where you want to set default values that can be easily overridden by users.

    Access Parameters

    All shortcode parameters can be accessed via the .Get method. Whether you pass a key (i.e., string) or a number to the .Get method depends on whether you are accessing a named or positional parameter, respectively.

    To access a parameter by name, use the .Get method followed by the named parameter as a quoted string:

    {{ .Get "class" }}
    

    To access a parameter by position, use the .Get followed by a numeric position, keeping in mind that positional parameters are zero-indexed:

    {{ .Get 0 }}
    

    with is great when the output depends on a parameter being set:

    {{ with .Get "class"}} class="{{.}}"{{ end }}
    

    .Get can also be used to check if a parameter has been provided. This is
    most helpful when the condition depends on either of the values, or both:

    {{ or .Get "title" | .Get "alt" | if }} alt="{{ with .Get "alt"}}{{.}}{{else}}{{.Get "title"}}{{end}}"{{ end }}
    

    .Inner

    If a closing shortcode is used, the .Inner variable will be populated with all of the content between the opening and closing shortcodes. If a closing shortcode is required, you can check the length of .Inner as an indicator of its existence.

    A shortcode with content declared via the .Inner variable can also be declared without the inline content and without the closing shortcode by using the self-closing syntax:

    {{</* innershortcode /*/>}}
    

    .Params

    The .Params variable in shortcodes contains the list parameters passed to shortcode for more complicated use cases. You can also access higher-scoped parameters with the following logic:

    $.Params
    these are the parameters passed directly into the shortcode declaration (e.g., a YouTube video ID)
    $.Page.Params
    refers to the page’s params; the “page” in this case refers to the content file in which the shortcode is declared (e.g., a shortcode_color field in a content’s front matter could be accessed via $.Page.Params.shortcode_color).
    $.Page.Site.Params
    refers to global variables as defined in your site’s configuration file.

    .IsNameParams

    The .IsNamedParams variable checks whether the shortcode declaration uses named parameters and returns a boolean value.

    For example, you could create an image shortcode that can take either a src named parameter or the first positional parameter, depending on the preference of the content’s author. Let’s assume the image shortcode is called as follows:

    {{</* image src="images/my-image.jpg"*/>}}
    

    You could then include the following as part of your shortcode templating:

    {{ if .IsNamedParams }}
    <img src="{{.Get "src" alt="">
    {{ else }}
    <img src="{{.Get 0}}" alt="">
    {{ end }}.
    

    See the example Vimeo shortcode below for .IsNamedParams in action.

    {{% warning %}}
    While you can create shortcode templates that accept both positional and named parameters, you cannot declare shortcodes in content with a mix of parameter types. Therefore, a shortcode declared like {{</* image src="images/my-image.jpg" "This is my alt text" */>}} will return an error.
    {{% /warning %}}

    You can also use the variable .Page to access all the normal page variables.

    A shortcodes can also be nested. In a nested shortcode, you can access the parent shortcode context with .Parent variable. This can be very useful for inheritance of common shortcode parameters from the root.

    Custom Shortcode Examples

    The following are examples of the different types of shortcodes you can create via shortcode template files in /layouts/shortcodes.

    Single-word Example: year

    Let’s assume you would like to keep mentions of your copyright year current in your content files without having to continually review your markdown. Your goal is to be able to call the shortcode as follows:

    {{</* year */>}}
    

    {{< code file=“/layouts/shortcodes/year.html” >}}
    {{ .Page.Now.Year }}
    {{< /code >}}

    Single Positional Example: youtube

    Embedded videos are a common addition to markdown content that can quickly become unsightly. The following is the code used by [Hugo’s built-in YouTube shortcode][youtubeshortcode]:

    {{</* youtube 09jf3ow9jfw */>}}
    

    Would load the template at /layouts/shortcodes/youtube.html:

    {{< code file=“/layouts/shortcodes/youtube.html” >}}

    {{< /code >}}

    {{< code file=“youtube-embed.html” copy=“false” >}}

    {{< /code >}}

    Single Named Example: image

    Let’s say you want to create your own img shortcode rather than use Hugo’s built-in figure shortcode. Your goal is to be able to call the shortcode as follows in your content files:

    {{< code file=“content-image.md” >}}
    {{</* img src=“/media/spf13.jpg” title=“Steve Francia” */>}}
    {{< /code >}}

    You have created the shortcode at /layouts/shortcodes/img.html, which loads the following shortcode template:

    {{< code file=“/layouts/shortcodes/img.html” >}}

    {{ with .Get "link"}}{{ end }} {{ if .Get "link"}}{{ end }} {{ if or (or (.Get "title") (.Get "caption")) (.Get "attr")}}
    {{ if isset .Params "title" }}

    {{ .Get "title" }}

    {{ end }} {{ if or (.Get "caption") (.Get "attr")}}

    {{ .Get "caption" }} {{ with .Get "attrlink"}} {{ end }} {{ .Get "attr" }} {{ if .Get "attrlink"}} {{ end }}

    {{ end }}
    {{ end }}
    {{< /code >}}

    Would be rendered as:

    {{< code file=“img-output.html” copy=“false” >}}

    Steve Francia

    {{< /code >}}

    Single Flexible Example: vimeo

    {{</* vimeo 49718712 */>}}
    {{</* vimeo id="49718712" class="flex-video" */>}}
    

    Would load the template found at /layouts/shortcodes/vimeo.html:

    {{< code file=“/layouts/shortcodes/vimeo.html” >}}
    {{ if .IsNamedParams }}

    {{ else }}
    {{ end }} {{< /code >}}

    Would be rendered as:

    {{< code file=“vimeo-iframes.html” copy=“false” >}}

    {{< /code >}}

    Paired Example: highlight

    The following is taken from highlight, which is a built-in shortcode that ships with Hugo.

    {{< code file=“highlight-example.md” >}}
    {{</* highlight html */>}}

    This HTML {{}} {{< /code >}}

    The template for the highlight shortcode uses the following code, which is already included in Hugo:

    {{ .Get 0 | highlight .Inner  }}
    

    The rendered output of the HTML example code block will be as follows:

    {{< code file=“syntax-highlighted.html” copy=“false” >}}

    <html>
        <body> This HTML </body>
    </html>
    
    {{< /code >}}

    {{% note %}}
    The preceding shortcode makes use of a Hugo-specific template function called highlight, which uses Pygments to add syntax highlighting to the example HTML code block. See the developer tools page on syntax highlighting for more information.
    {{% /note %}}

    Nested Shortcode: Image Gallery

    Hugo’s .Parent shortcode variable returns a boolean value depending on whether the shortcode in question is called within the context of a parent shortcode. This provides an inheritance model for common shortcode parameters.

    The following example is contrived but demonstrates the concept. Assume you have a gallery shortcode that expects one named class parameter:

    {{< code file=“layouts/shortcodes/gallery.html” >}}

    {{.Inner}}
    {{< /code >}}

    You also have an image shortcode with a single named src parameter that you want to call inside of gallery and other shortcodes so that the parent defines the context of each image:

    {{< code file=“layouts/shortcodes/image.html” >}}
    {{- $src := .Get “src” -}}
    {{- with .Parent -}}
    <img src=“{{$src}}” class=“{{.Get “class”}}-image”>
    {{- else -}}

    {{- end }}
    {{< /code >}}

    You can then call your shortcode in your content as follows:

    {{</* gallery class="content-gallery" */>}}
      {{</* img src="/images/one.jpg" */>}}
      {{</* img src="/images/two.jpg" */>}}
    {{</* /gallery */>}}
    {{</* img src="/images/three.jpg" */>}}
    

    This will output the following HTML. Note how the first two image shortcodes inherit the class value of content-gallery set with the call to the parent gallery, whereas the third image only uses src:

    <div class="content-gallery">
        <img src="/images/one.jpg" class="content-gallery-image">
        <img src="/images/two.jpg" class="content-gallery-image">
    </div>
    <img src="/images/three.jpg">
    

    More Shortcode Examples

    More shortcode examples can be found in the shortcodes directory for spf13.com and the shortcodes directory for the Hugo docs.

    [youtubeshortcode]: /content-management/shortcodes/#youtube “See how to use Hugo’s built-in YouTube shortcode.”

    Local File Templates

    Traverse Local Files

    With Hugo’s readDir and readFile template functions, you can traverse your website’s files on your server.

    Use readDir

    The readDir function returns an array of os.FileInfo. It takes the file’s path as a single string argument. This path can be to any directory of your website (i.e., as found on your server’s file system).

    Whether the path is absolute or relative does not matter because—at least for readDir—the root of your website (typically ./public/) in effect becomes both:

    1. The file system root
    2. The current working directory

    readDir Example: List Directory Files

    This shortcode creates a link to each of the files in a directory—display as the file’s basename—along with the file’s size in bytes.

    {{< code file=“layouts/shortcodes/directoryindex.html” download=“directoryindex.html” >}}
    {{< readfile file=“/themes/gohugoioTheme/layouts/shortcodes/directoryindex.html” >}}
    {{< /code >}}

    You can then call the shortcode as follows inside of your content’s markup:

    {{</* directoryindex path="/static/css" pathURL="/css" */>}}
    

    The above shortcode is part of the code for the Hugo docs. Here it lists this site’s CSS files:

    {{< directoryindex path=“/themes/gohugoioTheme/static/dist” pathURL=“/css” >}}

    {{% note “Slashes are Important” %}}
    The initial slash / in pathURL is important in the directoryindex shortcode. Otherwise, pathURL becomes relative to the current web page.
    {{% /note %}}

    Use readFile

    The readfile function reads a file from disk and converts it into a string to be manipulated by other Hugo functions or added as-is. readFile takes the file, including path, as an argument passed to the function.

    To use the readFile function in your templates, make sure the path is relative to your Hugo project’s root directory:

    {{ readFile "/content/templates/local-file-templates" }}
    

    readFile Example: Add a Project File to Content

    As readFile is a function, it is only available to you in your templates and not your content. However, we can create a simple shortcode template that calls readFile, passes the first argument through the function, and then allows an optional second argument to send the file through the Blackfriday markdown processor. The pattern for adding this shortcode to your content will be as follows:

    {{</* readfile file="/path/to/local/file.txt" markdown="true" */>}}
    

    {{% warning %}}
    If you are going to create custom shortcodes with readFile for a theme, note that usage of the shortcode will refer to the project root and not your themes directory.
    {{% /warning %}}

    Here is the templating for our new readfile shortcode:

    {{< code file=“layouts/shortcodes/readfile.html” download=“readfile.html” >}}
    {{< readfile file=“/themes/gohugoioTheme/layouts/shortcodes/readfile.html”>}}
    {{< /code >}}

    This readfile shortcode is also part of the Hugo docs. So is testing.txt, which we will call in this example by passing it into our new readfile shortcode as follows:

    {{</* readfile file="/content/readfiles/testing.txt" */>}}
    

    The output “string” for this shortcode declaration will be the following:

    {{< readfile file="/content/readfiles/testing.txt" >}}
    

    However, if we want Hugo to pass this string through Blackfriday, we should add the markdown="true" optional parameter:

    {{</* readfile file="/content/readfiles/testing.txt" markdown="true" */>}}
    

    And here is the result as called directly in the Hugo docs and rendered for display:

    {{< readfile file=“/content/readfiles/testing.txt” markdown=“true”>}}

    Custom 404 Page

    When using Hugo with GitHub Pages, you can provide your own template for a custom 404 error page by creating a 404.html template file in your /layouts folder. When Hugo generates your site, the 404.html file will be placed in the root.

    404 pages will have all the regular page variables available to use in the templates.

    In addition to the standard page variables, the 404 page has access to all site content accessible from .Data.Pages.

    ▾ layouts/
        404.html
    

    404.html

    This is a basic example of a 404.html template:

    {{< code file=“layouts/404.html” download=“404.html” >}}
    {{ define “main”}}



    <a href=“{{ “/” | relURL }}”>Go Home




    {{ end }}
    {{< /code >}}

    Automatic Loading

    Your 404.html file can be set to load automatically when a visitor enters a mistaken URL path, dependent upon the web serving environment you are using. For example:

    • GitHub Pages. The 404 page is automatic.
    • Apache. You can specify ErrorDocument 404 /404.html in an .htaccess file in the root of your site.
    • Nginx. You might specify error_page 404 /404.html; in your nginx.conf file.
    • Amazon AWS S3. When setting a bucket up for static web serving, you can specify the error file from within the S3 GUI.
    • Caddy Server. Using errors { 404 /404.html }. Details here

    pagevars: /variables/page/

    Menu Templates

    Hugo makes no assumptions about how your rendered HTML will be
    structured. Instead, it provides all of the functions you will need to be
    able to build your menu however you want.

    The following is an example:

    {{< code file=“layouts/partials/sidebar.html” download=“sidebar.html” >}}

    {{< /code >}}

    {{% note “absLangURL and relLangURL” %}}
    Use the absLangUrl or relLangUrl functions if your theme makes use of the multilingual feature. In contrast to absURL and relURL, these two functions add the correct language prefix to the url.
    {{% /note %}}

    Section Menu for Lazy Bloggers

    To enable this menu, configure sectionPagesMenu in your site config:

    sectionPagesMenu = "main"
    

    The menu name can be anything, but take a note of what it is.

    This will create a menu with all the sections as menu items and all the sections’ pages as “shadow-members”. The shadow implies that the pages isn’t represented by a menu-item themselves, but this enables you to create a top-level menu like this:

    <nav class="sidebar-nav">
        {{ $currentPage := . }}
        {{ range .Site.Menus.main }}
        <a class="sidebar-nav-item{{if or ($currentPage.IsMenuCurrent "main" .) ($currentPage.HasMenuCurrent "main" .) }} active{{end}}" href="{{.URL}}">{{ .Name }}</a>
        {{ end }}
    </nav>
    

    In the above, the menu item is marked as active if on the current section’s list page or on a page in that section.

    The above is all that’s needed. But if you want custom menu items, e.g. changing weight or name, you can define them manually in the site config, i.e. config.toml:

    [[menu.main]]
        name = "This is the blog section"
        weight = -110
        identifier = "blog"
        url = "/blog/"
    

    {{% note %}}
    The identifier must match the section name.
    {{% /note %}}

    Pagination

    The real power of Hugo pagination shines when combined with the where function and its SQL-like operators: first, last, and after. You can even order the content the way you’ve become used to with Hugo.

    Configure Pagination

    Pagination can be configured in your site configuration:

    Paginate
    default = 10. This setting can be overridden within the template.
    PaginatePath
    default = page. Allows you to set a different path for your pagination pages.

    Setting Paginate to a positive value will split the list pages for the homepage, sections and taxonomies into chunks of that size. But note that the generation of the pagination pages for sections, taxonomies and homepage is lazy — the pages will not be created if not referenced by a .Paginator (see below).

    PaginatePath is used to adapt the URL to the pages in the paginator (the default setting will produce URLs on the form /page/1/.

    List Paginator Pages

    {{% warning %}}
    .Paginator is provided to help you build a pager menu. This feature is currently only supported on homepage and list pages (i.e., taxonomies and section lists).
    {{% /warning %}}

    There are two ways to configure and use a .Paginator:

    1. The simplest way is just to call .Paginator.Pages from a template. It will contain the pages for that page.
    2. Select a subset of the pages with the available template functions and ordering options, and pass the slice to .Paginate, e.g. {{ range (.Paginate ( first 50 .Data.Pages.ByTitle )).Pages }}.

    For a given Page, it’s one of the options above. The .Paginator is static and cannot change once created.

    The global page size setting (Paginate) can be overridden by providing a positive integer as the last argument. The examples below will give five items per page:

    • {{ range (.Paginator 5).Pages }}
    • {{ $paginator := .Paginate (where .Data.Pages "Type" "post") 5 }}

    It is also possible to use the GroupBy functions in combination with pagination:

    {{ range (.Paginate (.Data.Pages.GroupByDate "2006")).PageGroups  }}
    

    Build the navigation

    The .Paginator contains enough information to build a paginator interface.

    The easiest way to add this to your pages is to include the built-in template (with Bootstrap-compatible styles):

    {{ template "_internal/pagination.html" . }}
    

    {{% note “When to Create .Paginator” %}}
    If you use any filters or ordering functions to create your .Paginator and you want the navigation buttons to be shown before the page listing, you must create the .Paginator before it’s used.
    {{% /note %}}

    The following example shows how to create .Paginator before its used:

    {{ $paginator := .Paginate (where .Data.Pages "Type" "post") }}
    {{ template "_internal/pagination.html" . }}
    {{ range $paginator.Pages }}
       {{ .Title }}
    {{ end }}
    

    Without the where filter, the above example is even simpler:

    {{ template "_internal/pagination.html" . }}
    {{ range .Paginator.Pages }}
       {{ .Title }}
    {{ end }}
    

    If you want to build custom navigation, you can do so using the .Paginator object, which includes the following properties:

    PageNumber
    The current page’s number in the pager sequence

    URL:
    The relative URL to the current pager

    Pages:
    The pages in the current pager

    NumberOfElements
    The number of elements on this page
    HasPrev
    Whether there are page(s) before the current
    Prev
    The pager for the previous page
    HasNext
    Whether there are page(s) after the current
    Next
    The pager for the next page
    First
    The pager for the first page
    Last
    The pager for the last page
    Pagers
    A list of pagers that can be used to build a pagination menu
    PageSize
    Size of each pager
    TotalPages
    The number of pages in the paginator
    TotalNumberOfElements
    The number of elements on all pages in this paginator

    Additional information

    The pages are built on the following form (BLANK means no value):

    [SECTION/TAXONOMY/BLANK]/index.html
    [SECTION/TAXONOMY/BLANK]/page/1/index.html => redirect to  [SECTION/TAXONOMY/BLANK]/index.html
    [SECTION/TAXONOMY/BLANK]/page/2/index.html
    ....
    

    where: /functions/where/

    RSS Templates

    RSS Template Lookup Order

    You can use a single RSS template to generate all of your RSS feeds or create a specific template for each individual feed.

    1. /layouts/section/<section>.rss.xml
    2. /layouts/_default/rss.xml
    3. /themes/<theme>/layouts/section/<section>.rss.xml
    4. /themes/<theme>/layouts/_default/rss.xml

    {{% note “Hugo Ships with an RSS Template” %}}
    Hugo ships with its own RSS 2.0 template. The embedded template will be sufficient for most use cases.
    {{% /note %}}

    RSS pages are of the type Page and have all the page variables available to use in the templates.

    Section RSS

    A section’s RSS will be rendered at /<SECTION>/index.xml (e.g., http://spf13.com/project/index.xml).

    Hugo provides the ability for you to define any RSS type you wish and can have different RSS files for each section and taxonomy.

    Lookup Order for RSS Templates

    Main RSS

    1. /layouts/rss.xml
    2. /layouts/_default/rss.xml
    3. Embedded rss.xml

    Section RSS

    1. /layouts/section/<SECTION>.rss.xml
    2. /layouts/_default/rss.xml
    3. /themes/<THEME>/layouts/section/<SECTION>.rss.xml
    4. /themes/<THEME>/layouts/_default/rss.xml
    5. Embedded rss.xml

    Taxonomy RSS

    1. /layouts/taxonomy/<SINGULAR>.rss.xml
    2. /layouts/_default/rss.xml
    3. /themes/<THEME>/layouts/taxonomy/<SINGULAR>.rss.xml
    4. /themes/<THEME>/layouts/_default/rss.xml
    5. Embedded rss.xml

    Configure RSS

    By default, Hugo will create an unlimited number of RSS entries. You can limit the number of articles included in the built-in RSS templates by assigning a numeric value to rssLimit: field in your project’s config file.

    The following values will also be included in the RSS output if specified in your site’s configuration:

    languageCode = "en-us"
    copyright = "This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License."
    
    [author]
        name = "My Name Here"
    

    The Embedded rss.xml

    This is the default RSS template that ships with Hugo. It adheres to the RSS 2.0 Specification.

    <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
      <channel>
        <title>{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}</title>
        <link>{{ .Permalink }}</link>
        <description>Recent content {{ with .Title }}in {{.}} {{ end }}on {{ .Site.Title }}</description>
        <generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }}
        <language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
        <managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
        <webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
        <copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
        <lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
        <atom:link href="{{.URL}}" rel="self" type="application/rss+xml" />
        {{ range first 15 .Data.Pages }}
        <item>
          <title>{{ .Title }}</title>
          <link>{{ .Permalink }}</link>
          <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
          {{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
          <guid>{{ .Permalink }}</guid>
          <description>{{ .Content | html }}</description>
        </item>
        {{ end }}
      </channel>
    </rss>
    

    {{% warning “XML Header” %}}
    Hugo will automatically add the following header line to this file on render. Please do not include this in the template as it’s not valid HTML.

    <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
    

    {{% /warning %}}

    Reference your RSS Feed in <head>

    In your header.html template, you can specify your RSS feed in your <head></head> tag like this:

    {{ if .RSSLink }}
      <link href="{{ .RSSLink }}" rel="alternate" type="application/rss+xml" title="{{ .Site.Title }}" />
      <link href="{{ .RSSLink }}" rel="feed" type="application/rss+xml" title="{{ .Site.Title }}" />
    {{ end }}
    

    …with the auto-discovery link specified by the line with rel="alternate".

    The .RSSLink will render the appropriate RSS feed URL for the section, whether it’s everything, posts in a section, or a taxonomy.

    If you reference your RSS link, be sure to specify the MIME type with type="application/rss+xml".

    <a href="{{ .URL }}" type="application/rss+xml" target="_blank">{{ .SomeText }}</a>
    

    Sitemap Template

    A single Sitemap template is used to generate the sitemap.xml file.
    Hugo automatically comes with this template file. No work is needed on
    the users’ part unless they want to customize sitemap.xml.

    A sitemap is a Page and therefore has all the page variables available to use in this template along with Sitemap-specific ones:

    .Sitemap.ChangeFreq
    The page change frequency
    .Sitemap.Priority
    The priority of the page
    .Sitemap.Filename
    The sitemap filename

    If provided, Hugo will use /layouts/sitemap.xml instead of the internal sitemap.xml template that ships with Hugo.

    Hugo’s sitemap.xml

    This template respects the version 0.9 of the Sitemap Protocol.

    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      {{ range .Data.Pages }}
      <url>
        <loc>{{ .Permalink }}</loc>{{ if not .Lastmod.IsZero }}
        <lastmod>{{ safeHTML ( .Lastmod.Format "2006-01-02T15:04:05-07:00" ) }}</lastmod>{{ end }}{{ with .Sitemap.ChangeFreq }}
        <changefreq>{{ . }}</changefreq>{{ end }}{{ if ge .Sitemap.Priority 0.0 }}
        <priority>{{ .Sitemap.Priority }}</priority>{{ end }}
      </url>
      {{ end }}
    </urlset>
    

    {{% note %}}
    Hugo will automatically add the following header line to this file
    on render. Please don’t include this in the template as it’s not valid HTML.

    <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
    {{% /note %}}

    Configure sitemap.xml

    Defaults for <changefreq>, <priority> and filename values can be set in the site’s config file, e.g.:

    [sitemap]
      changefreq = "monthly"
      priority = 0.5
      filename = "sitemap.xml"
    

    The same fields can be specified in an individual content file’s front matter in order to override the value assigned to that piece of content at render time.

    pagevars: /variables/page/

    Robots.txt File

    To create your robots.txt as a template, first set the enableRobotsTXT value to true in your configuration file. By default, this option generates a robots.txt with the following content, which tells search engines that they are allowed to crawl everything:

    User-agent: *
    

    Robots.txt Template Lookup Order

    The lookup order for the robots.txt template is as follows:

    • /layouts/robots.txt
    • /themes/<THEME>/layout/robots.txt

    {{% note %}}
    If you do not want Hugo to create a default robots.txt or leverage the robots.txt template, you can hand code your own and place the file in static. Remember that everything in the static directory is copied over as-is when Hugo builds your site.
    {{% /note %}}

    Robots.txt Template Example

    The following is an example robots.txt layout:

    {{< code file=“layouts/robots.txt” download=“robots.txt” >}}
    User-agent: *

    {{range .Data.Pages}}
    Disallow: {{.RelPermalink}}
    {{end}}
    {{< /code >}}

    This template disallows all the pages of the site by creating one Disallow entry for each page.

    [robots]: http://www.robotstxt.org/

    Internal Templates

    {{% warning %}}
    While the following internal templates are called similar to partials, they do not observe the partial template lookup order.
    {{% /warning %}}

    Google Analytics

    Hugo ships with internal templates for Google Analytics tracking, including both synchronous and asynchronous tracking codes.

    Configure Google Analytics

    Provide your tracking id in your configuration file:

    googleAnalytics = "UA-123-45"
    
    googleAnalytics: "UA-123-45"
    

    Use the Google Analytics Template

    You can then include the Google Analytics internal template:

    {{ template "_internal/google_analytics.html" . }}
    
    {{ template "_internal/google_analytics_async.html" . }}
    

    Disqus

    Hugo also ships with an internal template for Disqus comments, a popular commenting system for both static and dynamic websites. In order to effectively use Disqus, you will need to secure a Disqus “shortname” by [signing up for the free service][disqussignup].

    Configure Disqus

    To use Hugo’s Disqus template, you first need to set a single value in your site’s config.toml or config.yml:

    disqusShortname = "yourdiscussshortname"
    
    disqusShortname: "yourdiscussshortname"
    

    You also have the option to set the following in the front matter for a given piece of content:

    • disqus_identifier
    • disqus_title
    • disqus_url

    Use the Disqus Template

    To add Disqus, include the following line in templates where you want your comments to appear:

    {{ template "_internal/disqus.html" . }}
    

    Conditional Loading of Disqus Comments

    Users have noticed that enabling Disqus comments when running the Hugo web server on localhost (i.e. via hugo server) causes the creation of unwanted discussions on the associated Disqus account.

    You can create the following layouts/partials/disqus.html:

    {{< code file=“layouts/partials/disqus.html” download=“disqus.html” >}}



    comments powered by Disqus
    {{< /code >}}

    The if statement skips the initialization of the Disqus comment injection when you are running on localhost.

    You can then render your custom Disqus partial template as follows:

    {{ partial "disqus.html" . }}
    
    _internal/_default/robots.txt
    _internal/_default/rss.xml
    _internal/_default/sitemap.xml
    _internal/_default/sitemapindex.xml
    
    _internal/disqus.html
    _internal/google_news.html
    _internal/google_analytics.html
    _internal/google_analytics_async.html
    _internal/opengraph.html
    _internal/pagination.html
    _internal/schema.html
    _internal/twitter_cards.html
    

    Alternative Templating Languages

    Ace Templates

    For template documentation, follow the links from the Ace project.

    • Ace templates must be named with the ace-suffix; e.g., list.ace
    • It’s possible to use both Go templates and Ace templates side by side and even include one into the other
    • Full Go template syntax support, including all the useful helper template functions
    • Partials can be included both with the Ace and the Go template syntax. For example, the following two will have the same output in Ace:
      • = include partials/foo.html .
      • {{ partial "foo" . }}

    One noticeable difference between Ace and the other templating engines in Hugo is Ace’s inheritance support through base and inner templates.

    In Hugo, the Ace base template will be chosen with the same rule set as for [Go base templates][].

    .:
    index.ace
    
    ./blog:
    single.ace
    baseof.ace
    
    ./_default:
    baseof.ace  list.ace  single.ace  single-baseof.ace
    

    {{% note %}}
    Note that the html suffix is needed even if the filename is suffixed ace. This does not work from inside a theme (issue #763).
    {{% /note %}}

    Some examples for the layout files above:

    • Home page: ./index.ace + ./_default/baseof.ace
    • Single page in the blog section: ./blog/single.ace + ./blog/baseof.ace
    • Single page in another section: ./_default/single.ace + ./_default/single-baseof.ace
    • Taxonomy page in any section: ./_default/list.ace + ./_default/baseof.ace

    {{% note %}}
    In most cases, one baseof.ace in _default will suffice. An Ace template without a reference to a base section (e.g., = content) will be handled as a standalone template.
    {{% /note %}}

    Amber Templates

    For Amber template documentation, follow the links from the Amber project.

    • Amber templates must be named with the Amber suffix; e.g., list.amber
    • Partials in Amber or HTML can be included with the Amber template syntax:
      • import ../partials/test.html
      • import ../partials/test_a.amber

    [Go base templates]: /templates/base/

    Template Debugging

    Here are some snippets you can add to your template to answer some common questions.

    These snippets use the printf function available in all Go templates. This function is an alias to the Go function, fmt.Printf.

    What Variables are Available in this Context?

    You can use the template syntax, $., to get the top-level template context from anywhere in your template. This will print out all the values under, .Site.

    {{ printf "%#v" $.Site }}
    

    This will print out the value of .Permalink:

    {{ printf "%#v" .Permalink }}
    

    This will print out a list of all the variables scoped to the current context
    (., aka [“the dot”][tempintro]).

    {{ printf "%#v" . }}
    

    When developing a homepage, what does one of the pages you’re looping through look like?

    {{ range .Data.Pages }}
        {{/* The context, ".", is now each one of the pages as it goes through the loop */}}
        {{ printf "%#v" . }}
    {{ end }}
    

    {{% note “.Data.Pages on the Homepage” %}}
    .Data.Pages on the homepage is equivalent to .Site.Pages.
    {{% /note %}}

    Why Am I Showing No Defined Variables?

    Check that you are passing variables in the partial function:

    {{ partial "header" }}
    

    This example will render the header partial, but the header partial will not have access to any contextual variables. You need to pass variables explicitly. For example, note the addition of [“the dot”][tempintro].

    {{ partial "header" . }}
    

    The dot (.) is considered fundamental to understanding Hugo templating. For more information, see [Introduction to Hugo Templating][tempintro].

    [tempintro]: /templates/introduction/

    Functions Quick Reference

    Go templates are lightweight but extensible. Go itself supplies built-in functions, including comparison operators and other basic tools. These are listed in the Go template documentation. Hugo has added additional functions to the basic template logic.

    with

    An alternative way of writing an if statement and then referencing the same value is to use with instead. with rebinds the context (.) within its scope and skips the block if the variable is absent or unset.

    The following example checks for a user-defined site variable called twitteruser. If the key-value is not set, the following will render nothing:

    {{< code file=“layouts/partials/twitter.html” >}}
    {{with .Site.Params.twitteruser}}{{end}}
    {{< /code >}}

    where

    where filters an array to only the elements containing a matching value for a given field.

    {{ range where .Data.Pages "Section" "post" }}
      {{ .Content }}
    {{ end }}
    

    It can be used by dot-chaining the second argument to refer to a nested element of a value.

    +++
    series: golang
    +++
    
    {{ range where .Site.Pages "Params.series" "golang" }}
       {{ .Content }}
    {{ end }}
    

    It can also be used with the logical operators !=, >=, in, etc. Without an operator, where compares a given field with a matching value equivalent to =.

    {{ range where .Data.Pages "Section" "!=" "post" }}
       {{ .Content }}
    {{ end }}
    

    The following logical operators are vailable with where:

    =, ==, eq
    true if a given field value equals a matching value
    !=, <>, ne
    true if a given field value doesn’t equal a matching value
    >=, ge
    true if a given field value is greater than or equal to a matching value
    >, gt
    true if a given field value is greater than a matching value
    <=, le
    true if a given field value is lesser than or equal to a matching value
    <, lt
    true if a given field value is lesser than a matching value
    in
    true if a given field value is included in a matching value; a matching value must be an array or a slice
    not in
    true if a given field value isn’t included in a matching value; a matching value must be an array or a slice
    intersect
    true if a given field value that is a slice/array of strings or integers contains elements in common with the matching value; it follows the same rules as the intersect function.

    Use where with intersect

    {{ range where .Site.Pages ".Params.tags" "intersect" .Params.tags }}
      {{ if ne .Permalink $.Permalink }}
        {{ .Render "summary" }}
      {{ end }}
    {{ end }}
    

    You can also put the returned value of the where clauses into a variable:

    {{< code file=“where-intersect-variables.html” >}}
    {{ $v1 := where .Site.Pages “Params.a” “v1” }}
    {{ $v2 := where .Site.Pages “Params.b” “v2” }}
    {{ $filtered := $v1 | intersect $v2 }}
    {{ range $filtered }}
    {{ end }}
    {{< /code >}}

    Use where with first

    The following grabs the first five content files in post using the default ordering for lists (i.e., weight => date):

    {{< code file=“where-with-first.html” >}}
    {{ range first 5 (where .Data.Pages “Section” “post”) }}
    {{ .Content }}
    {{ end }}
    {{< /code >}}

    Nest where Clauses

    You can also nest where clauses to drill down on lists of content by more than one parameter. The following first grabs all pages in the “blog” section and then ranges through the result of the first where clause and finds all pages that are not featured:

    {{ range where (where .Data.Pages "Section" "blog" ) ".Params.featured" "!=" "true" }}
    

    Unset Fields

    Filtering only works for set fields. To check whether a field is set or exists, you can use the operand nil.

    This can be useful to filter a small amount of pages from a large pool. Instead of set field on all pages, you can set field on required pages only.

    Only the following operators are available for nil

    • =, ==, eq: True if the given field is not set.
    • !=, <>, ne: True if the given field is set.
    {{ range where .Data.Pages ".Params.specialpost" "!=" nil }}
       {{ .Content }}
    {{ end }}
    

    urlize

    The following examples pull from a content file with the following front matter:

    {{< code file=“content/blog/greatest-city.md” copy=“false”>}}
    +++
    title = “The World’s Greatest City”
    location = “Chicago IL”
    tags = [“pizza”,“beer”,“hot dogs”]
    +++
    {{< /code >}}

    The following might be used as a partial within a single page template:

    {{< code file=“layouts/partials/content-header.html” download=“content-header.html” >}}

    {{.Title}}

    {{ with .Params.location }} {{ end }} {{ with .Params.tags }} {{ end }}
    {{< /code >}}

    The preceding partial would then output to the rendered page as follows, assuming the page is being built with Hugo’s default pretty URLs.

    {{< output file=“/blog/greatest-city/index.html” >}}

    The World's Greatest City

    {{< /output >}}

    upper

    Note that upper can be applied in your templates in more than one way:

    {{ upper "BatMan" }} → "BATMAN"
    {{ "BatMan" | upper }} → "BATMAN"
    

    .Unix

    Example: Time Passed Since Last Modification

    This very simple one-liner uses now.Unix to calculate the amount of time that has passed between the .LastMod for the current page and the last build of the current page.

    {{< code file=“time-passed.html” >}}
    {{ div (sub now.Unix .Lastmod.Unix) 86400 }}
    {{< /code >}}

    Since both values are integers, they can be subtracted and then divided by the number of seconds in a day (i.e., 60 * 60 * 24 == 86400).

    {{% note %}}
    Hugo’s output is static. For the example above to be realistic, the site needs to be built every day.
    {{% /note %}}

    uniq

    {{ uniq (slice 1 2 3 2) }}
    {{ slice 1 2 3 2 | uniq }}
    <!-- both return [1 2 3] -->
    

    union

    Given two arrays (or slices) A and B, this function will return a new array that contains the elements or objects that belong to either A or to B or to both. The elements supported are strings, integers, and floats (only float64).

    {{ union (slice 1 2 3) (slice 3 4 5) }}
    <!-- returns [1 2 3 4 5] -->
    
    {{ union (slice 1 2 3) nil }}
    <!-- returns [1 2 3] -->
    
    {{ union nil (slice 1 2 3) }}
    <!-- returns [1 2 3] -->
    
    {{ union nil nil }}
    <!-- returns an error because both arrays/slices have to be of the same type -->
    

    This is also very useful to use as OR filters when combined with where:

    {{ $pages := where .Site.RegularPages "Type" "not in" (slice "page" "about") }}
    {{ $pages := $pages | union (where .Site.RegularPages "Params.pinned" true) }}
    {{ $pages := $pages | intersect (where .Site.RegularPages "Params.images" "!=" nil) }}
    

    The above fetches regular pages not of page or about type unless they are pinned. And finally, we exclude all pages with no images set in Page params.

    See intersect for AND.

    truncate

    Since Go templates are HTML-aware, truncate will intelligently handle normal strings vs HTML strings:

    {{ "<em>Keep my HTML</em>" | safeHTML | truncate 10 }}` → <em>Keep my …</em>`
    

    {{% note %}}
    If you have a raw string that contains HTML tags you want to remain treated as HTML, you will need to convert the string to HTML using the safeHTML template function before sending the value to truncate. Otherwise, the HTML tags will be escaped when passed through the truncate function.
    {{% /note %}}

    trim

    {{ trim "++Batman--" "+-" }} → "Batman"
    

    trim requires the second argument, which tells the function specifically what to remove from the first argument. There is no default value for the second argument, so the following usage will not work:

    {{ trim .Inner}}
    

    Instead, the following example tells trim to remove extra new lines from the content contained in the shortcode .Inner variable:

    {{ trim .Inner "\n" }}
    

    {{% note %}}
    Go templates also provide a simple method for trimming whitespace from either side of a Go tag by including a hyphen (-).
    {{% /note %}}

    title

    {{title "BatMan"}}` → "Batman"
    

    time

    time converts a timestamp string into a time.Time structure so you can access its fields:

    {{ time "2016-05-28" }} → "2016-05-28T00:00:00Z"
    {{ (time "2016-05-28").YearDay }} → 149
    {{ mul 1000 (time "2016-05-28T10:30:00.00+10:00").Unix }} → 1464395400000, or Unix time in milliseconds
    

    Example: Using time to get Month Index

    The following example takes a UNIX timestamp—set as utimestamp: "1489276800" in a content’s front matter—converts the timestamp (string) to an integer using the int function, and then uses printf to convert the Month property of time into an index.

    The following example may be useful when setting up multilingual sites:

    {{< code file=“unix-to-month-integer.html” >}}
    {{$time := time (int .Params.addDate)}}
    => $time = 1489276800
    {{$time.Month}}
    => “March”
    {{$monthindex := printf “%d” $time.Month }}
    => $monthindex = 3
    {{< /code >}}

    substr

    It normally takes two parameters: start and length. It can also take one parameter: start, i.e. length is omitted, in which case the substring starting from start until the end of the string will be returned.

    To extract characters from the end of the string, use a negative start number.

    In addition, borrowing from the extended behavior described at http://php.net substr, if length is given and is negative, that number of characters will be omitted from the end of string.

    {{substr "BatMan" 0 -3}} → "Bat"
    {{substr "BatMan" 3 3}} → "Man"
    

    string

    • {{string "BatMan"}} → “BatMan”

    split

    • {{split "tag1,tag2,tag3" "," }} → [“tag1” “tag2” “tag3”]

    sort

    A sorted array of map values will be returned with the keys eliminated. There are two optional arguments: sortByField and sortAsc. If left blank, sort will sort by keys (for maps) in ascending order as its default behavior.

    +++
    #tags: [ "tag3", "tag1", "tag2" ]
    +++
    
    // Site config
    +++
    [params.authors]
      [params.authors.Derek]
        "firstName"  = "Derek"
        "lastName"   = "Perkins"
      [params.authors.Joe]
        "firstName"  = "Joe"
        "lastName"   = "Bergevin"
      [params.authors.Tanner]
        "firstName"  = "Tanner"
        "lastName"   = "Linsley"
    +++
    
    // Use default sort options - sort by key / ascending
    Tags: {{ range sort .Params.tags }}{{ . }} {{ end }}
    
    → Outputs Tags: tag1 tag2 tag3
    
    // Sort by value / descending
    Tags: {{ range sort .Params.tags "value" "desc" }}{{ . }} {{ end }}
    
    → Outputs Tags: tag3 tag2 tag1
    
    // Use default sort options - sort by value / descending
    Authors: {{ range sort .Site.Params.authors }}{{ .firstName }} {{ end }}
    
    → Outputs Authors: Derek Joe Tanner
    
    // Use default sort options - sort by value / descending
    Authors: {{ range sort .Site.Params.authors "lastName" "desc" }}{{ .lastName }} {{ end }}
    
    → Outputs Authors: Perkins Linsley Bergevin
    

    slicestr

    For example, 1 and 4 creates a slice including elements 1 through 3.
    The end index can be omitted; it defaults to the string’s length.

    • {{slicestr "BatMan" 3}} → “Man”
    • {{slicestr "BatMan" 0 3}} → “Bat”

    slice

    One use case is the concatenation of elements in combination with the delimit function:

    {{< code file=“slice.html” >}}
    {{ delimit (slice “foo” “bar” “buzz”) ", " }}

    {{< /code >}}

    singularize

    {{ "cats" | singularize }} → “cat”

    See also the .Data.Singular taxonomy variable for singularizing taxonomy names.

    shuffle

    {{< code file=“shuffle-input.html” >}}

    {{ shuffle (seq 1 5) }}
    {{ shuffle (slice "foo" "bar" "buzz") }}
    {{< /code >}}

    This example would return the following:

    {{< output file=“shuffle-output.html” >}}

    2 5 3 1 4
    buzz foo bar
    {{< /output >}}

    This example also makes use of the slice and seq functions.

    sha

    sha1 hashes the given input and returns its SHA1 checksum.

    {{ sha1 "Hello world, gophers!" }}
    <!-- returns the string "c8b5b0e33d408246e30f53e32b8f7627a7a649d4" -->
    

    sha256 hashes the given input and returns its SHA256 checksum.

    {{ sha256 "Hello world, gophers!" }}
    <!-- returns the string "6ec43b78da9669f50e4e422575c54bf87536954ccd58280219c393f2ce352b46" -->
    

    seq

    It’s named and used in the model of GNU’s seq.

    3 → 1, 2, 3
    1 2 4 → 1, 3
    -3 → -1, -2, -3
    1 4 → 1, 2, 3, 4
    1 -2 → 1, 0, -1, -2
    

    Example: seq with range and after

    You can use seq in combination with range and after. The following will return 19 elements:

    {{ range after 1 (seq 20)}}
    {{ end }}
    

    However, when ranging with an index, the following may be less confusing in that $indexStartingAt1 and $num will return 1,2,3 ... 20:

    {{ range $index, $num := (seq 20) }}
    $indexStartingAt1 := (add $index 1)
    {{ end }}
    

    .Scratch

    In most cases you can do well without Scratch, but there are some use cases that aren’t solvable with Go’s templates without Scratch’s help, due to scoping issues.

    Scratch is added to both Page and Shortcode – with following methods:

    • Set and Add takes a key and the value to add.
    • Get returns the value for the key given.
    • SetInMap takes a key, mapKey and value
    • GetSortedMapValues returns array of values from key sorted by mapKey

    Set and SetInMap can store values of any type.

    For single values, Add accepts values that support Go’s + operator. If the first Add for a key is an array or slice, the following adds will be appended to that list.

    The scope of the backing data is global for the given Page or Shortcode, and spans partial and shortcode includes.

    Note that .Scratch from a shortcode will return the shortcode’s Scratch, which in most cases is what you want. If you want to store it in the page scroped Scratch, then use .Page.Scratch.

    Sample usage

    The usage is best illustrated with some samples:

    {{ $.Scratch.Add "a1" 12 }}
    {{ $.Scratch.Get "a1" }} {{/* => 12 */}}
    {{ $.Scratch.Add "a1" 1 }}
    {{ $.Scratch.Get "a1" }} // {{/* => 13 */}}
    
    {{ $.Scratch.Add "a2" "AB" }}
    {{ $.Scratch.Get "a2" }} {{/* => AB */}}
    {{ $.Scratch.Add "a2" "CD" }}
    {{ $.Scratch.Get "a2" }} {{/* => ABCD */}}
    
    {{ $.Scratch.Add "l1" (slice "A" "B") }}
    {{ $.Scratch.Get "l1" }} {{/* => [A B]  */}}
    {{ $.Scratch.Add "l1" (slice "C" "D") }}
    {{ $.Scratch.Get "l1" }} {{/* => [A B C D] */}}
    
    {{ $.Scratch.Set "v1" 123 }}
    {{ $.Scratch.Get "v1" }}  {{/* => 123 */}}
    
    {{ $.Scratch.SetInMap "a3" "b" "XX" }}
    {{ $.Scratch.SetInMap "a3" "a" "AA" }}
    {{ $.Scratch.SetInMap "a3" "c" "CC" }}
    {{ $.Scratch.SetInMap "a3" "b" "BB" }}
    {{ $.Scratch.GetSortedMapValues "a3" }} {{/* => []interface {}{"AA", "BB", "CC"} */}}
    

    {{% note %}}
    The examples above uses the special $ variable, which refers to the top-level node. This is the behavior you most likely want, and will help remove some confusion when using Scratch inside page range loops – and you start inadvertently calling the wrong Scratch. But there may be use cases for {{ .Scratch.Add "key" "some value" }}.
    {{% /note %}}

    safeURL

    safeURL declares the provided string as a “safe” URL or URL substring (see RFC 3986). A URL like javascript:checkThatFormNotEditedBeforeLeavingPage() from a trusted source should go in the page, but by default dynamic javascript: URLs are filtered out since they are a frequently exploited injection vector.

    Without safeURL, only the URI schemes http:, https: and mailto: are considered safe by Go templates. If any other URI schemes (e.g., irc: and javascript:) are detected, the whole URL will be replaced with #ZgotmplZ. This is to “defang” any potential attack in the URL by rendering it useless.

    The following examples use a site config.toml with the following menu entry:

    {{< code file=“config.toml” copy=“false” >}}
    [[menu.main]]
    name = “IRC: #golang at freenode”
    url = “irc://irc.freenode.net/#golang”
    {{< /code >}}

    The following is an example of a sidebar partial that may be used in conjunction with the preceding front matter example:

    {{< code file=“layouts/partials/bad-url-sidebar-menu.html” copy=“false” >}}

    {{< /code >}}

    This partial would produce the following HTML output:

    {{< output file=“bad-url-sidebar-menu-output.html” >}}

    {{< /output >}}

    The odd output can be remedied by adding | safeURL to our .Title page variable:

    {{< code file=“layouts/partials/correct-url-sidebar-menu.html” copy=“false” >}}

    {{< /code >}}

    With the .URL page variable piped through safeURL, we get the desired output:

    {{< output file=“correct-url-sidebar-menu-output.html” >}}

    {{< /output >}}

    safeJS

    In this context, safe means the string encapsulates a known safe EcmaScript5 Expression (e.g., (x + y * z())).

    Template authors are responsible for ensuring that typed expressions do not break the intended precedence and that there is no statement/expression ambiguity as when passing an expression like { foo:bar() }\n['foo'](), which is both a valid expression and a valid program with a very different meaning.

    Example: Given hash = "619c16f" defined in the front matter of your .md file:

    • <script>var form_{{ .Params.hash | safeJS }};…</script><script>var form_619c16f;…</script>
    • <script>var form_{{ .Params.hash }};…</script><script>var form_"619c16f";…</script>

    safeHTMLAttr

    Example: Given a site-wide config.toml that contains this menu entry:

    [[menu.main]]
        name = "IRC: #golang at freenode"
        url = "irc://irc.freenode.net/#golang"
    
    • <a href="{{ .URL }}"><a href="#ZgotmplZ">
    • <a {{ printf "href=%q" .URL | safeHTMLAttr }}><a href="irc://irc.freenode.net/#golang">

    safeHTML

    It should not be used for HTML from a third-party, or HTML with unclosed tags or comments.

    Given a site-wide config.toml with the following copyright value:

    copyright = "© 2015 Jane Doe.  <a href=\"http://creativecommons.org/licenses/by/4.0/\">Some rights reserved</a>."
    

    {{ .Site.Copyright | safeHTML }} in a template would then output:

    © 2015 Jane Doe.  <a href="http://creativecommons.org/licenses/by/4.0/">Some rights reserved</a>.
    

    However, without the safeHTML function, html/template assumes .Site.Copyright to be unsafe and therefore escapes all HTML tags and renders the whole string as plain text:

    <p>© 2015 Jane Doe.  &lt;a href=&#34;http://creativecommons.org/licenses by/4.0/&#34;&gt;Some rights reserved&lt;/a&gt;.</p>
    

    safeCSS

    In this context, safe means CSS content that matches any of the following:

    1. The CSS3 stylesheet production, such as p { color: purple }.
    2. The CSS3 rule production, such as a[href=~"https:"].foo#bar.
    3. CSS3 declaration productions, such as color: red; margin: 2px.
    4. The CSS3 value production, such as rgba(0, 0, 255, 127).

    Example: Given style = "color: red;" defined in the front matter of your .md file:

    • <p style="{{ .Params.style | safeCSS }}">…</p><p style="color: red;">…</p>
    • <p style="{{ .Params.style }}">…</p><p style="ZgotmplZ">…</p>

    {{% note “ZgotmplZ” %}}
    “ZgotmplZ” is a special value that indicates that unsafe content reached a CSS or URL context.
    {{% /note %}}

    replaceRE

    {{ replaceRE "^https?://([^/]+).*" "$1" "http://gohugo.io/docs" }}` → "gohugo.io"
    {{ "http://gohugo.io/docs" | replaceRE "^https?://([^/]+).*" "$1" }}` → "gohugo.io"
    

    {{% note %}}
    Hugo uses Golang’s Regular Expression package, which is the same general syntax used by Perl, Python, and other languages but with a few minor differences for those coming from a background in PCRE. For a full syntax listing, see the GitHub wiki for re2.

    If you are just learning RegEx, or at least Golang’s flavor, you can practice pattern matching in the browser at https://regex101.com/.
    {{% /note %}}

    replace

    `{{ replace "Batman and Robin" "Robin" "Catwoman" }}`
    → "Batman and Catwoman"
    

    render

    The view is an alternative layout and should be a file name that points to a template in one of the locations specified in the documentation for Content Views.

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

    This example could render a piece of content using the content view located at /layouts/_default/summary.html:

    {{ range .Data.Pages }}
        {{ .Render "summary"}}
    {{ end }}
    

    relURL

    Both absURL and relURL consider the configured value of baseURL in your site’s config file. Given a baseURL set to http://example.com/hugo/:

    {{ "mystyle.css" | absURL }} → "http://example.com/hugo/mystyle.css"
    {{ "mystyle.css" | relURL }} → "/hugo/mystyle.css"
    {{ "http://gohugo.io/" | relURL }} →  "http://gohugo.io/"
    {{ "http://gohugo.io/" | absURL }} →  "http://gohugo.io/"
    

    The last two examples may look strange but can be very useful. For example, the following shows how to use absURL in JSON-LD structured data for SEO where some of your images for a piece of content may or may not be hosted locally:

    {{< code file=“layouts/partials/schemaorg-metadata.html” download=“schemaorg-metadata.html” >}}

    {{< /code >}}

    The above uses the apply function and also exposes how the Go template parser JSON-encodes objects inside <script> tags. See the safeJS template function for examples of how to tell Hugo not to escape strings inside of such tags.

    {{% note “Ending Slash” %}}
    absURL and relURL are smart about missing slashes, but they will not add a closing slash to a URL if it is not present.
    {{% /note %}}

    relref

    ref and relRef look up a content page by relative path (relref) or logical name (ref) to return the permalink. Both functions require a Page object (usually satisfied with a “.”):

    {{ relref . "about.md" }}
    

    These functions are used in two of Hugo’s built-in shortcodes. You can see basic usage examples of both ref and relref in the shortcode documentation.

    For an extensive explanation of how to leverage ref and relref for content management, see Cross References.

    relLangURL

    absLangURL and relLangURL functions are similar to their absURL and relURL relatives but will add the correct language prefix when the site is configured with more than one language. (See Configuring Multilingual.)

    So for a site baseURL set to http://example.com/hugo/ and the current language is en:

    {{ "blog/" | absLangURL }} → "http://example.com/hugo/en/blog/"
    {{ "blog/" | relLangURL }} → "/hugo/en/blog/"
    

    ref

    ref and relRef look up a content page by relative path (relref) or logical name (ref) to return the permalink. Both functions require a Page object (usually satisfied with a “.”):

    {{ relref . "about.md" }}
    

    These functions are used in two of Hugo’s built-in shortcodes. You can see basic usage examples of both ref and relref in the shortcode documentation.

    For an extensive explanation of how to leverage ref and relref for content management, see Cross References.

    readFile

    Note that the filename must be relative to the current project working directory.

    So, if you have a file with the name README.txt in the root of your project with the content Hugo Rocks!:

    {{readFile "README.txt"}} → "Hugo Rocks!"
    

    For more information on using readDir and readFile in your templates, see Local File Templates.

    readDir

    If your current project working directory has a single file named README.txt:

    {{ range (readDir ".") }}{{ .Name }}{{ end }} → "README.txt"
    

    For more information on using readDir and readFile in your templates, see Local File Templates.

    range

    Just like in the Go programming language, Go and Hugo templates make heavy use of range to iterate over a map, array or slice.

    range is fundamental to templating in Hugo. (See the Introduction to Hugo Templates for more examples.

    querify

    querify takes a set of key-value pairs and returns a query string that can be appended to a URL. E.g.

    The following example creates a link to a search results page on Google.

    <a href="https://www.google.com?{{ (querify "q" "test" "page" 3) | safeURL }}">Search</a>
    

    This example renders the following HTML:

    <a href="https://www.google.com?page=3&q=test">Search</a>
    

    printf

    See the go doc for additional information.

    {{ i18n ( printf "combined_%s" $var ) }}
    
    {{ printf "formatted %.2f" 3.1416 }}
    

    pluralize

    {{ "cat" | pluralize }} → "cats"
    

    plainify

    {{ "<b>BatMan</b>" | plainify }} → "BatMan"
    

    See also the .PlainWords, .Plain, and .RawContent page variables.

    partialCached

    The partialCached template function can offer significant performance gains for complex templates that don’t need to be re-rendered on every invocation. Here is the simplest usage:

    {{ partialCached "footer.html" . }}
    

    You can also pass additional parameters to partialCached to create variants of the cached partial. For example, if you have a complex partial that should be identical when rendered for pages within the same section, you could use a variant based upon section so that the partial is only rendered once per section:

    {{< code file=“partial-cached-example.html” >}}
    {{ partialCached “footer.html” . .Section }}
    {{< /code >}}

    If you need to pass additional parameters to create unique variants, you can pass as many variant parameters as you need:

    {{ partialCached "footer.html" . .Params.country .Params.province }}
    

    Note that the variant parameters are not made available to the underlying partial template. They are only use to create a unique cache key.

    .Param

    In Hugo, you can declare site-wide params (i.e. in your configuration), as well as params for individual pages.

    A common use case is to have a general value for the site and a more specific value for some of the pages (e.g., an image).

    You can use the .Param method to call these values into your template. The following will first look for an image param in a specific content’s front matter. If not found, Hugo will look for an image param in your site’s configuration:

    $.Param "image"
    

    {{% note %}}
    The Param method may not consider empty strings in a content’s front matter as “not found.” If you are setting preconfigured front matter fields to empty strings using Hugo’s archetypes, it may be best to use the default function instead of Param. See the related issue on GitHub.
    {{% /note %}}

    now

    See time.Time.

    For example, building your site on June 24, 2017 with the following templating:

    <div>
        <small>&copy; {{ now.Format "2006"}}</small>
    </div>
    

    Which will produce the following:

    <div>
        <small>&copy; 2017</small>
    </div>
    

    The above example uses the .Format function, which page includes a full listing of date formatting using Golang’s layout string.

    {{% note %}}
    Older Hugo themes may use the deprecated .Now (uppercase). Be sure to use the lowercase .now in your templating.
    {{% /note %}}

    ne

    {{ if ne .Section "blog" }}current{{ end }}
    

    md5

    {{ md5 "Hello world, gophers!" }}
    <!-- returns the string "b3029f756f98f79e7f1b7f1d1f0dd53b" -->
    

    This can be useful if you want to use Gravatar for generating a unique avatar:

    <img src="https://www.gravatar.com/avatar/{{ md5 "[email protected]" }}?s=100&d=identicon">
    

    Math

    There are 6 basic mathematical operators that can be used in Hugo templates:

    Function Description Example
    add Adds two integers. {{add 1 2}} → 3
    div Divides two integers. {{div 6 3}} → 2
    mod Modulus of two integers. {{mod 15 3}} → 0
    modBool Boolean of modulus of two integers. Evaluates to true if = 0. {{modBool 15 3}} → true
    mul Multiplies two integers. {{mul 2 3}} → 6
    sub Subtracts two integers. {{sub 3 2}} → 1

    Use add with Strings

    You can also use the add function with strings. You may like this functionality in many use cases, including creating new variables by combining page- or site-level variables with other strings.

    For example, social media sharing with Twitter Cards requires the following meta link in your site’s <head> to display Twitter’s [“Summary Card with Large Image”][twtsummary]:

    <meta name="twitter:image" content="http://example.com/images/my-twitter-image.jpg">
    

    Let’s assume you have an image field in the front matter of each of your content files:

    ---
    title: My Post
    image: my-post-image.jpg
    ---
    

    You can then concatenate the image value (string) with the path to your images directory in static and leverage a URL-related templating function for increased flexibility:

    {{< code file=“partials/head/twitter-card.html” >}}
    {{$socialimage := add “images/” .Params.image}}

    {{< /code >}}

    {{% note %}}
    The add example above makes use of the absURL function. absURL and its relative companion relURL is the recommended way to construct URLs in Hugo.
    {{% /note %}}

    [twtsummary]: https://dev.twitter.com/cards/types/summary-large-image

    markdownify

    {{ .Title | markdownify }}
    

    lt

    {{ if lt 5 10 }}true{{ end }}
    

    lower

    {{lower "BatMan"}} → "batman"
    

    len

    len is a built-in function in Golang that returns the length of a variable according to its type. From the Golang documentation:

    Array: the number of elements in v.

    Pointer to array: the number of elements in *v (even if v is nil).

    Slice, or map: the number of elements in v; if v is nil, len(v) is zero.

    String: the number of bytes in v.

    Channel: the number of elements queued (unread) in the channel buffer; if v is nil, len(v) is zero.

    len is also considered a fundamental function for Hugo templating.

    len Example 1: Longer Headings

    You may want to append a class to a heading according to the length of the string therein. The following templating checks to see if the title’s length is greater than 80 characters and, if so, adds a long-title class to the <h1>:

    {{< code file=“check-title-length.html” >}}

    {{.Title}}
    {{< /code >}}

    len Example 2: Counting Pages with where

    The following templating uses [where][] in conjunction with len to figure out the total number of content pages in a posts section:

    {{< code file=“how-many-posts.html” >}}
    {{ $posts := (where .Site.RegularPages “Section” “==” “post”) }}
    {{ $postCount := len $posts }}
    {{< /code >}}

    Note the use of .RegularPages, a site variable that counts all regular content pages but not the _index.md pages used to add front matter and content to list templates.

    [where]: /functions/where/

    le

    {{ if le 5 10 }}true{{ end }}
    

    last

    {{ range last 10 .Data.Pages }}
        {{ .Render "summary" }}
    {{ end }}
    

    jsonify

    {{ dict "title" .Title "content" .Plain | jsonify }}
    

    See also the .PlainWords, .Plain, and .RawContent page variables.

    isset

    Takes either a slice, array, or channel and an index or a map and a key as input.

    {{ if isset .Params "project_url" }} {{ index .Params "project_url" }}{{ end }}
    

    {{% warning %}}
    All site-level configuration keys are stored as lower case. Therefore, a myParam key-value set in your site configuration file needs to be accessed with {{if isset .Site.Params "myparam"}} and not with {{if isset .Site.Params "myParam"}}. Note that you can still access the same config key with .Site.Params.myParam or .Site.Params.myparam, for example, when using with.
    {{% /warning %}}

    .IsMenuCurrent

    Used in menu templates.

    intersect

    The elements supported are strings, integers, and floats (only float64).

    A useful example of intersect functionality is a “related posts” block. isset allows us to create a list of links to other posts that have tags that intersect with the tags in the current post.

    The following is an example of a “related posts” partial template that could be added to a single page template:

    {{< code file=“layouts/partials/related-posts.html” download=“related-posts.html” >}}

      {{ $page_link := .Permalink }} {{ $tags := .Params.tags }} {{ range .Site.Pages }} {{ $page := . }} {{ $has_common_tags := intersect $tags .Params.tags | len | lt 0 }} {{ if and $has_common_tags (ne $page_link $page.Permalink) }}
    • {{ $page.Title }}
    • {{ end }} {{ end }}
    {{< /code >}}

    This is also very useful to use as AND filters when combined with where:

    {{ $pages := where .Site.RegularPages "Type" "not in" (slice "page" "about") }}
    {{ $pages := $pages | union (where .Site.RegularPages "Params.pinned" true) }}
    {{ $pages := $pages | intersect (where .Site.RegularPages "Params.images" "!=" nil) }}
    

    The above fetches regular pages not of page or about type unless they are pinned. And finally, we exclude all pages with no images set in Page params.

    See union for OR.

    int

    Useful for turning strings into numbers.

    {{ int "123" }} → 123
    

    index

    From the Godocs:

    Returns the result of indexing its first argument by the following arguments. Thus “index x 1 2 3” is, in Go syntax, x13. Each indexed item must be a map, slice, or array.

    In Go templates, you can’t access array, slice, or map elements directly the same way you would in Go. For example, $.Site.Data.authors[.Params.authorkey] isn’t supported syntax.

    Instead, you have to use index, a function that handles the lookup for you.

    Example: Load Data from a Path Based on Front Matter Params

    Assume you want to add a location = "" field to your front matter for every article written in content/vacations/. You want to use this field to populate information about the location at the bottom of the article in your single.html template. You also have a directory in data/locations/ that looks like the following:

    .
    └── data
        └── locations
            ├── abilene.toml
            ├── chicago.toml
            ├── oslo.toml
            └── provo.toml
    

    Here is an example of the data inside data/locations/oslo.toml:

    website = "https://www.oslo.kommune.no"
    pop_city = 658390
    pop_metro = 1717900
    

    The example we will use will be an article on Oslo, which front matter should set to exactly the same name as the corresponding file name in data/locations/:

    title = "My Norwegian Vacation"
    location = "oslo"
    

    The content of oslo.toml can be accessed from your template using the following node path: .Site.Data.locations.oslo. However, the specific file you need is going to change according to the front matter.

    This is where the index function is needed. index takes 2 parameters in this use case:

    1. The node path
    2. A string corresponding to the desired data; e.g.—
    {{ index .Site.Data.locations “oslo” }}
    

    The variable for .Params.location is a string and can therefore replace oslo in the example above:

    {{ index .Site.Data.authors .Params.author }}
    => map[website:https://www.oslo.kommune.no pop_city:658390 pop_metro:1717900]
    

    Now the call will return the specific file according to the location specified in the content’s front matter, but you will likely want to write specific properties to the template. You can do this by continuing down the node path via dot notation (.):

    {{ (index .Site.Data.locations .Params.location).pop_city }}
    => 658390
    

    in

    The elements supported are strings, integers and floats, although only float64 will match as expected.

    In addition, in can also check if a substring exists in a string.

    {{ if in .Params.tags "Git" }}Follow me on GitHub!{{ end }}
    
    {{ if in "this string contains a substring" "substring" }}Substring found!{{ end }}
    

    {{ with (imageConfig "favicon.ico") }}
    favicon.ico: {{.Width}} x {{.Height}}
    {{ end }}
    

    i18n

    This translates a piece of content based on your i18n/en-US.yaml (and similar) files. You can use the go-i18n tools to manage your translations. The translations can exist in both the theme and at the root of your repository.

    {{ i18n "translation_id" }}
    

    {{% note “Alias T” %}}
    T is an alias to i18n. E.g. {{ T "translation_id" }}.
    {{% /note %}}

    For more information about string translations, see Translation of Strings in Multilingual Mode.

    humanize

    If the input is either an int64 value or the string representation of an integer, humanize returns the number with the proper ordinal appended.

    {{humanize "my-first-post"}} → "My first post"
    {{humanize "myCamelPost"}} → "My camel post"
    {{humanize "52"}} → "52nd"
    {{humanize 103}} → "103rd"
    

    htmlUnescape

    htmlUnescape returns the given string with HTML escape codes un-escaped.

    Remember to pass the output of this to safeHTML if fully un-escaped characters are desired. Otherwise, the output will be escaped again as normal.

    {{ htmlUnescape "Hugo &amp; Caddy &gt; Wordpress &amp; Apache" }} → "Hugo & Caddy > Wordpress & Apache"
    

    htmlEscape

    In the result & becomes &amp; and so on. It escapes only: <, >, &, ' and ".

    {{ htmlEscape "Hugo & Caddy > Wordpress & Apache" }} → "Hugo &amp; Caddy &gt; Wordpress &amp; Apache"
    

    highlight

    highlight is used in Hugo’s built-in highlight shortcode.

    See Installing Hugo for more information on Pygments or Syntax Highlighting for more options on how to add syntax highlighting to your code blocks with Hugo.

    .HasMenuCurrent

    Used in menu templates.

    .HasChildren

    Used in menu templates.

    hasprefix

    • {{ hasPrefix "Hugo" "Hu" }} → true

    gt

    {{ if gt 10 5 }}true{{ end }}
    

    getenv

    Takes a string containing the name of the variable as input. Returns
    an empty string if the variable is not set, otherwise returns the
    value of the variable.

    {{ getenv "HOME" }}
    

    {{% note %}}
    In Unix-like environments, the variable must also be exported in order to be seen by hugo.
    {{% /note %}}

    .Get

    .Get is specifically used when creating your own shortcode template.

    ge

    {{ if ge 10 5 }}true{{ end }}
    

    .Format

    .Format will format date values defined in your front matter and can be used as a property on the following page variables:

    • .PublishDate
    • .Date
    • .LastMod

    Assuming a key-value of date: 2017-03-03 in a content file’s front matter, your can run the date through .Format followed by a layout string for your desired output at build time:

    {{ .PublishDate.Format "January 2, 2006" }} => March 3, 2017
    

    For formatting any string representations of dates defined in your front matter, see the dateFormat function, which will still leverage the Golang layout string explained below but uses a slightly different syntax.

    Go’s Layout String

    Hugo templates format your dates via layout strings that point to a specific reference time:

    Mon Jan 2 15:04:05 MST 2006
    

    While this may seem arbitrary, the numerical value of MST is 07, thus making the layout string a sequence of numbers.

    Here is a visual explanation taken directly from the Go docs:

     Jan 2 15:04:05 2006 MST
    => 1 2  3  4  5    6  -7
    

    Hugo Date and Time Templating Reference

    The following examples show the layout string followed by the rendered output.

    The examples were rendered and tested in CST and all point to the same field in a content file’s front matter:

    date: 2017-03-03T14:15:59-06:00
    
    .Date (i.e. called via page variable)
    Returns: 2017-03-03 14:15:59 -0600 CST
    "Monday, January 2, 2006"
    Returns: Friday, March 3, 2017
    "Mon Jan 2 2006"
    Returns: Fri Mar 3 2017
    "January 2nd"
    Returns: March 3rd
    "January 2006"
    Returns: March 2017
    "2006-01-02"
    Returns: 2017-03-03
    "Monday"
    Returns: Friday
    "02 Jan 06 15:04 MST" (RFC822)
    Returns: 03 Mar 17 14:15 CST
    "02 Jan 06 15:04 -0700" (RFC822Z)
    Returns: 03 Mar 17 14:15 -0600
    "Mon, 02 Jan 2006 15:04:05 MST" (RFC1123)
    Returns: Fri, 03 Mar 2017 14:15:59 CST
    "Mon, 02 Jan 2006 15:04:05 -0700" (RFC339)
    Returns: Fri, 03 Mar 2017 14:15:59 -0600

    Cardinal Numbers and Ordinal Abbreviations

    Spelled-out cardinal numbers (e.g. “one”, “two”, and “three”) and ordinal abbreviations (i.e., with shorted suffixes like “1st”, “2nd”, and “3rd”) are not currently supported:

    {{.Date.Format "Jan 2nd 2006"}}
    

    Hugo assumes you want to append nd as a string to the day of the month and outputs the following:

    Mar 3nd 2017
    

    Use .Local and .UTC

    In conjunction with the dateFormat function, you can also convert your dates to UTC or to local timezones:

    {{ dateFormat "02 Jan 06 15:04 MST" .Date.UTC }}
    Returns: 03 Mar 17 20:15 UTC
    {{ dateFormat "02 Jan 06 15:04 MST" .Date.Local }}
    Returns: 03 Mar 17 14:15 CST

    first

    {{ range first 10 .Data.Pages }}
        {{ .Render "summary" }}
    {{ end }}
    

    findRE

    By default all matches will be included. The number of matches can be limitted with an optional third parameter.

    The example below returns a list of all second level headers (<h2>) in the content:

    {{ findRE "<h2.*?>(.|\n)*?</h2>" .Content }}
    

    You can limit the number of matches in the list with a third parameter. The following example shows how to limit the returned value to just one match (or none, if there are no matched substrings):

    {{ findRE "<h2.*?>(.|\n)*?</h2>" .Content 1 }}
        <!-- returns ["<h2 id="#foo">Foo</h2>"] -->
    

    {{% note %}}
    Hugo uses Golang’s Regular Expression package, which is the same general syntax used by Perl, Python, and other languages but with a few minor differences for those coming from a background in PCRE. For a full syntax listing, see the GitHub wiki for re2.

    If you are just learning RegEx, or at least Golang’s flavor, you can practice pattern matching in the browser at https://regex101.com/.
    {{% /note %}}

    eq

    {{ if eq .Section "blog" }}current{{ end }}
    

    emojify

    emoji runs a passed string through the Emoji emoticons processor.

    See the Emoji cheat sheet for available emoticons.

    The emojify function can be called in your templates but not directly in your content files by default. For emojis in content files, set enableEmoji to true in your site’s configuration. Then you can write emoji shorthand directly into your content files; e.g. I :heart: Hugo!:

    I ❤️ Hugo!

    echoParam

    {{ echoParam .Params "project_url" }}
    

    dict

    dict is especially useful for passing more than one value to a partial template.

    Example: dict with Embedded SVGs

    The partial below creates a SVG and expects fill height and width from the caller:

    {{< code file=“layouts/partials/svgs/external-links.svg” download=“external-links.svg” >}}



    {{< /code >}}

    These values can be stored in one object with dict and passed to the partial:

    {{< code file=“layouts/_default/list.html” >}}
    {{ partial “svg/link-ext.svg” (dict “fill” “#01589B” “size” 10 “width” 20 ) }}
    {{< /code >}}

    delimit

    delimit called in your template takes the form of

    {{ delimit array/slice/map delimiter optionallastdelimiter}}
    

    delimit loops through any array, slice, or map and returns a string of all the values separated by a delimiter, the second argument in the function call. There is an optional third parameter that lets you choose a different delimiter to go between the last two values in the loop.

    To maintain a consistent output order, maps will be sorted by keys and only a slice of the values will be returned.

    The examples of delimit that follow all use the same front matter:

    {{< code file=“delimit-example-front-matter.toml” nocopy=“true” >}}
    +++
    title: I love Delimit
    #tags: [ “tag1”, “tag2”, “tag3” ]
    +++
    {{< /code >}}

    {{< code file=“delimit-page-tags-input.html” >}}

    Tags: {{ delimit .Params.tags ", " }}

    {{< /code >}}

    {{< output file=“delimit-page-tags-output.html” >}}

    Tags: tag1, tag2, tag3

    {{< /output >}}

    Here is the same example but with the optional “last” delimiter:

    {{< code file=“delimit-page-tags-final-and-input.html” >}}
    Tags: {{ delimit .Params.tags ", " ", and " }}
    {{< /code >}}

    {{< output file=“delimit-page-tags-final-and-output.html” >}}

    Tags: tag1, tag2, and tag3

    {{< /output >}}

    default

    default checks whether a given value is set and returns a default value if it is not. Set in this context means different things depending on date type:

    • non-zero for numeric types and times
    • non-zero length for strings, arrays, slices, and maps
    • any boolean or struct value
    • non-nil for any other types

    default function examples reference the following content page:

    {{< code file=“content/posts/default-function-example.md” >}}

    title: Sane Defaults
    seo_title:
    date: 2017-02-18
    font:
    oldparam: The default function helps make your templating DRYer.
    newparam:

    {{< /code >}}

    default can be written in more than one way:

    {{ index .Params "font" | default "Roboto" }}
    {{ default "Roboto" (index .Params "font") }}
    

    Both of the above default function calls return Roboto.

    A default value, however, does not need to be hard coded like the previous example. The default value can be a variable or pulled directly from the front matter using dot notation:

    {{< code file=“variable-as-default-value.html” nocopy=“true” >}}
    {{$old := .Params.oldparam }}

    {{ .Params.newparam | default $old }}

    {{< /code >}}

    Which would return:

    <p>The default function helps make your templating DRYer.</p>
    

    And then using dot notation

    {{< code file=“dot-notation-default-value.html” >}}

    {{ .Params.seo_title | default .Title }} {{< /code >}}

    Which would return

    {{< output file=“dot-notation-default-return-value.html” >}}

    Sane Defaults {{< /output >}}

    The following have equivalent return values but are far less terse. This demonstrates the utility of default:

    Using if:

    {{< code file=“if-instead-of-default.html” nocopy=“true” >}}

    {{if .Params.seo_title}}{{.Params.seo_title}}{{else}}{{.Title}}{{end}} => Sane Defaults {{< /code >}}

    Using with:

    {{< code file=“with-instead-of-default.html” nocopy=“true” >}}

    {{with .Params.seo_title}}{{.}}{{else}}{{.Title}}{{end}} => Sane Defaults {{< /code >}}

    dateFormat

    dateFormat converts the textual representation of the datetime into the specified format or returns it as a Go time.Time type value. These are formatted with the layout string.

    {{ dateFormat "Monday, Jan 2, 2006" "2015-01-21" }} → "Wednesday, Jan 21, 2015"
    

    {{% warning %}}
    As of v0.19 of Hugo, the dateFormat function is not supported as part of Hugo’s multilingual feature.
    {{% /warning %}}

    See the Format function for a more complete list of date formatting options in your templates.

    countwords

    The template function works similar to the .WordCount page variable.

    {{ "Hugo is a static site generator." | countwords }}
    <!-- outputs a content length of 6 words.  -->
    

    countrunes

    In contrast with countwords function, which counts every word in a string, the countrunes function determines the number of runes in the content and excludes any whitespace. This has specific utility if you are dealing with CJK-like languages.

    {{ "Hello, 世界" | countrunes }}
    <!-- outputs a content length of 8 runes. -->
    

    chomp

    Useful in a pipeline to remove newlines added by other processing (e.g., markdownify).

    {{chomp "<p>Blockhead</p>\n"}} → "<p>Blockhead</p>"
    

    base64

    An example:

    {{< code file=“base64-input.html” >}}

    Hello world = {{ "Hello world" | base64Encode }}

    SGVsbG8gd29ybGQ = {{ "SGVsbG8gd29ybGQ=" | base64Decode }}

    {{< /code >}}

    {{< output file=“base-64-output.html” >}}

    Hello world = SGVsbG8gd29ybGQ=

    SGVsbG8gd29ybGQ = Hello world

    {{< /output >}}

    You can also pass other data types as arguments to the template function which tries to convert them. The following will convert 42 from an integer to a string because both base64Encode and base64Decode always return a string.

    {{ 42 | base64Encode | base64Decode }}
    => "42" rather than 42
    

    base64 with APIs

    Using base64 to decode and encode becomes really powerful if we have to handle
    responses from APIs.

    {{ $resp := getJSON "https://api.github.com/repos/gohugoio/hugo/readme"  }}
    {{ $resp.content | base64Decode | markdownify }}
    

    The response of the GitHub API contains the base64-encoded version of the README.md in the Hugo repository. Now we can decode it and parse the Markdown. The final output will look similar to the rendered version on GitHub.

    apply

    {{< todo >}}

    {{< /todo >}}

    apply expects at least three parameters, depending on the function being applied.

    1. The first parameter is the sequence to operate on
    2. The second parameter is the name of the function as a string, which must be the name of a valid Hugo function.
    3. After that, the parameters to the applied function are provided, with the string "." standing in for each element of the sequence the function is to be applied against.

    Here is an example of a content file with name: as a front matter field:

    +++
    names: [ "Derek Perkins", "Joe Bergevin", "Tanner Linsley" ]
    +++
    

    You can then use apply as follows:

    {{ apply .Params.names "urlize" "." }}
    

    Which will result as follows:

    "derek-perkins", "joe-bergevin", "tanner-linsley"
    

    This is roughly equivalent to using the following with range

    {{ range .Params.names }}{{ . | urlize }}{{ end }}
    

    However, it isn’t possible to provide the output of a range to the delimit function, so you need to apply it.

    If you have post-tag-list.html and post-tag-link.html as partials, you could use the following snippets, respectively:

    {{< code file=“layouts/partial/post-tag-list.html” copy=“false” >}}
    {{ with .Params.tags }}

    Tags: {{ $len := len . }} {{ if eq $len 1 }} {{ partial "post/tag/link" (index . 0) }} {{ else }} {{ $last := sub $len 1 }} {{ range first $last . }} {{ partial "post/tag/link" . }}, {{ end }} {{ partial "post/tag/link" (index . $last) }} {{ end }}
    {{ end }} {{< /code >}}

    {{< code file=“layouts/partial/post-tag-link.html” copy=“false” >}}

    {{< /code >}}

    This works, but the complexity of post-tag-list.html is fairly high. The Hugo template needs to perform special behavior for the case where there’s only one tag, and it has to treat the last tag as special. Additionally, the tag list will be rendered something like Tags: tag1 , tag2 , tag3 because of the way that the HTML is generated and then interpreted by a browser.

    This first version of layouts/partials/post-tag-list.html separates all of the operations for ease of reading. The combined and DRYer version is shown next:

    {{ with .Params.tags }}
        <div class="tags-list">
          Tags:
          {{ $sort := sort . }}
          {{ $links := apply $sort "partial" "post-tag-link" "." }}
          {{ $clean := apply $links "chomp" "." }}
          {{ delimit $clean ", " }}
        </div>
    {{ end }}
    

    Now in the completed version, you can sort the tags, convert the tags to links with layouts/partials/post-tag-link.html, chomp off stray newlines, and join the tags together in a delimited list for presentation. Here is an even DRYer version of the preceding example:

    {{< code file=“layouts/partials/post-tag-list.html” download=“post-tag-list.html” >}}
    {{ with .Params.tags }}


    Tags:
    {{ delimit (apply (apply (sort .) “partial” “post-tag-link” “.”) “chomp” “.”) ", " }}

    {{ end }}
    {{< /code >}}

    {{% note %}}
    apply does not work when receiving the sequence as an argument through a pipeline.
    {{% /note %}}

    after

    The following shows after being used in conjunction with the slice function:

    {{ $data := slice "one" "two" "three" "four" }}
    {{ range after 2 $data }}
        {{ . }}
    {{ end }}
    → ["three", "four"]
    

    Example of after with first: 2nd–4th Most Recent Articles

    You can use after in combination with the first function and Hugo’s powerful sorting methods. Let’s assume you have a list page at example.com/articles. You have 10 articles, but you want your templating for the list/section page to show only two rows:

    1. The top row is titled “Featured” and shows only the most recently published article (i.e. by publishdate in the content files’ front matter).
    2. The second row is titled “Recent Articles” and shows only the 2nd- to 4th-most recently published articles.

    {{< code file=“layouts/section/articles.html” download=“articles.html” >}}
    {{ define “main” }}

    Featured Article

    {{ range first 1 .Data.Pages.ByPublishDate.Reverse }}

    {{.Title}}

    {{.Description}}

    {{ end }}

    Recent Articles

    {{ range first 3 (after 1 .Data.Pages.ByPublishDate.Reverse) }}

    {{.Title}}

    {{.Description}}

    {{ end }}
    {{ end }} {{< /code >}}

    .AddDate

    The AddDate function takes three arguments in logical order of years, months, and days.

    Example: Randomized Tweets from the Last 2 Years

    Let’s assume you have a file at data/tweets.toml that contains a list of Tweets to display on your site’s homepage. The file is filled with [[tweet]] blocks; e.g.—

    [[tweet]]
    name = "Steve Francia"
    twitter_handle = "@spf13"
    quote = "I'm creator of Hugo. #metadocreference"
    link = "https://twitter.com/spf13"
    date = "2017-01-07T00:00:00Z"
    

    Let’s assume you want to grab Tweets from the last two years and present them in a random order. In conjunction with the where and now functions, you can limit our range to the last two years via now.AddDate -2 0 0, which represents a point in time 2 years, 0 days, and 0 hours before the time of your last site build.

    {{< code file=“partials/templates/random-tweets.html” download=“tweets.html” >}}
    {{ range where $.Site.Data.tweets.tweet “date” “ge” (now.AddDate -2 0 0) | shuffle }}




    {{ .quote | safeHTML }}


    — {{ .name }} ({{ .twitter_handle }})
    {{ dateFormat “January 2, 2006” .date }}



    {{ end }}
    {{< /code >}}

    absURL

    Both absURL and relURL consider the configured value of baseURL in your site’s config file. Given a baseURL set to http://example.com/hugo/:

    {{ "mystyle.css" | absURL }} → "http://example.com/hugo/mystyle.css"
    {{ "mystyle.css" | relURL }} → "/hugo/mystyle.css"
    {{ "http://gohugo.io/" | relURL }} →  "http://gohugo.io/"
    {{ "http://gohugo.io/" | absURL }} →  "http://gohugo.io/"
    

    The last two examples may look strange but can be very useful. For example, the following shows how to use absURL in JSON-LD structured data (SEO), where some of your images for a piece of content may or may not be hosted locally:

    {{< code file=“layouts/partials/schemaorg-metadata.html” download=“schemaorg-metadata.html” >}}

    {{< /code >}}

    The above uses the apply function and also exposes how the Go template parser JSON-encodes objects inside <script> tags. See the safeJS template function for examples of how to tell Hugo not to escape strings inside of such tags.

    {{% note “Ending Slash” %}}
    absURL and relURL are smart about missing slashes, but they will not add a closing slash to a URL if it is not present.
    {{% /note %}}

    absLangURL

    Both absLangURL and relLangURL are similar to their absURL and relURL relatives but will add the correct language prefix when the site is configured with more than one language.

    So for a site baseURL set to http://example.com/hugo/ and the current language is en:

    {{ "blog/" | absLangURL }} → "http://example.com/hugo/en/blog/"
    {{ "blog/" | relLangURL }} → "/hugo/en/blog/"
    

    lang.NumFmt

    The default options value is - . ,.

    Numbers greater than or equal to 5 are rounded up. For example, if precision is set to 0, 1.5 becomes 2, and 1.4 becomes 1.

    {{ lang.NumFmt "," "." "-" 2 12345.6789 }} → 12.345,68
    {{ lang.NumFmt "." "" "-" 6 -12345.6789 }} → -12345.678900
    {{ lang.NumFmt "." "," "-" 0 -12345.6789 }} → -12,346
    {{ -98765.4321 | lang.NumFmt "." "," "-" 2 }} → -98,765.43
    

    .GetPage

    Every Page has a Kind attribute that shows what kind of page it is. While this attribute can be used to list pages of a certain kind using where, often it can be useful to fetch a single page by its path.

    .GetPage looks up a page of a given Kind and path.

    {{ with .Site.GetPage "section" "blog" }}{{ .Title }}{{ end }}
    

    This method wil return nil when no page could be found, so the above will not print anything if the blog section isn’t found.

    For a regular page:

    {{ with .Site.GetPage "page" "blog" "my-post.md" }}{{ .Title }}{{ end }}
    

    Note that the path can also be supplied like this:

    {{ with .Site.GetPage "page" "blog/my-post.md" }}{{ .Title }}{{ end }}
    

    The valid page kinds are: page, home, section, taxonomy and taxonomyTerm.

    .GetPage Example

    This code snippet—in the form of a partial template—allows you to do the following:

    1. Grab the index object of your tags taxonomy.
    2. Assign this object to a variable, $t
    3. Sort the terms associated with the taxonomy by popularity.
    4. Grab the top two most popular terms in the taxonomy (i.e., the two most popular tags assigned to content.

    {{< code file=“grab-top-two-tags.html” >}}

    {{< /code >}}

    Variables and Params

    Hugo’s templates are context aware and make a large number of values available to you as you’re creating views for your website.

    Site Variables

    The following is a list of site-level (aka “global”) variables. Many of these variables are defined in your site’s configuration file, whereas others are built into Hugo’s core for convenient usage in your templates.

    Site Variables List

    .Site.AllPages
    array of all pages, regardless of their translation.
    .Site.Author
    a map of the authors as defined in the site configuration.
    .Site.BaseURL
    the base URL for the site as defined in the site configuration.
    .Site.BuildDrafts
    a boolean (default: false) to indicate whether to build drafts as defined in the site configuration.
    .Site.Copyright
    a string representing the copyright of your website as defined in the site configuration.
    .Site.Data
    custom data, see Data Templates.
    .Site.DisqusShortname
    a string representing the shortname of the Disqus shortcode as defined in the site configuration.
    .Site.Files
    all source files for the Hugo website.
    .Site.GoogleAnalytics
    a string representing your tracking code for Google Analytics as defined in the site configuration.
    .Site.IsMultiLingual
    whether there are more than one language in this site. See Multilingual for more information.
    .Site.Language.Lang
    the language code of the current locale (e.g., en).
    .Site.Language.LanguageName
    the full language name (e.g. English).
    .Site.Language.Weight
    the weight that defines the order in the .Site.Languages list.
    .Site.Language
    indicates the language currently being used to render the website. This object’s attributes are set in site configurations’ language definition.
    .Site.LanguageCode
    a string representing the language as defined in the site configuration. This is mostly used to populate the RSS feeds with the right language code.
    .Site.LanguagePrefix
    this can be used to prefix URLs to point to the correct language. It will even work when only one defined language. See also the functions absLangURL and relLangURL.
    .Site.Languages
    an ordered list (ordered by defined weight) of languages.
    .Site.LastChange
    a string representing the date/time of the most recent change to your site. This string is based on the date variable in the front matter of your content pages.
    .Site.Menus
    all of the menus in the site.
    .Site.Pages
    array of all content ordered by Date with the newest first. This array contains only the pages in the current language.
    .Site.Permalinks
    a string to override the default permalink format as defined in the site configuration.
    .Site.RegularPages
    a shortcut to the regular page collection. .Site.RegularPages is equivalent to where .Site.Pages "Kind" "page".
    .Site.RSSLink
    the URL for the site RSS.
    .Site.Sections
    top-level directories of the site.
    .Site.Taxonomies
    the taxonomies for the entire site. Replaces the now-obsolete .Site.Indexes since v0.11. Also see section Taxonomies elsewhere.
    .Site.Title
    a string representing the title of the site.

    The .Site.Params Variable

    .Site.Params is a container holding the values from the params section of your site configuration.

    Example: .Site.Params

    The following config.toml defines a site-wide param for description:

    baseURL = "http://yoursite.example.com/"
    
    [params]
      description = "Tesla's Awesome Hugo Site"
      author = "Nikola Tesla"
    

    You can use .Site.Params in a partial template to call the default site description:

    {{< code file=“layouts/partials/head.html” >}}

    {{< /code >}}

    config: /getting-started/configuration/

    Shortcode Variables

    Shortcodes have access to parameters delimited in the shortcode declaration via .Get, page- and site-level variables, and also the following shortcode-specific fields:

    .Parent
    provides access to the parent shortcode context in nested shortcodes. This can be very useful for inheritance of common shortcode parameters from the root.
    .IsNamedParams
    boolean that returns true when the shortcode in question uses named rather than positional parameters
    .Inner
    represents the content between the opening and closing shortcode tags when a closing shortcode is used

    Page Variables

    The following is a list of page-level variables. Many of these will be defined in the front matter, derived from file location, or extracted from the content itself.

    {{% note “.Scratch” %}}
    See .Scratch for page-scoped, writable variables.
    {{% /note %}}

    Page Variables

    .AlternativeOutputFormats
    contains all alternative formats for a given page; this variable is especially useful link rel list in your site’s <head>. (See Output Formats.)
    .Content
    the content itself, defined below the front matter.
    .Data
    the data specific to this type of page.
    .Date
    the date associated with the page; .Date pulls from the date field in a content’s front matter. See also .ExpiryDate, .PublishDate, and .Lastmod.
    .Description
    the description for the page.
    .Draft
    a boolean, true if the content is marked as a draft in the front matter.
    .ExpiryDate
    the date on which the content is scheduled to expire; .ExpiryDate pulls from the expirydate field in a content’s front matter. See also .PublishDate, .Date, and .Lastmod.
    .FuzzyWordCount
    the approximate number of words in the content.
    .Hugo
    see Hugo Variables.
    .IsHome
    true in the context of the homepage.
    .IsNode
    always false for regular content pages.
    .IsPage
    always true for regular content pages.
    .IsTranslated
    true if there are translations to display.
    .Keywords
    the meta keywords for the content.
    .Kind
    the page’s kind. Possible return values are page, home, section, taxonomy, or taxonomyTerm. Note that there are also RSS, sitemap, robotsTXT, and 404 kinds, but these are only available during the rendering of each of these respective page’s kind and therefore not available in any of the Pages collections.
    .Lang
    language taken from the language extension notation.
    .Language
    a language object that points to the language’s definition in the site
    config.
    .Lastmod
    the date the content was last modified; .Lastmod pulls from the lastmod field in a content’s front matter. If lastmod is not set, Hugo will default to the date field. See also .ExpiryDate, .Date, and .PublishDate.
    .LinkTitle
    access when creating links to the content. If set, Hugo will use the linktitle from the front matter before title.
    .Next
    pointer to the following content (based on the publishdate field in front matter).
    .NextInSection
    pointer to the following content within the same section (based on publishdate field in front matter).
    .OutputFormats
    contains all formats, including the current format, for a given page. Can be combined the with .Get function to grab a specific format. (See Output Formats.)
    .Pages
    a collection of associated pages. This value will be nil for regular content pages. .Pages is an alias for .Data.Pages.
    .Permalink
    the Permanent link for this page; see Permalinks
    .Plain
    the Page content stripped of HTML tags and presented as a string.
    .PlainWords
    the Page content stripped of HTML as a []string using Go’s strings.Fields to split .Plain into a slice.
    .Prev
    Pointer to the previous content (based on publishdate in front matter).
    .PrevInSection
    Pointer to the previous content within the same section (based on publishdate in front matter). For example, {{if .PrevInSection}}{{.PrevInSection.Permalink}}{{end}}.
    .PublishDate
    the date on which the content was or will be published; .Publishdate pulls from the publishdate field in a content’s front matter. See also .ExpiryDate, .Date, and .Lastmod.
    .RSSLink
    link to the taxonomies’ RSS link.
    .RawContent
    raw markdown content without the front matter. Useful with remarkjs.com
    .ReadingTime
    the estimated time, in minutes, it takes to read the content.
    .Ref
    returns the permalink for a given reference (e.g., .Ref "sample.md"). .Ref does not handle in-page fragments correctly. See Cross References.
    .RelPermalink
    the relative permanent link for this page.
    .RelRef
    returns the relative permalink for a given reference (e.g., RelRef "sample.md"). .RelRef does not handle in-page fragments correctly. See Cross References.
    .Section
    the section this content belongs to.
    .Site
    see Site Variables.
    .Summary
    a generated summary of the content for easily showing a snippet in a summary view. The breakpoint can be set manually by inserting <!--more--> at the appropriate place in the content page. See Content Summaries for more details.
    .TableOfContents
    the rendered table of contents for the page.
    .Title
    the title for this page.
    .Translations
    a list of translated versions of the current page. See Multilingual Mode for more information.
    .Truncated
    a boolean, true if the .Summary is truncated. Useful for showing a “Read more…” link only when necessary. See Summaries for more information.
    .Type
    the content type of the content (e.g., post).
    .URL
    the URL for the page relative to the web root. Note that a url set directly in front matter overrides the default relative URL for the rendered page.
    .UniqueID
    the MD5-checksum of the content file’s path.
    .Weight
    assigned weight (in the front matter) to this content, used in sorting.
    .WordCount
    the number of words in the content.

    Page-level Params

    Any other value defined in the front matter in a content file, including taxonomies, will be made available as part of the .Params variable.

    ---
    title: My First Post
    date: date: 2017-02-20T15:26:23-06:00
    categories: [one]
    #tags: [two,three,four]
    

    With the above front matter, the tags and categories taxonomies are accessible via the following:

    • .Params.tags
    • .Params.categories

    {{% note “Casing of Params” %}}
    Page-level .Params are only accessible in lowercase.
    {{% /note %}}

    The .Params variable is particularly useful for the introduction of user-defined front matter fields in content files. For example, a Hugo website on book reviews could have the following front matter in /content/review/book01.md:

    ---
    ...
    affiliatelink: "http://www.my-book-link.here"
    recommendedby: "My Mother"
    ...
    ---
    

    These fields would then be accessible to the /themes/yourtheme/layouts/review/single.html template through .Params.affiliatelink and .Params.recommendedby, respectively.

    Two common situations where this type of front matter field could be introduced is as a value of a certain attribute like href="" or by itself to be displayed as text to the website’s visitors.

    {{< code file=“/themes/yourtheme/layouts/review/single.html” >}}

    Buy this book

    It was recommended by {{ .Params.recommendedby }}.

    {{< /code >}}

    This template would render as follows, assuming you’ve set uglyURLs to false in your site config:

    {{< output file=“yourbaseurl/review/book01/index.html” >}}

    Buy this book

    It was recommended by my Mother.

    {{< /output >}}

    {{% note %}}
    See Archetypes for consistency of Params across pieces of content.
    {{% /note %}}

    The .Param Method

    In Hugo, you can declare params in individual pages and globally for your entire website. A common use case is to have a general value for the site param and a more specific value for some of the pages (i.e., a header image):

    {{ $.Param "header_image" }}
    

    The .Param method provides a way to resolve a single value according to it’s definition in a page parameter (i.e. in the content’s front matter) or a site parameter (i.e., in your config).

    Access Nested Fields in Front Matter

    When front matter contains nested fields like the following:

    ---
    author:
      given_name: John
      family_name: Feminella
      display_name: John Feminella
    ---
    

    .Param can access these fields by concatenating the field names together with a dot:

    {{ $.Param "author.display_name" }}
    

    If your front matter contains a top-level key that is ambiguous with a nested key, as in the following case:

    ---
    favorites.flavor: vanilla
    favorites:
      flavor: chocolate
    ---
    

    The top-level key will be preferred. Therefore, the following method, when applied to the previous example, will print vanilla and not chocolate:

    {{ $.Param "favorites.flavor" }}
    => vanilla
    

    Taxonomy Variables

    Taxonomy Terms Page Variables

    [Taxonomy terms pages][taxonomytemplates] are of the type Page and have the following additional variables.

    For example, the following fields would be available in layouts/_defaults/terms.html, depending on how you organize your [taxonomy templates][taxonomytemplates]:

    .Data.Singular
    The singular name of the taxonomy (e.g., tags => tag`)
    .Data.Plural
    The plural name of the taxonomy (e.g., tags => tags)
    .Data.Pages
    The list of pages in the taxonomy
    .Data.Terms
    The taxonomy itself
    .Data.Terms.Alphabetical
    The taxonomy terms alphabetized
    .Data.Terms.ByCount
    The Terms ordered by popularity

    Note that .Data.Terms.Alphabetical and .Data.Terms.ByCount can also be reversed:

    • .Data.Terms.Alphabetical.Reverse
    • .Data.Terms.ByCount.Reverse

    Use .Site.Taxonomies Outside of Taxonomy Templates

    The .Site.Taxonomies variable holds all the taxonomies defined site-wide. .Site.Taxonomies is a map of the taxonomy name to a list of its values (e.g., `“tags” -> [“tag1”, “tag2”, “tag3”]``). Each value, though, is not a string but rather a Taxonomy variable.

    The .Taxonomy Variable

    The .Taxonomy variable, available, for example, as .Site.Taxonomies.tags, contains the list of tags (values) and, for each tag, their corresponding content pages.

    Example Usage of .Site.Taxonomies

    The following partial template will list all your site’s taxonomies, each of their keys, and all the content assigned to each of the keys. For more examples of how to order and render your taxonomies, see [Taxonomy Templates][taxonomytemplates].

    {{< code file=“all-taxonomies-keys-and-pages.html” download=“all-taxonomies-keys-and-pages.html” >}}

      {{ range $taxonomyname, $taxonomy := .Site.Taxonomies }}
    • {{ $taxonomyname }}
        {{ range $key, $value := $taxonomy }}
      • {{ $key }}
      • {{ end }}
    • {{ end }}
    {{< /code >}}

    [taxonomytemplates]: /templates/taxonomy-templates/

    File Variables

    {{% note “Rendering Local Files” %}}
    For information on creating shortcodes and templates that tap into Hugo’s file-related feature set, see Local File Templates.
    {{% /note %}}

    The .File object contains the following fields:

    .File.Path
    the original relative path of the page (e.g., content/posts/foo.en.md)
    .File.LogicalName
    the name of the content file that represents a page (e.g., foo.en.md)
    .File.TranslationBaseName
    the filename without extension or optional language identifier (e.g., foo)
    .File.BaseFileName
    the filename without extension (e.g., foo.en)
    .File.Ext
    the file extension of the content file (e.g., md); this can also be called using .File.Extension as well. Note that it is only the extension without ..
    .File.Lang
    the language associated with the given file if Hugo’s Multilingual features are enabled (e.g., en)
    .File.Dir
    given the path content/posts/dir1/dir2/, the relative directory path of the content file will be returned (e.g., posts/dir1/dir2/)

    Multilingual: /content-management/multilingual/

    Menu Variables

    The [menu template][] has the following properties:

    .URL
    string
    .Name
    string
    .Menu
    string
    .Identifier
    string
    .Pre
    template.HTML
    .Post
    template.HTML
    .Weight
    int
    .Parent
    string
    .Children
    Menu

    [menu template]: /templates/menu-templates/

    Hugo-specific Variables

    It contains the following fields:

    .Hugo.Generator
    <meta> tag for the version of Hugo that generated the site. .Hugo.Generator outputs a complete HTML tag; e.g. <meta name="generator" content="Hugo 0.18" />
    .Hugo.Version
    the current version of the Hugo binary you are using e.g. 0.13-DEV
    .Hugo.CommitHash
    the git commit hash of the current Hugo binary e.g. 0e8bed9ccffba0df554728b46c5bbf6d78ae5247
    .Hugo.BuildDate
    the compile date of the current Hugo binary formatted with RFC 3339 e.g. 2002-10-02T10:00:00-05:00

    {{% note “Use the Hugo Generator Tag” %}}
    We highly recommend using .Hugo.Generator in your website’s <head>. .Hugo.Generator is included by default in all themes hosted on themes.gohugo.io. The generator tag allows the Hugo team to track the usage and popularity of Hugo.
    {{% /note %}}

    Git Info Variables

    {{% note “.GitInfo Performance Considerations” %}}
    Hugo’s Git integrations should be fairly performant but can increase your build time. This will depend on the size of your Git history.
    {{% /note %}}

    .GitInfo Prerequisites

    1. The Hugo site must be in a Git-enabled directory.
    2. The Git executable must be installed and in your system PATH.
    3. The .GitInfo feature must be enabled in your Hugo project by passing --enableGitInfo flag on the command line or by setting enableGitInfo to true in your site’s configuration file.

    The .GitInfo Object

    The GitInfo object contains the following fields:

    .AbbreviatedHash
    the abbreviated commit hash (e.g., 866cbcc)
    .AuthorName
    the author’s name, respecting .mailmap
    .AuthorEmail
    the author’s email address, respecting .mailmap
    .AuthorDate
    the author date
    .Hash
    the commit hash (e.g., 866cbccdab588b9908887ffd3b4f2667e94090c3)
    .Subject
    commit message subject (e.g., tpl: Add custom index function)

    Sitemap Variables

    A sitemap is a Page and therefore has all the page variables available to use sitemap templates. They also have the following sitemap-specific variables available to them:

    .Sitemap.ChangeFreq
    the page change frequency
    .Sitemap.Priority
    the priority of the page
    .Sitemap.Filename
    the sitemap filename

    pagevars: /variables/page/

    Command Line Reference

    The following list contains auto-generated and up-to-date (thanks to Cobra) documentation for all the CLI commands in Hugo.

    “hugo version”

    hugo version

    Print the version number of Hugo

    Synopsis

    All software has versions. This is Hugo’s.

    hugo version [flags]
    

    Options

      -h, --help   help for version
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo - hugo builds your site
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo undraft”

    hugo undraft

    Undraft resets the content’s draft status

    Synopsis

    Undraft resets the content’s draft status
    and updates the date to the current date and time.
    If the content’s draft status is ‘False’, nothing is done.

    hugo undraft path/to/content [flags]
    

    Options

      -h, --help   help for undraft
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo - hugo builds your site
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo server”

    hugo server

    A high performance webserver

    Synopsis

    Hugo provides its own webserver which builds and serves the site.
    While hugo server is high performance, it is a webserver with limited options.
    Many run it in production, but the standard behavior is for people to use it
    in development and use a more full featured server such as Nginx or Caddy.

    ‘hugo server’ will avoid writing the rendered and served content to disk,
    preferring to store it in memory.

    By default hugo will also watch your files for any changes you make and
    automatically rebuild the site. It will then live reload any open browser pages
    and push the latest content to them. As most Hugo sites are built in a fraction
    of a second, you will be able to save and see your changes nearly instantly.

    hugo server [flags]
    

    Options

          --appendPort                 append port to baseURL (default true)
      -b, --baseURL string             hostname (and path) to the root, e.g. http://spf13.com/
          --bind string                interface to which the server will bind (default "127.0.0.1")
      -D, --buildDrafts                include content marked as draft
      -E, --buildExpired               include expired content
      -F, --buildFuture                include content with publishdate in the future
          --cacheDir string            filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/
          --canonifyURLs               if true, all relative URLs will be canonicalized using baseURL
          --cleanDestinationDir        remove files from destination not found in static directories
      -c, --contentDir string          filesystem path to content directory
      -d, --destination string         filesystem path to write files to
          --disable404                 do not render 404 page
          --disableKinds stringSlice   disable different kind of pages (home, RSS etc.)
          --disableLiveReload          watch without enabling live browser reload on rebuild
          --disableRSS                 do not build RSS files
          --disableSitemap             do not build Sitemap file
          --enableGitInfo              add Git revision, date and author info to the pages
          --forceSyncStatic            copy all files when static is changed.
      -h, --help                       help for server
          --i18n-warnings              print missing translations
          --ignoreCache                ignores the cache directory
      -l, --layoutDir string           filesystem path to layout directory
          --meminterval string         interval to poll memory usage (requires --memstats), valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". (default "100ms")
          --memstats string            log memory usage to this file
          --navigateToChanged          navigate to changed content file on live browser reload
          --noChmod                    don't sync permission mode of files
          --noTimes                    don't sync modification time of files
          --pluralizeListTitles        pluralize titles in lists using inflect (default true)
      -p, --port int                   port on which the server will listen (default 1313)
          --preserveTaxonomyNames      preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu")
          --renderToDisk               render to Destination path (default is render to memory & serve from there)
      -s, --source string              filesystem path to read files relative from
          --stepAnalysis               display memory and timing of different steps of the program
      -t, --theme string               theme to use (located in /themes/THEMENAME/)
          --themesDir string           filesystem path to themes directory
          --uglyURLs                   if true, use /filename.html instead of /filename/
      -w, --watch                      watch filesystem for changes and recreate as needed (default true)
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo - hugo builds your site
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo new theme”

    hugo new theme

    Create a new theme

    Synopsis

    Create a new theme (skeleton) called [name] in the current directory.
    New theme is a skeleton. Please add content to the touched files. Add your
    name to the copyright line in the license and adjust the theme.toml file
    as you see fit.

    hugo new theme [name] [flags]
    

    Options

      -h, --help   help for theme
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -s, --source string    filesystem path to read files relative from
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo new - Create new content for your site
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo new site”

    hugo new site

    Create a new site (skeleton)

    Synopsis

    Create a new site in the provided directory.
    The new site will have the correct structure, but no content or theme yet.
    Use hugo new [contentPath] to create new content.

    hugo new site [path] [flags]
    

    Options

          --force           init inside non-empty directory
      -f, --format string   config & frontmatter format (default "toml")
      -h, --help            help for site
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -s, --source string    filesystem path to read files relative from
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo new - Create new content for your site
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo new”

    hugo new

    Create new content for your site

    Synopsis

    Create a new content file and automatically set the date and title.
    It will guess which kind of file to create based on the path provided.

    You can also specify the kind with -k KIND.

    If archetypes are provided in your theme or site, they will be used.

    hugo new [path] [flags]
    

    Options

          --editor string   edit new content with this editor, if provided
      -h, --help            help for new
      -k, --kind string     content type to create
      -s, --source string   filesystem path to read files relative from
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo list future”

    hugo list future

    List all posts dated in the future

    Synopsis

    List all of the posts in your content directory which will be
    posted in the future.

    hugo list future [flags]
    

    Options

      -h, --help   help for future
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -s, --source string    filesystem path to read files relative from
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo list - Listing out various types of content
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo list expired”

    hugo list expired

    List all posts already expired

    Synopsis

    List all of the posts in your content directory which has already
    expired.

    hugo list expired [flags]
    

    Options

      -h, --help   help for expired
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -s, --source string    filesystem path to read files relative from
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo list - Listing out various types of content
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo list drafts”

    hugo list drafts

    List all drafts

    Synopsis

    List all of the drafts in your content directory.

    hugo list drafts [flags]
    

    Options

      -h, --help   help for drafts
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -s, --source string    filesystem path to read files relative from
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo list - Listing out various types of content
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo list”

    hugo list

    Listing out various types of content

    Synopsis

    Listing out various types of content.

    List requires a subcommand, e.g. hugo list drafts.

    Options

      -h, --help            help for list
      -s, --source string   filesystem path to read files relative from
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo import jekyll”

    hugo import jekyll

    hugo import from Jekyll

    Synopsis

    hugo import from Jekyll.

    Import from Jekyll requires two paths, e.g. hugo import jekyll jekyll_root_path target_path.

    hugo import jekyll [flags]
    

    Options

          --force   allow import into non-empty target directory
      -h, --help    help for jekyll
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo import”

    hugo import

    Import your site from others.

    Synopsis

    Import your site from other web site generators like Jekyll.

    Import requires a subcommand, e.g. hugo import jekyll jekyll_root_path target_path.

    Options

      -h, --help   help for import
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo gen man”

    hugo gen man

    Generate man pages for the Hugo CLI

    Synopsis

    This command automatically generates up-to-date man pages of Hugo’s
    command-line interface. By default, it creates the man page files
    in the “man” directory under the current directory.

    hugo gen man [flags]
    

    Options

          --dir string   the directory to write the man pages. (default "man/")
      -h, --help         help for man
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo gen - A collection of several useful generators.
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo gen doc”

    hugo gen doc

    Generate Markdown documentation for the Hugo CLI.

    Synopsis

    Generate Markdown documentation for the Hugo CLI.

    This command is, mostly, used to create up-to-date documentation
    of Hugo’s command-line interface for http://gohugo.io/.

    It creates one Markdown file per command with front matter suitable
    for rendering in Hugo.

    hugo gen doc [flags]
    

    Options

          --dir string   the directory to write the doc. (default "/tmp/hugodoc/")
      -h, --help         help for doc
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo gen - A collection of several useful generators.
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo gen autocomplete”

    hugo gen autocomplete

    Generate shell autocompletion script for Hugo

    Synopsis

    Generates a shell autocompletion script for Hugo.

    NOTE: The current version supports Bash only.
    This should work for *nix systems with Bash installed.

    By default, the file is written directly to /etc/bash_completion.d
    for convenience, and the command may need superuser rights, e.g.:

    $ sudo hugo gen autocomplete
    

    Add --completionfile=/path/to/file flag to set alternative
    file-path and name.

    Logout and in again to reload the completion scripts,
    or just source them in directly:

    $ . /etc/bash_completion
    
    hugo gen autocomplete [flags]
    

    Options

          --completionfile string   autocompletion file (default "/etc/bash_completion.d/hugo.sh")
      -h, --help                    help for autocomplete
          --type string             autocompletion type (currently only bash supported) (default "bash")
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo gen - A collection of several useful generators.
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo gen”

    hugo gen

    A collection of several useful generators.

    Synopsis

    A collection of several useful generators.

    Options

      -h, --help   help for gen
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo env”

    hugo env

    Print Hugo version and environment info

    Synopsis

    Print Hugo version and environment info. This is useful in Hugo bug reports.

    hugo env [flags]
    

    Options

      -h, --help   help for env
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo - hugo builds your site
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo convert toYAML”

    hugo convert toYAML

    Convert front matter to YAML

    Synopsis

    toYAML converts all front matter in the content directory
    to use YAML for the front matter.

    hugo convert toYAML [flags]
    

    Options

      -h, --help   help for toYAML
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
      -o, --output string    filesystem path to write files to
          --quiet            build in quiet mode
      -s, --source string    filesystem path to read files relative from
          --unsafe           enable less safe operations, please backup first
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo convert toTOML”

    hugo convert toTOML

    Convert front matter to TOML

    Synopsis

    toTOML converts all front matter in the content directory
    to use TOML for the front matter.

    hugo convert toTOML [flags]
    

    Options

      -h, --help   help for toTOML
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
      -o, --output string    filesystem path to write files to
          --quiet            build in quiet mode
      -s, --source string    filesystem path to read files relative from
          --unsafe           enable less safe operations, please backup first
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo convert toJSON”

    hugo convert toJSON

    Convert front matter to JSON

    Synopsis

    toJSON converts all front matter in the content directory
    to use JSON for the front matter.

    hugo convert toJSON [flags]
    

    Options

      -h, --help   help for toJSON
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
      -o, --output string    filesystem path to write files to
          --quiet            build in quiet mode
      -s, --source string    filesystem path to read files relative from
          --unsafe           enable less safe operations, please backup first
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo convert”

    hugo convert

    Convert your content to different formats

    Synopsis

    Convert your content (e.g. front matter) to different formats.

    See convert’s subcommands toJSON, toTOML and toYAML for more information.

    Options

      -h, --help            help for convert
      -o, --output string   filesystem path to write files to
      -s, --source string   filesystem path to read files relative from
          --unsafe          enable less safe operations, please backup first
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo config”

    hugo config

    Print the site configuration

    Synopsis

    Print the site configuration, both default and custom settings.

    hugo config [flags]
    

    Options

      -h, --help   help for config
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo - hugo builds your site
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo check ulimit”

    hugo check ulimit

    Check system ulimit settings

    Synopsis

    Hugo will inspect the current ulimit settings on the system.
    This is primarily to ensure that Hugo can watch enough files on some OSs

    hugo check ulimit [flags]
    

    Options

      -h, --help   help for ulimit
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo check”

    hugo check

    Contains some verification checks

    Synopsis

    Contains some verification checks

    Options

      -h, --help   help for check
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo benchmark”

    hugo benchmark

    Benchmark Hugo by building a site a number of times.

    Synopsis

    Hugo can build a site many times over and analyze the running process
    creating a benchmark.

    hugo benchmark [flags]
    

    Options

      -b, --baseURL string             hostname (and path) to the root, e.g. http://spf13.com/
      -D, --buildDrafts                include content marked as draft
      -E, --buildExpired               include expired content
      -F, --buildFuture                include content with publishdate in the future
          --cacheDir string            filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/
          --canonifyURLs               if true, all relative URLs will be canonicalized using baseURL
          --cleanDestinationDir        remove files from destination not found in static directories
      -c, --contentDir string          filesystem path to content directory
      -n, --count int                  number of times to build the site (default 13)
          --cpuprofile string          path/filename for the CPU profile file
      -d, --destination string         filesystem path to write files to
          --disable404                 do not render 404 page
          --disableKinds stringSlice   disable different kind of pages (home, RSS etc.)
          --disableRSS                 do not build RSS files
          --disableSitemap             do not build Sitemap file
          --enableGitInfo              add Git revision, date and author info to the pages
          --forceSyncStatic            copy all files when static is changed.
      -h, --help                       help for benchmark
          --i18n-warnings              print missing translations
          --ignoreCache                ignores the cache directory
      -l, --layoutDir string           filesystem path to layout directory
          --memprofile string          path/filename for the memory profile file
          --noChmod                    don't sync permission mode of files
          --noTimes                    don't sync modification time of files
          --pluralizeListTitles        pluralize titles in lists using inflect (default true)
          --preserveTaxonomyNames      preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu")
          --renderToMemory             render to memory (only useful for benchmark testing)
      -s, --source string              filesystem path to read files relative from
          --stepAnalysis               display memory and timing of different steps of the program
      -t, --theme string               theme to use (located in /themes/THEMENAME/)
          --themesDir string           filesystem path to themes directory
          --uglyURLs                   if true, use /filename.html instead of /filename/
    

    Options inherited from parent commands

          --config string    config file (default is path/config.yaml|json|toml)
          --log              enable Logging
          --logFile string   log File path (if set, logging enabled automatically)
          --quiet            build in quiet mode
      -v, --verbose          verbose output
          --verboseLog       verbose logging
    

    SEE ALSO

    • hugo - hugo builds your site
    Auto generated by spf13/cobra on 16-Jul-2017

    “hugo”

    hugo

    hugo builds your site

    Synopsis

    hugo is the main command, used to build your Hugo site.

    Hugo is a Fast and Flexible Static Site Generator
    built with love by spf13 and friends in Go.

    Complete documentation is available at http://gohugo.io/.

    hugo [flags]
    

    Options

      -b, --baseURL string             hostname (and path) to the root, e.g. http://spf13.com/
      -D, --buildDrafts                include content marked as draft
      -E, --buildExpired               include expired content
      -F, --buildFuture                include content with publishdate in the future
          --cacheDir string            filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/
          --canonifyURLs               if true, all relative URLs will be canonicalized using baseURL
          --cleanDestinationDir        remove files from destination not found in static directories
          --config string              config file (default is path/config.yaml|json|toml)
      -c, --contentDir string          filesystem path to content directory
      -d, --destination string         filesystem path to write files to
          --disable404                 do not render 404 page
          --disableKinds stringSlice   disable different kind of pages (home, RSS etc.)
          --disableRSS                 do not build RSS files
          --disableSitemap             do not build Sitemap file
          --enableGitInfo              add Git revision, date and author info to the pages
          --forceSyncStatic            copy all files when static is changed.
      -h, --help                       help for hugo
          --i18n-warnings              print missing translations
          --ignoreCache                ignores the cache directory
      -l, --layoutDir string           filesystem path to layout directory
          --log                        enable Logging
          --logFile string             log File path (if set, logging enabled automatically)
          --noChmod                    don't sync permission mode of files
          --noTimes                    don't sync modification time of files
          --pluralizeListTitles        pluralize titles in lists using inflect (default true)
          --preserveTaxonomyNames      preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu")
          --quiet                      build in quiet mode
          --renderToMemory             render to memory (only useful for benchmark testing)
      -s, --source string              filesystem path to read files relative from
          --stepAnalysis               display memory and timing of different steps of the program
      -t, --theme string               theme to use (located in /themes/THEMENAME/)
          --themesDir string           filesystem path to themes directory
          --uglyURLs                   if true, use /filename.html instead of /filename/
      -v, --verbose                    verbose output
          --verboseLog                 verbose logging
      -w, --watch                      watch filesystem for changes and recreate as needed
    

    SEE ALSO

    Auto generated by spf13/cobra on 16-Jul-2017

    Troubleshoot

    The Troubleshooting section includes known issues, recent workarounds, and FAQs pulled from the Hugo Discussion Forum.

    EOF Error

    Trouble: hugo new Aborts with EOF error

    I’m running into an issue where I cannot get archetypes working, when running hugo new showcase/test.md, for example, I see an EOF error thrown by Hugo.

    When I run Hugo with v0.12 via hugo new -v showcase/test.md, I see the following output:

    INFO: 2015/01/04 Using config file: /private/tmp/test/config.toml
    INFO: 2015/01/04 attempting to create  showcase/test.md of showcase
    INFO: 2015/01/04 curpath: /private/tmp/test/archetypes/showcase.md
    ERROR: 2015/01/04 EOF
    

    Is there something that I am blatantly missing?

    Solution: Carriage Returns

    The solution is to add a final newline (i.e., EOL) to the end of your default.md archetype file of your theme. You can do this by adding a carriage return after the closing +++ or --- of your TOML or YAML front matter, respectively.

    {{% note “Final EOL Unnecessary in v0.13+” %}}
    As of v0.13, Hugo’s parser has been enhanced to accommodate archetype files without final EOL thanks to the great work by @tatsushid.
    {{% /note %}}

    Discussion Forum References

    Related Hugo Issues

    Build Performance

    Accented Characters in URLs

    Trouble: Categories with accented characters

    One of my categories is named “Le-carré,” but the link ends up being generated like this:

    categories/le-carr%C3%A9
    

    And not working. Is there an easy fix for this that I’m overlooking?

    Solution

    Are you a macOS user? If so, you are likely a victim of HFS Plus file system’s insistence to store the “é” (U+00E9) character in Normal Form Decomposed (NFD) mode, i.e. as “e” + " ́" (U+0065 U+0301).

    le-carr%C3%A9 is actually correct, %C3%A9 being the UTF-8 version of U+00E9 as expected by the web server. The problem is that OS X turns [U+00E9] into [U+0065 U+0301], and thus le-carr%C3%A9 no longer works. Instead, only le-carre%CC%81 ending with e%CC%81 would match that [U+0065 U+0301] at the end.

    This is unique to OS X. The rest of the world does not do this, and most certainly not your web server which is most likely running Linux. This is not a Hugo-specific problem either. Other people have been bitten by this when they have accented characters in their HTML files.

    Note that this problem is not specific to Latin scripts. Japanese Mac users often run into the same issue; e.g., with decomposing into and &#x3099;. (Read the Japanese Perl users article).

    Rsync 3.x to the rescue! From an answer posted on Server Fault:

    You can use rsync’s --iconv option to convert between UTF-8 NFC & NFD, at least if you’re on a Mac. There is a special utf-8-mac character set that stands for UTF-8 NFD. So to copy files from your Mac to your web server, you’d need to run something like:

    rsync -a --iconv=utf-8-mac,utf-8 localdir/ mywebserver:remotedir/

    This will convert all the local filenames from UTF-8 NFD to UTF-8 NFC on the remote server. The files’ contents won’t be affected. - Server Fault

    Please make sure you have the latest version of rsync 3.x installed. The rsync that ships with OS X is outdated. Even the version that comes packaged with 10.10 (Yosemite) is version 2.6.9 protocol version 29. The --iconv flag is new in rsync 3.x.

    Discussion Forum References

    Developer Tools

    One of Hugo’s greatest strengths is it’s passionate—and always evolving—developer community. With the exception of the highlight shortcode mentioned in Syntax Highlighting, the tools and other projects featured in this section are offerings from both commercial services and open-source projects, many of which are developed by Hugo developers just like you.

    See the popularity of Hugo compared with other static site generators.

    Migrate to Hugo

    This section highlights some projects around Hugo that are independently developed. These tools try to extend the functionality of our static site generator or help you to get started.

    {{% note %}}
    Do you know or maintain a similar project around Hugo? Feel free to open a pull request on GitHub if you think it should be added.
    {{% /note %}}

    Take a look at this list of migration tools if you currently use other logging tools like Jekyll or WordPress but intend to switch to Hugo instead. They’ll take care to export your content into Hugo-friendly formats.

    Jekyll

    Alternatively, you can use the new Jekyll import command.

    • JekyllToHugo - A Small script for converting Jekyll blog posts to a Hugo site.
    • ConvertToHugo - Convert your blog from Jekyll to Hugo.

    Ghost

    • ghostToHugo - Convert Ghost blog posts and export them to Hugo.

    Octopress

    • octohug - Octopress to Hugo migrator.

    DokuWiki

    • dokuwiki-to-hugo - Migrates your dokuwiki source pages from DokuWiki syntax to Hugo Markdown syntax. Includes extra’s like the TODO plugin. Written with extensibility in mind using python 3. Also generates a TOML header for each page. Designed to copypaste the wiki directory into your /content directory.

    WordPress

    • wordpress-to-hugo-exporter - A one-click WordPress plugin that converts all posts, pages, taxonomies, metadata, and settings to Markdown and YAML which can be dropped into Hugo. (Note: If you have trouble using this plugin, you can export your site for Jekyll and use Hugo’s built in Jekyll converter listed above.)

    Tumblr

    • tumblr-importr - An importer that uses the Tumblr API to create a Hugo static site.
    • tumblr2hugomarkdown - Export all your Tumblr content to Hugo Markdown files with preserved original formatting.
    • Tumblr to Hugo - A migration tool that converts each of your Tumblr posts to a content file with a proper title and path. Furthermore, “Tumblr to Hugo” creates a CSV file with the original URL and the new path on Hugo, to help you setup the redirections.

    Drupal

    Joomla

    • hugojoomla - This utility written in Java takes a Joomla database and converts all the content into Markdown files. It changes any URLs that are in Joomla’s internal format and converts them to a suitable form.

    Blogger

    • blogimport - A tool to import from Blogger posts to Hugo.

    Contentful

    Syntax Highlighting

    Hugo can highlight source code in two different ways—either pre-processed server side from your content or to defer the processing to the client side, using a JavaScript library.

    Server-side

    For the pre-processed approach, highlighting is performed by an external Python-based program called Pygments and is triggered via an embedded Hugo shortcode (see example below). If Pygments is absent from the path, it will silently simply pass the content along without highlighting.

    Server-side Advantages

    The advantages of server-side syntax highlighting are that it doesn’t depend on a JavaScript library and, consequently, works very well when read from an RSS feed.

    Pygments

    If you have never worked with Pygments before, here is a brief primer:

    • Install Python from python.org. Version 2.7.x is already sufficient.
    • Run pip install Pygments in order to install Pygments. Once installed, Pygments gives you a command pygmentize. Make sure it sits in your PATH; otherwise, Hugo will not be able to find and use it.

    On Debian and Ubuntu systems, you may also install Pygments by running sudo apt-get install python3-pygments.

    Hugo gives you two options that you can set with the variable pygmentsuseclasses (default false) in your site configuration.

    1. Color codes for highlighting keywords are directly inserted if pygmentsuseclasses = false (default). The color codes depend on your choice of the pygmentsstyle (default = "monokai"). You can explore the different color styles on pygments.org after inserting some example code.
    2. If you choose pygmentsuseclasses = true, Hugo includes class names in your code instead of color codes. For class-names to be meaningful, you need to include a .css file in your website representing your color scheme. You can either generate this .css files according to the description from the Pygments documentation or download the one of the many pre-built color schemes from Pygment’s GitHub css repository.

    Server-side Usage

    Highlighting is carried out via the built-in shortcode highlight. highlight takes exactly one required parameter for the programming language to be highlighted and requires a closing shortcode. Note that highlight is not used for client-side javascript highlighting.

    Example highlight Shortcode Input

    {{< code file=“example-highlight-shortcode-input.md” >}}
    {{</* highlight html */>}}

    {{ .Title }}

    {{ range .Data.Pages }} {{ .Render "summary"}} {{ end }}
    {{}} {{< /code >}}

    Example highlight Shortcode Output

    {{< output file=“example-highlight-shortcode-output.html” >}}
    <section id=“main”>
    <div>
    <h1 id=“title”>{{ .Title }}</h1>
    {{ range .Data.Pages }}
    {{ .Render “summary”}}
    {{ end }}
    </div>
    </section>
    {{< /output >}}

    Options

    Options for controlling highlighting can be added in the second argument as a quoted, comma-separated key-value list. The example below will syntax highlight in go with inline line numbers and line numbers 2 and 3 highlighted.

    {{</* highlight go "linenos=inline,hl_lines=2 3" */>}}
    var a string
    var b string
    var c string
    var d string
    {{</* / highlight */>}}
    

    The highlight shortcode includes the following supported keywords:

    • style
    • encoding
    • noclasses
    • hl_lines
    • linenos

    Note that style and noclasses will override the similar setting in the global config.

    The keywords in the highlight shortcode mirror those of Pygments from the command line. See the Pygments documentation for more information.

    Code Fences

    It is also possible to add syntax highlighting with GitHub flavored code fences. To enable this, set the PygmentsCodeFences to true in Hugo’s configuration file;

    {{ .Title }}

    {{ range .Data.Pages }} {{ .Render "summary"}} {{ end }}
    ``` ```

    {{% note “Disclaimers on Pygments” %}}

    • Pygments is relatively slow and causes a performance hit when building your site, but Hugo has been designed to cache the results to disk.
    • The caching can be turned off by setting the --ignoreCache flag to true.
    • The languages available for highlighting depend on your Pygments installation.
      {{% /note %}}

    Client-side

    Alternatively, code highlighting can be applied to your code blocks in client-side JavaScript.

    Client-side syntax highlighting is very simple to add. You’ll need to pick
    a library and a corresponding theme. Some popular libraries are:

    Client-side Advantages

    The advantages of client-side syntax highlighting are that it doesn’t cost anything when building your site, and some of the highlighting scripts available cover more languages than Pygments does.

    Highlight.js Example

    This example uses the popular Highlight.js library, hosted by [Yandex], a popular Russian search engine.

    In your ./layouts/partials/ (or ./layouts/chrome/) folder, depending on your specific theme, there will be a snippet that will be included in every generated HTML page, such as header.html or header.includes.html. Simply add the css and js to initialize Highlight.js:

    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/styles/default.min.css">
    <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/highlight.min.js"></script>
    <script>hljs.initHighlightingOnLoad();</script>
    

    Prism example

    Prism is another popular highlighter library and is used on some major sites.
    The download section of the prism.js website is simple to use and affords you a high degree of customization to pick only the languages you’ll be using on your site.

    Similar to Highlight.js, you simply load prism.css in your <head> via whatever Hugo partial template is creating that part of your pages:

    ...
    <link href="/css/prism.css" rel="stylesheet" />
    ...
    

    Add prism.js near the bottom of your <body> tag in whatever Hugo partial template is appropriate for your site or theme.

    ...
    <script src="/js/prism.js"></script>
    </body>
    

    In this example, the local paths indicate that your downloaded copy of these files are being added to the site, typically under ./static/css/ and ./static/js/, respectively.

    Client-side Usage

    To use client-side highlighting, most of these javascript libraries expect your code to be wrapped in semantically correct <code> elements with language-specific class attributes. For example, a code block for HTML would have class="language-html".

    The client-side highlighting script therefore looks for programming language classes according to this convention: language-go, language-html, language-css, language-bash, etc. If you look at the page’s source, you might see something like the following:

    <pre>
      <code class="language-css">
      body {
        font-family: "Noto Sans", sans-serif;
      }
      </code>
    </pre>
    

    If you are using markdown, your content pages needs to use the following syntax, with the name of the language to be highlighted entered directly after the first “fence.” A fenced code block can be noted by opening and closing triple tilde ~ or triple back ticks `:

    {{< nohighlight >}}

    body {
      font-family: "Noto Sans", sans-serif;
    }
    

    {{< /nohighlight >}}

    Here is the same example but with triple back ticks to denote the fenced code block:

    {{< nohighlight >}}

    body {
      font-family: "Noto Sans", sans-serif;
    }
    

    {{< /nohighlight >}}

    Passing the above examples through the highlighter script would yield the following markup:

    {{< nohighlight >}}
    <pre><code class=“language-css hljs”>;<span class=“hljs-selector-tag”>body</span> {
    <span class=“hljs-attribute”>font-family</span>: &ltspan class=“hljs-string”>“Noto Sans”</span>, sans-serif;
    }
    {{< /nohighlight >}}

    In the case of the coding color scheme used by the Hugo docs, the resulting output would then look like the following to the website’s end users:

    body {
      font-family: "Noto Sans", sans-serif;
    }
    

    Please see individual libraries’ documentation for how to implement each of the JavaScript-based libraries.

    [Yandex]: http://yandex.ru/

    Starter Kits

    Know of a Hugo-related starter kit that isn’t mentioned here? Please add it to the list.

    {{% note “Starter Kits are Not Maintained by the Hugo Team”%}}
    The following starter kits are developed by active members of the Hugo community. If you find yourself having issues with any of the projects, it’s best to file an issue directly with the project’s maintainer(s).
    {{% /note %}}

    • [Victor Hugo][]. Victor Hugo is a Hugo boilerplate for creating truly epic websites using Gulp + Webpack as an asset pipeline. Victor Hugo uses post-css and Babel for CSS and JavaScript, respectively, and is actively maintained.
    • GOHUGO AMP. GoHugo AMP is a starter theme that aims to make it easy to adopt Google’s AMP Project. The starter kit comes with 40+ shortcodes and partials plus automatic structured data. The project also includes a separate site with extensive documentation.
    • Blaupause. Blaupause is a developer-friendly Hugo starter kit based on Gulp tasks. It comes ES6-ready with several helpers for SVG and fonts and basic structure for HTML, SCSS, and JavaScript.
    • hugulp. hugulp is a tool to optimize the assets of a Hugo website. The main idea is to recreate the famous Ruby on Rails Asset Pipeline, which minifies, concatenates and fingerprints the assets used in your website.

    [Victor Hugo]: https://github.com/netlify/victor-hugo

    Frontend Interfaces with Hugo

    • enwrite. Enwrite enables evernote-powered, statically generated blogs and websites. Now posting to your blog or updating your website is as easy as writing a new note in Evernote!
    • caddy-hugo. caddy-hugo is an add-on for Caddy that delivers a good UI to edit the content of your Hugo website.
    • Lipi. Lipi is a native GUI frontend written in Java to manage your Hugo websites.

    Commercial Services

    • Appernetic.io is a Hugo Static Site Generator as a Service that is easy to use for non-technical users.
      • Features: inline PageDown editor, visual tree view, image upload and digital asset management with Cloudinary, site preview, continuous integration with GitHub, atomic deploy and hosting, Git and Hugo integration, autosave, custom domain, project syncing, theme cloning and management. Developers have complete control over the source code and can manage it with GitHub’s deceptively simple workflow.
    • DATOCMS DatoCMS is a fully customizable administrative area for your static websites. Use your favorite website generator, let your clients publish new content independently, and the host the site anywhere you like.
    • Forestry.io. Forestry is a simple CMS for Jekyll and Hugo websites with support for GitHub, GitLab, and Bitbucket. Every time an update is made via the CMS, Forestry will commit changes back to your repo and will compile/deploy your website to S3, GitHub Pages, FTP, etc.
    • Netlify.com. Netlify builds, deploys, and hosts your static website or app (Hugo, Jekyll, etc). Netlify offers a drag-and-drop interface and automatic deployments from GitHub or Bitbucket.
      • Features: global CDN, atomic deploys, ultra-fast DNS, instant cache invalidation, high availability, automated hosting, Git integration, form submission hooks, authentication providers, and custom domains. Developers have complete control over the source code and can manage it with GitHub or Bitbucket’s deceptively simple workflow.

    Editor Plug-ins for Hugo

    The Hugo community uses a wide range of preferred tools and has developed plug-ins for some of the most popular text editors to help automate parts of your workflow.

    Sublime Text

    • Hugofy. Hugofy is a plugin for Sublime Text 3 to make life easier to use Hugo static site generator.

    Visual Studio Code

    • Hugofy. Hugofy is a plugin for Visual Studio Code to “make life easier” when developing with Hugo. The source code can be found here.

    Emacs

    • hugo.el. Some helper functions for creating a Website with Hugo. Note that Hugo also supports Org-mode.

    Vim

    • Vim Hugo Helper. A small Vim plugin to help me with writing posts with Hugo.

    Atom

    • Hugofy. A Hugo Static Website Generator package for Atom.
    • language-hugo. Adds syntax highlighting to Hugo files.

    formats: /content-management/formats/

    Search for your Hugo Website

    A static website with a dynamic search function? Yes. As alternatives to embeddable scripts from Google or other search engines, you can provide your visitors a custom search by indexing your content files directly.

    • Hugoidx is an experimental application to create a search index. It’s built on top of Bleve.
    • GitHub Gist for Hugo Workflow. This gist contains a simple workflow to create a search index for your static website. It uses a simple Grunt script to index all your content files and lunr.js to serve the search results.
    • hugo-lunr. A simple way to add site search to your static Hugo site using lunr.js. Hugo-lunr will create an index file of any html and markdown documents in your Hugo project.

    Commercial Search Services

    • Algolia’s Search API makes it easy to deliver a great search experience in your apps and websites. Algolia Search provides hosted full-text, numerical, faceted, and geolocalized search.

    Other Hugo Community Projects

    And for all the other small things around Hugo:

    Hosting & Deployment

    Because Hugo renders static websites, you can host your new Hugo website virtually anywhere. The following represent only a few of the more popular hosting and automated deployment solutions used by the Hugo community.

    Host on Netlify

    Netlify provides continuous deployment services, global CDN, ultra-fast DNS, atomic deploys, instant cache invalidation, one-click SSL, a browser-based interface, a CLI, and many other features for managing your Hugo website.

    Assumptions

    • You have an account with GitHub, GitLab, or Bitbucket.
    • You have completed the Quick Start or have Hugo website you are ready to deploy and share with the world.
    • You do not already have a Netlify account.

    Create a Netlify account

    Go to app.netlify.com and select your preferred signup method. This will likely be a hosted Git provider, although you also have the option to sign up with an email address.

    The following examples use GitHub, but other git providers will follow a similar process.

    Screenshot of the homepage for app.netlify.com, containing links to the most popular hosted git solutions.

    Selecting GitHub will bring up a typical modal you’ve seen through other application that use GitHub for authentication. Select “Authorize application.”

    Screenshot of the authorization popup for Netlify and GitHub.

    Create a New Site with Continuous Deployment

    You’re now already a Netlify member and should be brought to your new dashboard. Select “New site from git.”

    Screenshot of the blank Netlify admin panel with no sites and highlighted 'add new site' button'

    Netlify will then start walking you through the steps necessary for continuous deployment. First, you’ll need to select your git provider again, but this time you are giving Netlify added permissions to your repositories.

    Screenshot of step 1 of create a new site for Netlify: selecting the git provider

    And then again with the GitHub authorization modal:

    Screenshot of step 1 of create a new site for Netlify: selecting the git provider

    Select the repo you want to use for continuous deployment. If you have a large number of repositories, you can filter through them in real time using repo search:

    Screenshot of step 1 of create a new site for Netlify: selecting the git provider

    Once selected, you’ll be brought to a screen for basic setup. Here you can select the branch you wanted published, your build command, and your publish (i.e. deploy) directory. The publish directory should mirror that of what you’ve set in your site configuration, the default of which is public. The following steps assume you are publishing from the master branch.

    Build with a Specific Hugo Version

    Setting the build command to hugo will build your site according to the current default Hugo version used by Netlify. You can see the full list of available Hugo versions in Netlify’s Docker file.

    If you want to tell Netlify to build with a specific version, you can append an underscore followed by the version number to the build command:

    hugo_0.19
    

    Your simple configuration should now look similar to the following:

    Screenshot of 3-step, basic continuous deployment setup with a new Hugo site on Netlify

    Selecting “Deploy site” will immediately take you to a terminal for your build:.

    Animated gif of deploying a site to Netlify, including the terminal read out for the build.

    Once the build is finished—this should only take a few seconds–you should now see a “Hero Card” at the top of your screen letting you know the deployment is successful. The Hero Card is the first element that you see in most pages. It allows you to see a quick summary of the page and gives access to the most common/pertinent actions and information. You’ll see that the URL is automatically generated by Netlify. You can update the URL in “Settings.”

    Screenshot of successful deploy badge at the top of a deployments screen from within the Netlify admin.

    Screenshot of homepage to https://hugo-netlify-example.netlify.com, which is mostly dummy text

    Visit the live site.

    Now every time you push changes to your hosted git repository, Netlify will rebuild and redeploy your site.

    Use Hugo Themes with Netlify

    The git clone method for installing themes is not supported by Netlify. If you were to use git clone, it would require you to recursively remove the .git subdirectory from the theme folder and would therefore prevent compatibility with future versions of the theme.

    A better approach is to install a theme as a proper git submodule. You can read the GitHub documentation for submodules or those found on Git’s website for more information, but the command is similar to that of git clone:

    cd themes
    git submodule add https://github.com/<THEMECREATOR>/<THEMENAME>
    

    Next Steps

    You now have a live website served over https, distributed through CDN, and configured for continuous deployment. Dig deeper into the Netlify documentation:

    1. Using a Custom Domain
    2. Setting up HTTPS on Custom Domains
    3. Redirects and Rewrite Rules

    Host on Firebase

    Assumptions

    1. You have an account with Firebase. (If you don’t, you can sign up for free using your Google account.)
    2. You have completed the Quick Start or have a completed Hugo website ready for deployment.

    Initial setup

    Go to the Firebase console and create a new project (unless you already have a project). You will need to globally install firebase-tools (node.js):

    npm install -g firebase-tools
    

    Log in to Firebase (setup on your local machine) using firebase login, which opens a browser where you can select your account. Use firebase logout in case you are already logged in but to the wrong account.

    firebase login
    

    In the root of your Hugo project, initialize the Firebase project with the firebase init command:

    firebase init
    

    From here:

    1. Choose Hosting in the feature question
    2. Choose the project you just set up
    3. Accept the default for your database rules file
    4. Accept the default for the publish directory, which is public
    5. Choose “No” in the question if you are deploying a single-page app

    Deploy

    To deploy your Hugo site, execute the firebase deploy command, and your site will be up in no time:

    hugo && firebase deploy
    

    CI Setup

    You can generate a deploy token using

    firebase login:ci
    

    You can also set up your CI (e.g., with Wercker) and add the token to a private variable like $FIREBASE_DEPLOY_TOKEN.

    {{% note %}}
    This is a private secret and it should not appear in a public repository. Make sure you understand your chosen CI and that it’s not visible to others.
    {{% /note %}}

    You can then add a step in your build to do the deployment using the token:

    firebase deploy --token $FIREBASE_DEPLOY_TOKEN
    

    Reference links

    Host on GitHub

    GitHub provides free and fast static hosting over SSL for personal, organization, or project pages directly from a GitHub repository via its GitHub Pages service.

    Assumptions

    1. You have Git 2.5 or greater installed on your machine.
    2. You have a GitHub account. Signing up for GitHub is free.
    3. You have a ready-to-publish Hugo website or have at least completed the Quick Start.

    If you are working within an Organization account or want to set up a User website on GitHub and would like more information, refer to the GitHub Pages documentation.

    {{% note %}}
    Make sure your baseURL key-value in your site configuration reflects the full URL of your GitHub pages repository if you’re using the default GH Pages URL (e.g., username.github.io/myprojectname/) and not a custom domain.
    {{% /note %}}

    Deployment via /docs Folder on Master Branch

    As described in the GitHub Pages documentation, you can deploy from a folder called docs/ on your master branch. To effectively use this feature with Hugo, you need to change the Hugo publish directory in your site’s config.toml and config.yaml, respectively:

    publishDir: docs
    
    publishDir = "docs"
    

    After running hugo, push your master branch to the remote repository and choose the docs/ folder as the website source of your repo. Do the following from within your GitHub project:

    1. Go to SettingsGitHub Pages
    2. From Source, select “master branch /docs folder”. If the option isn’t enabled, you likely do not have a docs/ folder in the root of your project.

    {{% note %}}
    The docs/ option is the simplest approach but requires you set a publish directory in your site configuration. You cannot currently configure GitHub pages to publish from another directory on master, and not everyone prefers the output site live concomitantly with source files in version control.
    {{% /note %}}

    Deployment From Your gh-pages Branch

    You can also tell GitHub pages to treat your master branch as the published site or point to a separate gh-pages branch. The latter approach is a bit more complex but has some advantages:

    • It keeps your source and generated website in different branches and therefore maintains version control history for both.
    • Unlike the preceding docs/ option, it uses the default public folder.

    Preparations for gh-pages Branch

    These steps only need to be done once. Replace upstream with the name of your remote; e.g., origin:

    Add the Public Folder

    First, add the public folder to your .gitignore file at the project root so that the directory is ignored on the master branch:

    echo "public" >> .gitignore
    

    Initialize Your gh-pages Branch

    You can now initialize your gh-pages branch as an empty orphan branch:

    git checkout --orphan gh-pages
    git reset --hard
    git commit --allow-empty -m "Initializing gh-pages branch"
    git push upstream gh-pages
    git checkout master
    

    Build and Deployment

    Now check out the gh-pages branch into your public folder using git’s worktree feature. Essentially, the worktree allows you to have multiple branches of the same local repository to be checked out in different directories:

    rm -rf public
    git worktree add -B gh-pages public upstream/gh-pages
    

    Regenerate the site using the hugo command and commit the generated files on the gh-pages branch:

    {{< code file=“commit-gh-pages-files.sh”>}}
    hugo
    cd public && git add --all && git commit -m “Publishing to gh-pages” && cd …
    {{< /code >}}

    If the changes in your local gh-pages branch look alright, push them to the remote repo:

    git push upstream gh-pages
    

    Set gh-pages as Your Publish Branch

    In order to use your gh-pages branch as your publishing branch, you’ll need to configure the repository within the GitHub UI. This will likely happen automatically once GitHub realizes you’ve created this branch. You can also set the branch manually from within your GitHub project:

    1. Go to SettingsGitHub Pages
    2. From Source, select “gh-pages branch” and then Save. If the option isn’t enabled, you likely have not created the branch yet OR you have not pushed the branch from your local machine to the hosted repository on GitHub.

    After a short while, you’ll see the updated contents on your GitHub Pages site.

    Put it Into a Script

    To automate these steps, you can create a script with the following contents:

    {{< code file=“publish_to_ghpages.sh” >}}
    #!/bin/sh

    DIR=$(dirname “$0”)

    cd $DIR/…

    if [[ $(git status -s) ]]
    then
    echo “The working directory is dirty. Please commit any pending changes.”
    exit 1;
    fi

    echo “Deleting old publication”
    rm -rf public
    mkdir public
    git worktree prune
    rm -rf .git/worktrees/public/

    echo “Checking out gh-pages branch into public”
    git worktree add -B gh-pages public upstream/gh-pages

    echo “Removing existing files”
    rm -rf public/*

    echo “Generating site”
    hugo

    echo “Updating gh-pages branch”
    cd public && git add --all && git commit -m “Publishing to gh-pages (publish.sh)”
    {{< /code >}}

    This will abort if there are pending changes in the working directory and also makes sure that all previously existing output files are removed. Adjust the script to taste, e.g. to include the final push to the remote repository if you don’t need to take a look at the gh-pages branch before pushing. Or adding echo yourdomainname.com >> CNAME if you set up for your gh-pages to use customize domain.

    Deployment From Your master Branch

    To use master as your publishing branch, you’ll need your rendered website to live at the root of the GitHub repository. Steps should be similar to that of the gh-pages branch, with the exception that you will create your GitHub repository with the public directory as the root. Note that this does not provide the same benefits of the gh-pages branch in keeping your source and output in separate, but version controlled, branches within the same repo.

    You will also need to set master as your publishable branch from within the GitHub UI:

    1. Go to SettingsGitHub Pages
    2. From Source, select “master branch” and then Save.

    Host GitHub User or Organization Pages

    As mentioned in this GitHub Help article, you can host a user/organization page in addition to project pages. Here are the key differences in GitHub Pages websites for Users and Organizations:

    1. You must use the <USERNAME>.github.io naming scheme for your GitHub repo.
    2. Content from the master branch will be used to publish your GitHub Pages site.

    It becomes much simpler in this case: we’ll create two separate repos, one for Hugo’s content, and a git submodule with the public folder’s content in it.

    Step-by-step Instructions

    1. Create a <YOUR-PROJECT> git repository on GitHub. This repository will contain Hugo’s content and other source files.
    2. Create a <USERNAME>.github.io GitHub repository. This is the repository that will contain the fully rendered version of your Hugo website.
    3. git clone <YOUR-PROJECT-URL> && cd <YOUR-PROJECT>
    4. Make your website work locally (hugo server or hugo server -t <YOURTHEME>) and open your browser to http://localhost:1313.
    5. Once you are happy with the results:
      • Press Ctrl+C to kill the server
      • rm -rf public to completely remove the public directory if there
    6. git submodule add -b master [email protected]:<USERNAME>/<USERNAME>.github.io.git public. This creates a git submodule. Now when you run the hugo command to build your site to public, the created public directory will have a different remote origin (i.e. hosted GitHub repository). You can automate some of these steps with the following script.

    Put it Into a Script

    You’re almost done. You can also add a deploy.sh script to automate the preceding steps for you. You can also make it executable with chmod +x deploy.sh.

    The following are the contents of the deploy.sh script:

    #!/bin/bash
    
    echo -e "\033[0;32mDeploying updates to GitHub...\033[0m"
    
    # Build the project.
    hugo # if using a theme, replace with `hugo -t <YOURTHEME>`
    
    # Go To Public folder
    cd public
    # Add changes to git.
    git add .
    
    # Commit changes.
    msg="rebuilding site `date`"
    if [ $# -eq 1 ]
      then msg="$1"
    fi
    git commit -m "$msg"
    
    # Push source and build repos.
    git push origin master
    
    # Come Back up to the Project Root
    cd ..
    

    You can then run ./deploy.sh "Your optional commit message" to send changes to <USERNAME>.github.io. Note that you likely will want to commit changes to your <YOUR-PROJECDT> repository as well.

    That’s it! Your personal page should be up and running at https://yourusername.github.io within a couple minutes.

    Use a Custom Domain

    If you’d like to use a custom domain for your GitHub Pages site, create a file static/CNAME. Your custom domain name should be the only contents inside CNAME. Since it’s inside static, the published site will contain the CNAME file at the root of the published site, which is a requirements of GitHub Pages.

    Refer to the official documentation for custom domains for further information.

    Host on GitLab

    GitLab makes it incredibly easy to build, deploy, and host your Hugo website via their free GitLab Pages service, which provides native support for Hugo, as well as numerous other static site generators.

    Assumptions

    • Working familiarity with Git for version control
    • Completion of the Hugo Quick Start
    • A GitLab account
    • A Hugo website on your local machine that you are ready to publish

    Create .gitlab-ci.yml

    cd your-hugo-site
    

    In the root directory of your Hugo site, create a .gitlab-ci.yml file. The .gitlab-ci.yml configures the GitLab CI on how to build your page. Simply add the content below.

    {{< code file=“gitlab-ci.yml” >}}
    image: publysher/hugo

    pages:
    script:

    • hugo
      artifacts:
      paths:
      • public
        only:
    • master
      {{< /code >}}

    Push Your Hugo Website to GitLab

    Next, create a new repository on GitLab. It is not necessary to make the repository public. In addition, you might want to add /public to your .gitignore file, as there is no need to push compiled assets to GitLab or keep your output website in version control.

    # initialize new git repository
    git init
    
    # add /public directory to our .gitignore file
    echo "/public" >> .gitignore
    
    # commit and push code to master branch
    git add .
    git commit -m "Initial commit"
    git remote add origin https://gitlab.com/YourUsername/your-hugo-site.git
    git push -u origin master
    

    Wait for Your Page to Build

    That’s it! You can now follow the CI agent building your page at https://gitlab.com///pipelines.

    After the build has passed, your new website is available at https://<YourUsername>.gitlab.io/<your-hugo-site>/.

    Next Steps

    GitLab supports using custom CNAME’s and TLS certificates. For more details on GitLab Pages, see the GitLab Pages setup documentation.

    Host on Bitbucket

    You can use Bitbucket and Aerobatic to build, deploy, and host a Hugo website. Aerobatic is a static hosting service that integrates with Bitbucket and provides a free hosting tier.

    Assumptions

    Install Aerobatic CLI

    If you haven’t previously used Aerobatic, you’ll first need to install the Command Line Interface (CLI) and create an account. For a list of all commands available, see the Aerobatic CLI docs.

    npm install aerobatic-cli -g
    aero register
    

    Create and Deploy Site

    hugo new site my-new-hugo-site
    cd my-new-hugo-site
    cd themes; git clone https://github.com/eliasson/liquorice
    hugo -t liquorice
    aero create                                           # create the Aerobatic site
    hugo --baseURL https://my-new-hugo-site.aerobatic.io  # build the site overriding baseURL
    aero deploy -d public                                 # deploy output to Aerobatic
    
    Version v1 deployment complete.
    View now at https://hugo-docs-test.aerobatic.io
    

    In the rendered page response, the https://__baseurl__ will be replaced with your actual site url (in this example, https://my-new-hugo-site.aerobatic.io). You can always rename your Aerobatic website with the aero rename command.

    Push Hugo site to Bitbucket

    We will now create a git repository and then push our code to Bitbucket. In Bitbucket, create a repository.

    # initialize new git repository
    git init
    
    # set up our .gitignore file
    echo -e "/public \n/themes \naero-deploy.tar.gz" >> .gitignore
    
    # commit and push code to master branch
    git add --all
    git commit -m "Initial commit"
    git remote add origin [email protected]:YourUsername/my-new-hugo-site.git
    git push -u origin master
    

    Continuous Deployment With Bitbucket Pipelines

    In the example above, we pushed the compiled assets in the /public folder to Aerobatic. In the following example, we use Bitbucket Pipelines to continuously create and deploy the compiled assets to Aerobatic.

    Step 1: Configure Bitbucket Pipelines

    In your Hugo website’s Bitbucket repo;

    1. Click the Pipelines link in the left nav menu of your Bitbucket repository.
    2. Click the Enable Pipelines button.
    3. On the next screen, leave the default template and click Next.
    4. In the editor, paste in the yaml contents below and click Commit.
    image: beevelop/nodejs-python
    pipelines:
      branches:
        master:
          - step:
              script:
                - apt-get update -y && apt-get install wget
                - apt-get -y install git
                - wget https://github.com/gohugoio/hugo/releases/download/v0.18/hugo_0.18-64bit.deb
                - dpkg -i hugo*.deb
                - git clone https://github.com/eliasson/liquorice themes/liquorice
                - hugo --theme=liquorice --baseURL https://__baseurl__ --buildDrafts
                - npm install -g aerobatic-cli
                - aero deploy
    

    Step 2: Create AEROBATIC_API_KEY environment variable.

    This step only needs to be done once per account. From the command line;

    aero apikey
    
    1. Navigate to the Bitbucket account settings for the account that the website repo belongs to.
    2. Scroll down to the bottom of the left nav and click the Environment variables link in the PIPELINES section.
    3. Create a new environment variable called AEROBATIC_API_KEY with the value you got by running the aero apikey command. Be sure to click the Secured checkbox.

    Step 3: Edit and Commit Code

    hugo new post/good-to-great.md
    hugo server --buildDrafts -t liquorice #Check that all looks good
    
    # commit and push code to master branch
    git add --all
    git commit -m "New blog post"
    git push -u origin master
    

    Your code will be committed to Bitbucket, Bitbucket Pipelines will run your build, and a new version of your site will be deployed to Aerobatic.

    At this point, you can now create and edit blog posts directly in the Bitbucket UI.

    Suggested next steps

    The code for this example can be found in this Bitbucket repository. Aerobatic also provides a number of additional plugins such as auth and redirects that you can use for your Hugo site.

    Deployment with Wercker

    Goals

    By the end of this guide, you will have completed the following:

    • Creating a basic Hugo project and website
    • Version controlling your project with Git
    • Adding your project to GitHub
    • Automating site deployments with a free tool called Wercker
    • Deploying your website to GitHub Pages for free hosting

    Assumptions

    1. You have a working familiarity with using Git for version control
    2. You have a GitHub account
    3. You have already created a basic Hugo project

    If you do not meet these assumptions, the GitHub help section has an explanation of how to install and use git. Signing up for a GitHub account is free as well. If you are completely unfamiliar with creating a new Hugo website, visit the Hugo Quick Start.

    Create a Basic Hugo Site

    {{% note “This Guide Uses the Hugo CLI” %}}
    All the work for setting up a Hugo project and using this guide is done via the Hugo CLI’s most basic commands. See the command line reference page for a more exhaustive account of the CLI’s features.
    {{% /note %}}

    First, create your new Hugo website using the hugo new site command and change into the newly created directory for the project. In this guide, we are calling our new project hugo-wercker-example:

    {{< code file=“hugo-new-site.sh” >}}
    hugo new site hugo-wercker-example
    cd hugo-wercker-example
    {{< /code >}}

    We will use the Herring Cove theme by first cloning the theme into the themes directory.

    {{< code file=“clone-herring-cove-theme.sh” >}}
    cd themes
    git clone https://github.com/spf13/herring-cove.git
    {{< /code >}}

    Cloning the project from the command line will conflict with our own version control. So, we need to remove the external git configuration that came with the clone of Herring Cove:

    {{< code file=“remove-herring-cove-git.sh” >}}
    rm -rf herring-cove/.git
    {{< /code >}}

    We need content for Hugo to build. Let’s add a quick /about page:

    hugo new about.md
    

    {{% note %}}
    The preceding example for the about page leverages archetypes to scaffold a new content file with preconfigured front matter. Find out more about Hugo’s archetypes.
    {{% /note %}}

    Now you can edit contents/about.md in your text editor of choice, but this is not necessary for the purposes of this guide. Running the following command will build your Hugo site into the public directory. We have added undraft to ensure that the example page is no longer in draft mode:

    {{< code file=“hugo-build-undraft.sh” >}}
    hugo undraft content/about.md
    {{< /code >}}

    Once the website is build, t’s a good idea to run the following command to start a local server and ensure you’re changes have been implemented:

    hugo server --theme=herring-cove
    

    If everything is fine, you should see something similar to the image below when you go to http://localhost:1313 in your browser.

    Set up Version Control in Git

    Adding Git to your project is done by running the git init command from the root directory of your project.

    git init
    

    Running git status at this point will show you the following entries: the config.toml file, the themes directory, the contents directory, and the public directory. However, we don’t want the public directory version controlled because Wercker is responsible for generating the finished website later on. Therefore, we’ll add a .gitignore file to our project that will exclude the /public directory from being tracked by Git:

    {{< code file=“gitignore.sh” >}}
    echo “/public” >> .gitignore
    {{< /code >}}

    Wercker might complain when we try to build the site later on because we currently do not have any static files outside of the themes directory. We simply have to add any file to the static folder to prevent Wercker from complaining. To keep this guide simple, let’s add a robots.txt. The following command creates the file in /static. The contents of the robots.txt lets search engines know they have full access to crawl the published website:

    {{< code file=“addrobotstxt.sh” >}}
    echo “User-agent: *\nDisallow:” > static/robots.txt
    {{< /code >}}

    Now we need to add (i.e., stage [see Git documentation]) and commit all of our changes in the repository into Git:

    git commit -a -m "Initial commit"
    

    Add the Project to GitHub

    Now we need to create a new repository on GitHub. Once you are signed in to GitHub, you can add a new repository by clicking on the +▼ dropdown at the top right or by going to https://github.com/new

    We then choose a name for the project (hugo-wercker-example). When clicking on create repository GitHub displays the commands for adding an existing project to the site. The commands shown below are the ones used for this site, if you’re following along you will need to use the ones shown by GitHub. Once we’ve run those commands the project is in GitHub and we can move on to setting up the Wercker configuration. Be sure to replace YourUserName with your GitHub account/username:

    {{< code file=“setup-gh-repo.sh” >}}
    git remote add origin [email protected]:YourUsername/hugo-wercker-example.git
    git push -u origin master
    {{< /code >}}

    Set Up Wercker

    To sign up for a free Wercker account, go to https://wercker.com and click the the Sign Up button on the top right of the home screen.

    Registe for Wercker with Your GitHub Account

    Sign up for Wercker using your GitHub credentials. If you don’t have a GitHub account, or don’t want to use it for your account, you have the option to register with a username and password as well. However, the second half of this guide—devoted to hosting your website on GitHub pages—will no longer be of interest to you.

    Connecte GitHub or Bitbucket

    After you are registered, you will need to link your GitHub or Bitbucket account to Wercker. You can link your account by navigating to your profile settings and then selecting “Git connections.”

    If you registered for Wercker using GitHub, it will most likely look like the following image. To connect a missing service, click the Connect button, which may send you to either GitHub or Bitbucket to sign into your respective account.

    Add Your Project

    Now that we’ve got all the preliminaries out of the way, it’s time to set up our application. For this we click on the + Create button next to Applications and choose GitHub as our provider.

    Select a Repository

    When selecting GitHub, Wercker will show all your GitHub repositories. You have the option to filter repositories using the search input at the top of the repositories list. Once you have your repository selected, click the Use selected repo button.

    Select the Repository Owner

    In the next step, Wercker asks you to select the repository owner. Select your GitHub account and continue.

    Configure Access

    {{% note %}}
    This guide assumes you are using a public GitHub repository and understand that the published GitHub Pages website will be available to everyone.
    {{%/note %}}

    This step can be slightly tricky. Wercker does not have privileges to check out your private projects by default and therefore needs your permission to add a deploy key to your repository. By selecting the first option, you’re simply allowing Wercker to check out the code via the same methods available to anyone visiting the project on GitHub.

    Wercker.yml

    Wercker will now attempt to create an initial wercker.yml file for you. More specifically, it will create a code block within the Wercker interface that you can copy to your finished file. Wercker gives us a debian box because our project does not have any special requirements.

    Now we need to create a wercker.yml file in the root of our project. This file will contain our Wercker app’s configuration. After we finish setting up our app, we will expand the contents of this file to build and deploy our website.

    Public or Private

    This is a personal choice. You can make an app public so that everyone can see more details about it. Keeping it private or public does not provide any overt benefits for you as the creator of the app. That said, the app we are currently creating has been made public to facilitate easier usage of this hosting and deployment guide.

    App Successfully Created

    The application is now added and Wercker will offer you the chance to trigger a build. However, we will decline the offer because we haven’t yet pushed our wercker.yml file to our GitHub repository.

    Add the Hugo-build Step

    Now we need to add the Wercker steps to our build process. First, we go to the “Registry” action in the top menu. When in the registry, we can search for “hugo build”. Select the “Hugo-Build by arjen” step.

    Use the Hugo-build Step

    A summary of very basic usage is available at the top of the details for the Hugo-Build step. Below the basic usage is the contents of the README.md file associated with the step’s repository. README.md’s on Wercker usually contain more details about the advanced options and examples of usage.

    We’re not going to use any of the advanced features of Hugo-Build in this guide. Let’s return to our project and add the first section of details we need to our wercker.yml.

    {{% warning “Hugo Version in wercker.yml” %}}
    The docs are a work in progress. As such, the version represented in this guide may not represent the version you’ve been using for local development. Be sure to use the appropriate Hugo version for your build step.
    {{% /warning %}}

    {{< code file=“wercker-build-step.yml” >}}
    box: debian
    build:
    steps:
    - arjen/hugo-build:
    version: “0.17”
    theme: herring-cove
    flags: --buildDrafts=true
    {{< /code >}}

    We can conclude this first step by pushing our wercker.yml to our GitHub repository and then seeing the magic at work within Wercker’s interface.

    {{< code file=“push-wecker-to-gh.sh” >}}
    git commit -a -m “Add wercker.yml”
    git push origin master
    {{< /code >}}

    If completed and successful, a green check mark should appear in the commit column of your first build. However, this is only the build step. We still need to deploy the website to our free hosting on GitHub Pages. If you would like more details about the build, you can click the commit hash.

    Add a GitHub Pages Deploy Step to wercker.yml

    In order to deploy to GitHub Pages, we need to add a deploy step to our wercker.yml. We are going to add lukevevier/gh-pages, the most popular GitHub Pages step in the Wercker Steps repository. Additionally, we need to ensure the box Wercker uses for our deployments has git and ssh installed. We can do this using the install-packages command. Here is our final wercker.yml file:

    {{< code file=“wercker.yml” >}}
    box: debian
    build:
    steps:
    - arjen/hugo-build:
    version: “0.17”
    theme: herring-cove
    flags: --buildDrafts=true
    deploy:
    steps:
    - install-packages:
    packages: git ssh-client
    - lukevivier/[email protected]:
    token: $GIT_TOKEN
    domain: hugo-wercker.ig.nore.me
    basedir: public
    {{< /code >}}

    How does the GitHub Pages Configuration Work?

    We’ve provided a some important information in our wercker.yml. First, we’ve added the domain we want to use for our published website. Configuring the domain here will ensure that GitHub Pages is aware of the domain we want to use.

    Secondly, we’ve configured the basedir to public. This is the directory that will be used as the website on GitHub Pages. public is also the default publishing directory in Hugo. (For more information, see hugo’s configuration docs).

    Lastly, you’ll notice a $GIT_TOKEN variable. This is used for pushing our changes to GitHub. We will need to configure this token before Wercker can build our website.

    Set the App’s Deploy Target

    We can set our deploy target by going to our app’s settings and clicking on Deploy targets. Now select Add deploy target and then Custom deploy.

    Configure the Deploy Step in Wercker

    The next screen requires you fill in the deploy target name.

    1. Make sure you enable auto deploy from the master branch.
    2. Add a variable for the GIT_TOKEN. You’ll need to create an access token in GitHub. Follow the directions in GitHub help.
    3. With the deploy step configured in Wercker, we can push the updated wercker.yml file to GitHub and it will create the GitHub pages site for us.

    The website described in this guide is available at http://hugo-wercker.ig.nore.me.

    Conclusion

    Once this workflow is established, you can update your website automatically by pushing any content changes to your GitHub repository.

    Code for the Wercker Deployment Guide

    The source code for the site used in this guide is available on GitHub, as is the Wercker Hugo Build step.

    If you want to see an example of how you can deploy to S3 instead of GitHub pages, check Wercker’s documentation for guidance on setup.

    Deployment with Rysnc

    Assumptions

    • Access to your web host with SSH
    • A functional static website built with Hugo

    The spoiler is that you can deploy your entire website with a command that looks like the following:

    hugo && rsync -avz --delete public/ [email protected]:~/www/
    

    As you will see, we put it in a shell script file, which makes building and deployment as easy as executing ./deploy.

    Install SSH Key

    If it is not done yet, we will make an automated way to SSH to your server. If you have already installed an SSH key, switch to the next section.

    First, install the ssh client. On Debian/Ubuntu/derivates, use the following command:

    {{< code file=“install-openssh.sh” >}}
    sudo apt-get install openssh-client
    {{< /code >}}

    Then generate your ssh key by entering the following commands:

    ~$ cd && mkdir .ssh & cd .ssh
    ~/.ssh/$ ssh-keygen -t rsa -q -C "For SSH" -f rsa_id
    ~/.ssh/$ cat >> config <<EOF
    Host HOST
         Hostname HOST
         Port 22
         User USER
         IdentityFile ~/.ssh/rsa_id
    EOF
    

    Don’t forget to replace the HOST and USER values with your own ones. Then copy your ssh public key to the remote server:

    ~/.ssh/$ ssh-copy-id -i rsa_id.pub [email protected]
    

    Now you can easily connect to the remote server:

    ~$ ssh user@host
    Enter passphrase for key '/home/mylogin/.ssh/rsa_id':
    

    And you’ve done it!

    Shell Script

    We will put the first command in a script at the root of your Hugo tree:

    ~/websites/topologix.fr$ editor deploy
    

    Here you put the following content. Replace the USER, HOST, and DIR values with your own:

    #!/bin/sh
    USER=my-user
    HOST=my-server.com
    DIR=my/directory/to/topologix.fr/   # might sometimes be empty!
    
    hugo && rsync -avz --delete public/ ${USER}@${HOST}:~/${DIR}
    
    exit 0
    

    Note that DIR is the relative path from the remote user’s home. If you have to specify a full path (for instance /var/www/mysite/) you must change ~/${DIR} to ${DIR} inside the command line. For most cases you should not have to.

    Save and close, and make the deploy file executable:

    ~/websites/topologix.fr$ chmod +x deploy
    

    Now you only have to enter the following command to deploy and update your website:

    ~/websites/topologix.fr$ ./deploy
    Started building sites ...
    Built site for language en:
    0 draft content
    0 future content
    0 expired content
    5 pages created
    0 non-page files copied
    0 paginator pages created
    0 tags created
    0 categories created
    total in 56 ms
    sending incremental file list
    404.html
    index.html
    index.xml
    sitemap.xml
    cours-versailles/index.html
    exercices/index.html
    exercices/index.xml
    exercices/barycentre-et-carres-des-distances/index.html
    post/
    post/index.html
    sujets/index.html
    sujets/index.xml
    sujets/2016-09_supelec-jp/index.html
    tarifs-contact/index.html
    
    sent 9,550 bytes  received 1,708 bytes  7,505.33 bytes/sec
    total size is 966,557  speedup is 85.86
    

    Contribute to the Hugo Project

    Hugo relies heavily on the enthusiasm and participation of the open-source community. We need your support in both its development and documentation.

    Hugo’s contribution guidelines are detailed in a CONTRIBUTING.md in the Hugo source repository on GitHub.

    Contribute to Hugo Development

    Introduction

    Hugo is an open-source project and lives by the work of its contributors. There are plenty of open issues, and we need your help to make Hugo even more awesome. You don’t need to be a Go guru to contribute to the project’s development.

    Assumptions

    This contribution guide takes a step-by-step approach in hopes of helping newcomers. Therefore, we only assume the following:

    • You are new to Git or open-source projects in general
    • You are a fan of Hugo and enthusiastic about contributing to the project

    {{% note “Additional Questions?” %}}
    If you’re struggling at any point in this contribution guide, reach out to the Hugo community in Hugo’s Discussion forum.
    {{% /note %}}

    Install Go

    The installation of Go should take only a few minutes. You have more than one option to get Go up and running on your machine.

    If you are having trouble following the installation guides for go, check out Go Bootcamp, which contains setups for every platform or reach out to the Hugo community in the Hugo Discussion Forums.

    Install Go From Source

    Download the latest stable version of Go and follow the official Golang installation guide.

    Once you’re finished installing Go, let’s confirm everything is working correctly. Open a terminal—or command line under Windows–and type the following:

    go version
    

    You should see something similar to the following written to the console. Note that the version here reflects the most recent version of Go as of the last update for this page:

    go version go1.8 darwin/amd64
    

    Next, make sure that you set up your GOPATH as described in the installation guide.

    You can print the GOPATH with echo $GOPATH. You should see a non-empty string containing a valid path to your Go workspace; .e.g.:

    /Users/<yourusername>/Code/go
    

    Install Go with Homebrew

    If you are a macOS user and have Homebrew installed on your machine, installing Go is as simple as the following command:

    {{< code file=“install-go.sh” >}}
    brew install go
    {{< /code >}}

    Install Go via GVM

    More experienced users can use the Go Version Manager (GVM). GVM allows you to switch between different Go versions on the same machine. If you’re a beginner, you probably don’t need this feature. However, GVM makes it easy to upgrade to a new released Go version with just a few commands.

    GVM comes in especially handy if you follow the development of Hugo over a longer period of time. Future versions of Hugo will usually be compiled with the latest version of Go. Sooner or later, you will have to upgrade if you want to keep up.

    Create a GitHub Account

    If you’re going to contribute code, you’ll need to have an account on GitHub. Go to www.github.com/join and set up a personal account.

    Install Git on Your System

    You will need to have Git installed on your computer to contribute to Hugo development. Teaching git is outside the scope of the Hugo docs, but if you’re looking for an excellent reference to learn the basics of Git, we recommend the Git book if you are not sure where to begin. The used terminology will be explained with annotations.

    Git is a version control system to track the changes of source code. Hugo depends on smaller third-party packages that are used to extend the functionality. We use them because we don’t want to reinvent the wheel.

    Go ships with a sub-command called get that will download these packages for us when we setup our working environment. The source code of the packages is tracked with Git. get will interact with the Git servers of the package hosters in order to fetch all dependencies.

    Move back to the terminal and check if Git is already installed. Type in git version and press enter. You can skip the rest of this section if the command returned a version number. Otherwise download the lastest version of Git and follow this installation guide.

    Finally, check again with git version if Git was installed successfully.

    Git Graphical Front Ends

    There are several GUI clients that help you to operate Git. Not all are available for all operating systems and maybe differ in their usage. Thus, so we will use the command line since the commands are everywhere the same.

    Install Hub on Your System (Optional)

    Hub is a great tool for working with GitHub. The main site for it is hub.github.com. Feel free to install this little Git wrapper.

    On a Mac, you can install Hub using Homebrew:

    brew install hub
    

    Now we’ll create an alias in Bash so that typing git actually runs Hub:

    echo "alias git='hub'" >> ~/.bash_profile
    

    Confirm the installation:

    git version 2.6.3
    hub version 2.2.2
    

    Set up your working copy

    The working copy is set up locally on your computer. It’s what you’ll edit, compile, and end up pushing back to GitHub. The main steps are cloning the repository and creating your fork as a remote.

    Clone the repository

    We assume that you’ve set up your GOPATH (see the section above if you’re unsure about this). You should now copy the Hugo repository down to your computer. You’ll hear this called “clone the repo”. GitHub’s help pages give us a short explanation:

    When you create a repository on GitHub, it exists as a remote repository. You can create a local clone of your repository on your computer and sync between the two locations.

    We’re going to clone the master Hugo repository. That seems counter-intuitive, since you won’t have commit rights on it. But it’s required for the Go workflow. You’ll work on a copy of the master and push your changes to your own repository on GitHub.

    So, let’s clone that master repository:

    go get -v -u github.com/gohugoio/hugo
    

    Fork the repository

    If you’re not fimiliar with this term, GitHub’s help pages provide again a simple explanation:

    A fork is a copy of a repository. Forking a repository allows you to freely experiment with changes without affecting the original project.

    Fork by hand

    Open the Hugo repository on GitHub and click on the “Fork” button in the top right.

    Fork button

    Now open your fork repository on GitHub and copy the remote url of your fork. You can choose between HTTPS and SSH as protocol that Git should use for the following operations. HTTPS works always if you’re not sure.

    Copy remote url

    Switch back to the terminal and move into the directory of the cloned master repository from the last step.

    cd $GOPATH/src/github.com/gohugoio/hugo
    

    Now Git needs to know that our fork exists by adding the copied remote url:

    git remote add <YOUR-GITHUB-USERNAME> <COPIED REMOTE-URL>
    

    Fork with Hub

    Alternatively, you can use the Git wrapper Hub. Hub makes forking a repository easy:

    git fork
    

    That command will log in to GitHub using your account, create a fork of the repository that you’re currently working in, and add it as a remote to your working copy.

    Trust, but verify

    Let’s check if everything went right by listing all known remotes:

    git remote -v
    

    The output should look similar:

    digitalcraftsman    [email protected]:digitalcraftsman/hugo.git (fetch)
    digitalcraftsman    [email protected]:digitalcraftsman/hugo.git (push)
    origin  https://github.com/gohugoio/hugo (fetch)
    origin  https://github.com/gohugoio/hugo (push)
    

    The Hugo Git Contribution Workflow

    Create a new branch

    You should never develop against the “master” branch. The development team will not accept a pull request against that branch. Instead, create a descriptive named branch and work on it.

    First, you should always pull the latest changes from the master repository:

    git checkout master
    git pull
    

    Now we can create a new branch for your additions:

    git checkout -b <BRANCH-NAME>
    

    You can check on which branch your are with git branch. You should see a list of all local branches. The current branch is indicated with a little asterisk.

    Contribute to Documentation

    Perhaps you want to start contributing to the Hugo docs. If so, you can ignore most of the following steps and focus on the /docs directory within your newly cloned repository. You can change directories into the Hugo docs using cd docs.

    You can start Hugo’s built-in server via hugo server. Browse the documentation by entering http://localhost:1313 in the address bar of your browser. The server automatically updates the page whenever you change content.

    We have developed a separate Hugo documentation contribution guide for more information on how the Hugo docs are built, organized, and improved by the generosity of people like you.

    Build Hugo

    While making changes in the codebase it’s a good idea to build the binary to test them:

    go build -o hugo main.go
    

    Test

    Sometimes changes on the codebase can cause unintended side effects. Or they don’t work as expected. Most functions have their own test cases. You can find them in files ending with _test.go.

    Make sure the commands go test ./... passes, and go build completes.

    Formatting

    The Go code styleguide maybe is opiniated but it ensures that the codebase looks the same, regardless who wrote the code. Go comes with its own formatting tool. Let’s apply the styleguide to our addtions:

    go fmt ./...
    

    Once you made your additions commit your changes. Make sure that you follow our code contribution guidelines:

    # Add all changed files
    git add --all
    git commit --message "YOUR COMMIT MESSAGE"
    

    The commit message should describe what the commit does (e.g. add feature XYZ), not how it is done.

    Modify commits

    You noticed some commit messages don’t fulfill the code contribution guidelines or you just forget something to add some files? No problem. Git provides the necessary tools to fix such problems. The next two methods cover all common cases.

    If you are unsure what a command does leave the commit as it is. We can fix your commits later in the pull request.

    Modify the last commit

    Let’s say you want to modify the last commit message. Run the following command and replace the current message:

    git commit --amend -m"YOUR NEW COMMIT MESSAGE"
    

    Take a look at the commit log to see the change:

    git log
    # Exit with q
    

    After making the last commit you may forgot something. There is no need to create a new commit. Just add the latest changes and merge them into the intended commit:

    git add --all
    git commit --amend
    

    Modify multiple commits

    {{% warning “Be Careful Modifying Multiple Commits”%}}
    Modifications such as those described in this section can have serious unintended consequences. Skip this section if you’re not sure!
    {{% /warning %}}

    This is a bit more advanced. Git allows you to rebase commits interactively. In other words: it allows you to rewrite the commit history.

    git rebase --interactive @~6
    

    The 6 at the end of the command represents the number of commits that should be modified. An editor should open and present a list of last six commit messages:

    pick 80d02a1 tpl: Add hasPrefix to the template funcs' "smoke test"
    pick aaee038 tpl: Sort the smoke tests
    pick f0dbf2c tpl: Add the other test case for hasPrefix
    pick 911c35b Add "How to contribute to Hugo" tutorial
    pick 33c8973 Begin workflow
    pick 3502f2e Refactoring and typo fixes
    

    In the case above we should merge the last to commits in the commit of this tutorial (Add "How to contribute to Hugo" tutorial). You can “squash” commits, i.e. merge two or more commits into a single one.

    All operations are written before the commit message. Replace “pick” with an operation. In this case squash or s for short:

    pick 80d02a1 tpl: Add hasPrefix to the template funcs' "smoke test"
    pick aaee038 tpl: Sort the smoke tests
    pick f0dbf2c tpl: Add the other test case for hasPrefix
    pick 911c35b Add "How to contribute to Hugo" tutorial
    squash 33c8973 Begin workflow
    squash 3502f2e Refactoring and typo fixes
    

    We also want to rewrite the commits message of the third last commit. We forgot “docs:” as prefix according to the code contribution guidelines. The operation to rewrite a commit is called reword (or r as shortcut).

    You should end up with a similar setup:

    pick 80d02a1 tpl: Add hasPrefix to the template funcs' "smoke test"
    pick aaee038 tpl: Sort the smoke tests
    pick f0dbf2c tpl: Add the other test case for hasPrefix
    reword 911c35b Add "How to contribute to Hugo" tutorial
    squash 33c8973 Begin workflow
    squash 3502f2e Refactoring and typo fixes
    

    Close the editor. It should open again with a new tab. A text is instructing you to define a new commit message for the last two commits that should be merged (aka “squashed”). Save the file with CTRL+S and close the editor again.

    A last time a new tab opens. Enter a new commit message and save again. Your terminal should contain a status message. Hopefully this one:

    Successfully rebased and updated refs/heads/<BRANCHNAME>.
    

    Check the commit log if everything looks as expected. Should an error occur you can abort this rebase with git rebase --abort.

    Push commits

    To push our commits to the fork on GitHub we need to speficy a destination. A destination is defined by the remote and a branch name. Earlier, the defined that the remote url of our fork is the same as our GitHub handle, in my case digitalcraftsman. The branch should have the same as our local one. This makes it easy to identify corresponding branches.

    git push --set-upstream <YOUR-GITHUB-USERNAME> <BRANCHNAME>
    

    Now Git knows the destination. Next time when you to push commits you just need to enter git push.

    If you modified your commit history in the last step GitHub will reject your try to push. This is a safety-feature because the commit history isn’t the same and new commits can’t be appended as usual. You can enforce this push explicitly with git push --force.

    Open a pull request

    We made a lot of progress. Good work. In this step we finally open a pull request to submit our additions. Open the Hugo master repository on GitHub in your browser.

    You should find a green button labeld with “New pull request”. But GitHub is clever and probably suggests you a pull request like in the beige box below:

    Open a pull request

    The new page summaries the most important information of your pull request. Scroll down and you find the additions of all your commits. Make sure everything looks as expected and click on “Create pull request”.

    Accept the contributor license agreement

    Last but not least you should accept the contributor license agreement (CLA). A new comment should be added automatically to your pull request. Click on the yellow badge, accept the agreement and authenticate yourself with your GitHub account. It just takes a few clicks and only needs to be done once.

    Accept the CLA

    Automatic builds

    We use the Travis CI loop (Linux and OS X) and AppVeyor (Windows) to compile Hugo with your additions. This should ensure that everything works as expected before merging your pull request. This in most cases only relevant if you made changes to the codebase of Hugo.

    Automic builds and their status

    Above you can see that Travis wasn’t able to compile the changes in this pull request. Click on “Details” and try to investigate why the build failed. But it doesn’t have to be your fault. Mostly, the master branch that we used as foundation for your pull request should build without problems.

    If you have questions, leave a comment in the pull request. We are willing to assist you.

    Where to start?

    Thank you for reading through this contribution guide. Hopefully, we will see you again soon on GitHub. There are plenty of open issues for you to help with.

    Feel free to open an issue if you think you found a bug or you have a new idea to improve Hugo. We are happy to hear from you.

    Additional References for Learning Git and Golang

    Contribute to the Hugo Docs

    Create Your Fork

    It’s best to make changes to the Hugo docs on your local machine to check for consistent visual styling. Make sure you’ve created a fork of hugoDocs on GitHub and cloned the repository locally on your machine. For more information, you can see GitHub’s documentation on “forking” or follow along with Hugo’s development contribution guide.

    You can then create a separate branch for your additions. Be sure to choose a descriptive branch name that best fits the type of content. The following is an example of a branch name you might use for adding a new website to the showcase:

    git checkout -b jon-doe-showcase-addition
    

    Add New Content

    The Hugo docs make heavy use of Hugo’s archetypes feature. All content sections in Hugo documentation have an assigned archetype.

    Adding new content to the Hugo docs follows the same pattern, regardless of the content section:

    hugo new <DOCS-SECTION>/<new-content-lowercase>.md
    

    Add a New Function

    Once you have cloned the Hugo repository, you can create a new function via the following command. Keep the file name lowercase.

    hugo new functions/newfunction.md
    

    The archetype for functions according to the Hugo theme is as follows:

    {{< code file=“archetypes/functions.md” >}}
    {{< readfile file=“/themes/gohugoioTheme/archetypes/functions.md”>}}
    {{< /code >}}

    New Function Required Fields

    Here is a review of the front matter fields automatically generated for you using hugo new functions/*:

    title
    this will be auto-populated in all lowercase when you use hugo new generator.
    linktitle
    the function’s actual casing (e.g., replaceRE rather than replacere).
    description
    a brief description used to populate the Functions Quick Reference.
    categories
    currently auto-populated with 'functions` for future-proofing and portability reasons only; ignore this field.
    tags
    only if you think it will help end users find other related functions
    signature
    this is a signature/syntax definition for calling the function (e.g., apply SEQUENCE FUNCTION [PARAM...]).
    workson
    acceptable values include lists,taxonomies, terms, groups, and files.
    hugoversion
    the version of Hugo that will ship with this new function.
    relatedfuncs
    other [templating functions][] you feel are related to your new function to help fellow Hugo users.
    {{.Content}}
    an extended description of the new function; examples are not only welcomed but encouraged.

    In the body of your function, expand the short description used in the front matter. Include as many examples as possible, and leverage the Hugo docs code shortcode. If you are unable to add examples but would like to solicit help from the Hugo community, add needsexample: true to your front matter.

    Add Code Blocks

    Code blocks are crucial for providing examples of Hugo’s new features to end users of the Hugo docs. Whenever possible, create examples that you think Hugo users will be able to implement in their own projects.

    Standard Syntax

    Across all pages on the Hugo docs, the typical triple-back-tick markdown syntax is used. If you do not want to take the extra time to implement the following code block shortcodes, please use standard GitHub-flavored markdown. The Hugo docs use a version of highlight.js with a specific set of languages.

    Your options for languages are xml/html, go/golang, md/markdown/mkd, handlebars, apache, toml, yaml, json, css, asciidoc, ruby, powershell/ps, scss, sh/zsh/bash/git, http/https, and javascript/js.

    Hello world!

    ``` ```

    Code Block Shortcode

    The Hugo documentation comes with a very robust shortcode for adding interactive code blocks.

    {{% note %}}
    With the code shortcodes, you must include triple back ticks and a language declaration. This was done by design so that the shortcode wrappers were easily added to legacy documentation and will be that much easier to remove if needed in future versions of the Hugo docs.
    {{% /note %}}

    code

    code is the Hugo docs shortcode you’ll use most often. code requires has only one named parameter: file. Here is the pattern:

    {{%/* code file="smart/file/name/with/path.html" download="download.html" copy="true" */%}}
    

    A whole bunch of coding going on up in here!

    {{%/* /code */%}}
    

    The following are the arguments passed into code:

    file
    the only required argument. file is needed for styling but also plays an important role in helping users create a mental model around Hugo’s directory structure. Visually, this will be displayed as text in the top left of the code block.
    download
    if omitted, this will have no effect on the rendered shortcode. When a value is added to download, it’s used as the filename for a downloadable version of the code block.
    copy
    a copy button is added automatically to all code shortcodes. If you want to keep the filename and styling of code but don’t want to encourage readers to copy the code (e.g., a “Do not do” snippet in a tutorial), use copy="false".

    Example code Input

    This example HTML code block tells Hugo users the following:

    1. This file could live in layouts/_default, as demonstrated by layouts/_default/single.html as the value for file.
    2. This snippet is complete enough to be downloaded and implemented in a Hugo project, as demonstrated by download="single.html".
    {{%/* code file="layouts/_default/single.html" download="single.html" */%}}
    

    {{ define “main” }}

    {{.Title}}

    {{with .Params.subtitle}} {{.}}
    {{.Content}}
    {{ end }} ``` {{%/* /code */%}} ```
    Example ‘code’ Display

    The output of this example will render to the Hugo docs as follows:

    {{< code file=“layouts/_default/single.html” download=“single.html” >}}
    {{ define “main” }}

    {{.Title}}

    {{with .Params.subtitle}} {{.}}
    {{.Content}}
    {{ end }} {{< /code >}}

    Blockquotes

    Blockquotes can be added to the Hugo documentation using typical Markdown blockquote syntax:

    > Without the threat of punishment, there is no joy in flight.
    

    The preceding blockquote will render as follows in the Hugo docs:

    Without the threat of punishment, there is no joy in flight.

    However, you can add a quick and easy <cite> element (added on the client via JavaScript) by separating your main blockquote and the citation with a hyphen with a single space on each side:

    > Without the threat of punishment, there is no joy in flight. - [Kobo Abe](https://en.wikipedia.org/wiki/Kobo_Abe)
    

    Which will render as follows in the Hugo docs:

    Without the threat of punishment, there is no joy in flight. - Kobo Abe

    {{% note “Blockquotes != Admonitions” %}}
    Previous versions of Hugo documentation used blockquotes to draw attention to text. This is not the intended semantic use of <blockquote>. Use blockquotes when quoting. To note or warn your user of specific information, use the admonition shortcodes that follow.
    {{% /note %}}

    Admonitions

    Admonitions are common in technical documentation. The most popular is that seen in reStructuredText Directives. From the SourceForge documentation:

    Admonitions are specially marked “topics” that can appear anywhere an ordinary body element can. They contain arbitrary body elements. Typically, an admonition is rendered as an offset block in a document, sometimes outlined or shaded, with a title matching the admonition type. - SourceForge

    The Hugo docs contain three admonitions: note, tip, and warning.

    note Admonition

    Use the note shortcode when you want to draw attention to information subtly. note is intended to be less of an interruption in content than is warning.

    Example note Input

    {{< code file=“note-with-heading.md” >}}
    {{%/* note /%}}
    Here is a piece of information I would like to draw your attention to.
    {{%/
    /note */%}}
    {{< /code >}}

    Example note Output

    {{< output file=“note-with-heading.html” >}}
    {{% note %}}
    Here is a piece of information I would like to draw your attention to.
    {{% /note %}}
    {{< /output >}}

    Example note Display

    {{% note %}}
    Here is a piece of information I would like to draw your attention to.
    {{% /note %}}

    tip Admonition

    Use the tip shortcode when you want to give the reader advice. tip, like note, is intended to be less of an interruption in content than is warning.

    Example tip Input

    {{< code file=“using-tip.md” >}}
    {{%/* tip /%}}
    Here’s a bit of advice to improve your productivity with Hugo.
    {{%/
    /tip */%}}
    {{< /code >}}

    Example tip Output

    {{< output file=“tip-output.html” >}}
    {{% tip %}}
    Here’s a bit of advice to improve your productivity with Hugo.
    {{% /tip %}}
    {{< /output >}}

    Example tip Display

    {{% tip %}}
    Here’s a bit of advice to improve your productivity with Hugo.
    {{% /tip %}}

    warning Admonition

    Use the warning shortcode when you want to draw the user’s attention to something important. A good usage example is for articulating breaking changes in Hugo versions, known bugs, or templating “gotchas.”

    Example warning Input

    {{< code file=“warning-admonition-input.md” >}}
    {{%/* warning /%}}
    This is a warning, which should be reserved for important information like breaking changes.
    {{%/
    /warning */%}}
    {{< /code >}}

    Example warning Output

    {{< output file=“warning-admonition-output.html” >}}
    {{% warning %}}
    This is a warning, which should be reserved for important information like breaking changes.
    {{% /warning %}}
    {{< /output >}}

    Example warning Display

    {{% warning %}}
    This is a warning, which should be reserved for important information like breaking changes.
    {{% /warning %}}

    {{% note “Pull Requests and Branches” %}}
    Similar to contributing to Hugo development, the Hugo team expects you to create a separate branch/fork when you make your contributions to the Hugo docs.
    {{% /note %}}

    Add Your Hugo Theme to the Showcase

    A collection of all themes created by the Hugo community, including screenshots and demos, can be found at https://themes.gohugo.io. Every theme in this list will automatically be added to the theme site. Theme updates aren’t scheduled but usually happen at least once a week.

    tl;dr

    1. Create your theme using hugo new theme <THEMENAME>;
    2. Test your theme against https://github.com/spf13/HugoBasicExample *
    3. Add a theme.toml file to the root of the theme with all required metadata
    4. Add a descriptive README.md to the root of the theme source
    5. Add /images/screenshot.png and /images/tn.png

    * If your theme doesn’t fit into the Hugo Basic Example site, we encourage theme authors to supply a self-contained Hugo site in /exampleSite.

    {{% note %}}
    The folder name here—exampleSite—is important, as this folder will be picked up and used by the script that generates the Hugo Theme Site. It mirrors the root directory of a Hugo website and allows you to add custom content, assets, and a config file with preset values.
    {{% /note %}}

    See the Hugo Artist theme’s exampleSite for a good example.

    {{% note %}}
    Please make your example site’s content is as neutral as possible. We hope this goes without saying.
    {{% /note %}}

    Theme Requirements

    In order to add your theme to the Hugo Themes Showcase, the following requirements need to be met:

    1. theme.toml with all required fields
    2. Images for thumbnail and screenshot
    3. A good README file instructions for users
    4. Addition to the hugoThemes GitHub repository

    Add Your Theme to the Repo

    The easiest way to add your theme is to open up a new issue in the theme repository with a link to the theme’s repository on GitHub.

    Create a theme.toml File

    theme.toml contains metadata about the theme and its creator and should be created automatically when running the hugo new theme. The auto-generated file is provided here as well for easy downloading:

    {{< code file=“theme.toml” download=“theme.toml” >}}
    name = “”
    license = “MIT”
    licenselink = “https://github.com///blob/master/LICENSE.md”
    description = “”
    homepage = “http://example.com/
    tags = []
    features = []
    min_version = 0.19

    [author]
    name = “”
    homepage = “”

    If porting an existing theme

    [original]
    name = “”
    homepage = “”
    repo = “”
    {{< /code >}}

    The following fields are required:

    name = "Hyde"
    license = "MIT"
    licenselink = "https://github.com/spf13/hyde/blob/master/LICENSE.md"
    description = "An elegant open source and mobile first theme"
    homepage = "http://siteforthistheme.com/"
    tags = ["blog", "company"]
    features = ["blog"]
    min_version = 0.13
    
    [author]
        name = "spf13"
        homepage = "http://spf13.com/"
    
    # If porting an existing theme
    [original]
        author = "mdo"
        homepage = "http://hyde.getpoole.com/"
        repo = "https://www.github.com/mdo/hyde"
    

    {{% note %}}

    1. This is different from the theme.toml file created by hugo new theme in Hugo versions before v0.14.
    2. Only theme.toml is accepted; ie. not theme.yaml andnot theme.json.
      {{% /note %}}

    Images

    Screenshots are used for previews in the Hugo Theme Gallery. Make sure that they have the right dimensions:

    • Thumbnail should be 900px × 600px
    • Screenshot should be 1500px × 1000px
    • Media must be located in
      • /images/screenshot.png
      • /images/tn.png

    Additional media may be provided in the same directory.

    Create a README File

    Your theme’s README file should be written in markdown and saved at the root of your theme’s directory structure. Your README.md serves as

    1. Content for your theme’s details page at https://themes.gohugo.io
    2. General information about the theme in your GitHub repository (i.e., it’s usual purpose)

    Example README.md

    You can download the following README.md as an outline:

    {{< code file=“README.md” download=“README.md” >}}

    Theme Title

    Need input from @digitalcraftsman on what could be added to this file.

    {{< /code >}}

    {{% note “Screenshots in your README.md”%}}
    If you add screenshots to the README, please make use of absolute file paths instead of relative ones like /images/screenshot.png. Relative paths work great on GitHub but they don’t correspond to the directory structure of themes.gohugo.io. Therefore, browsers will not be able to display screenshots on the theme site under the given (relative) path.
    {{% /note %}}