With Claude's help I figured out what I think is the most basic version of a static site generated using Hugo.
I wanted a base template that set out a common layout, then two example of pages that used that layout to render content with a custom title.
This is my first time ever trying out Hugo so it's quite possible there's an even simpler approach, but this is what I got to.
Hugo uses a directory called layouts
to define its templates. I created three files in this directory:
<!DOCTYPE html>
<html>
<head>
<title>{{ .Title }}</title>
</head>
<body>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
{{ .Content }}
<footer>
<p>My Site Footer</p>
</footer>
</body>
</html>
{{ define "main" }}
{{ .Content }}
{{ end }}
{{ define "main" }}
{{ .Content }}
{{ end }}
Note that index.html
and single.html
are identical. I'm not sure why Hugo needed both - the index.html
file is used for the homepage.
I created a content
directory with two files in it:
---
title: Welcome
---
# Welcome to my site
This is my homepage content in Markdown.
---
title: About
---
<h1>About Us</h1>
<p>This is the about page, written directly in HTML.</p>
Note that both of these have frontmatter at the top to define the title. This seems to be the right pattern for combining HTML content and Markdown content in the same project.
According to the Hugo documentation:
_index.md
has a special role in Hugo. It allows you to add front matter and content tohome
,section
,taxonomy
, andterm
pages.
Since I'm not using the taxonomy
and term
features yet this probably isn't relevant to me.
Here's a Bash script that, when run, will create the directories and files listed above:
mkdir hugo-site
cd hugo-site
mkdir -p layouts/_default content
cat > layouts/_default/baseof.html <<EOF
<!DOCTYPE html>
<html>
<head>
<title>{{ .Title }}</title>
</head>
<body>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
{{ .Content }}
<footer>
<p>My Site Footer</p>
</footer>
</body>
</html>
EOF
cat > layouts/_default/single.html <<EOF
{{ define "main" }}
{{ .Content }}
{{ end }}
EOF
cat > layouts/index.html <<EOF
{{ define "main" }}
{{ .Content }}
{{ end }}
EOF
cat > content/_index.md <<EOF
---
title: Welcome
---
# Welcome to my site
This is my homepage content in Markdown.
EOF
cat > content/about.html <<EOF
---
title: About
---
<h1>About Us</h1>
<p>This is the about page, written directly in HTML.</p>
EOF
Having created these files (in a hugo-site
folder) we can initialize a Hugo site like this:
hugo new site . --force
The --force
flag is needed because we are creating the site in a directory that already contains files.
Now run this to preview the site in a browser:
hugo server
And visit http://localhost:1313/
to see the site.
The About page is now located at /about/
and the homepage is at /
.
Running this command builds a static version of the site in the public
directory:
hugo build
When I ran it I got this non-fatal warning:
WARN found no layout file for "html" for kind "taxonomy": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
Since I wasn't using the taxonomy
feature I added the following to the hugo.conf
file that had been generated for me:
disableKinds = ['taxonomy', 'term']
After this, hugo build
ran without warnings.
The public
folder contained these files:
public
public/index.html
public/index.xml
public/about
public/about/index.html
public/sitemap.xml
index.yml
is an RSS 2.0 feed, and sitemap.xml
is a Sitemap.
Both of these had example.org
hard-coded into them, e.g. sitemap.xml
looked like this:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://example.org/about/</loc>
</url><url>
<loc>https://example.org/</loc>
</url>
</urlset>
The fix for that is to update hugo.toml
to set the domain name where the site will be deployed:
baseURL = 'https://example.simonwillison.net/'
languageCode = 'en-us'
title = 'My example site'
disableKinds = ['taxonomy', 'term']
Running hugo build
rewrites the sitemap.xml
and index.xml
files to use the correct domain name.
I haven't actually deployed a Hugo site yet, but I expect I'll try this using either GitHub Pages or Netlify or Cloudflare Pages soon.