Welcome to the first post on diggit-metal, the first thing we’re trying to figure out today is:

How little do you need to actually get something running on your hugo site?

This article is going to assume some things about you, or at the very least, has some stipulation’s you’ll have to understand to have proper content. If you’re following along it’s assumed:

If you don’t meet all the criteria here, you may have to pick your battles with what we’re going to go over. That said, the core content related to hugo should be applicable to most people trying to get started with a hugo site. If you’re not particular to Linux, or even Unix, you can skip the deployment section, and look at something like Github pages

If you’re familiar with the quick start tutorial, you’ll know that it doesn’t take make much to get started. Once you’ve got the hugo binary installed on your computer, you just need these commands to get some rendering going:

hugo new project quickstart
cd quickstart
git init
git submodule add https://github.com/gohugo-ananke/ananke themes/ananke
echo "theme = 'ananke'" >> hugo.toml
hugo server

If you open up the link, in my case http://localhost:1313, you’ll see the standard splash page for the ananke theme. Then, if you follow the docs a little futher, you can create your first blog post with:

hugo new content content/posts/my-first-post.md

After you re-render the site with hugo server -D (the D is for DRAFTS), you’ve got a blog post and you’re off to the races. This is all fine and dandy, but what happens if you want to skip this part?

git submodule add https://github.com/gohugo-ananke/ananke themes/ananke
echo "theme = 'ananke'" >> hugo.toml

The Commendable Way

This post isn’t a reiteration of the The Recommended Way, we’re here for The Commendable Way of setting up hugo, which is to say: for your own gratification and learning. To emphasize the point, we’re trying to get started without a theme. Bryce Wray makes some excellent points of why you’d want to do this in his blog post where he writes his own getting-started for hugo without a theme. If you’re looking for the themeless quick-start, I’d suggest starting there. We’re here for the process.

Spinning up the Project

Here, we’re going to rehash the quickstart from The Recommended Way, and see what we get.

hugo new project diggit-metal
cd diggit-metal
git init
hugo server -D

The log has a few warnings, we’ll come back to that.

WARN  found no layout file for "html" for kind "home": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
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.
WARN  found no layout file for "html" for kind "section": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.

Then, we go to http://localhost:1313

flashbang

That makes sense. There are no layout files so there are no templates to render my blog post, much less the front page. The web engine starts, though, and I’ve got a working site, so that counts for something, right? What happens if I just build my site? I can do that by just running:

hugo

Which if I tree my public/ folder…

❯ tree public
public
├── categories
│   └── index.xml
├── images
│   └── my-beautiful-hugo-site.png
├── index.xml
├── posts
│   ├── index.xml
│   └── my-beautiful-hugo-site.png
├── sitemap.xml
└── tags
    └── index.xml

It works! It outputs files and, while I love that it performs on a minimal setup, it’s not exactly what we’re looking for. We’re trying to get something that resembles a website.

What Do You Mean I Need Templates?

This is the work we have to do ourselves: setting up the overall structure of our site. For our purposes, knowing the template types should be sufficient, so we know the expectations. The WARN logs said that it’s looking for home, taxonomy, and section templates.

[!note] Front-End Witchcraft If you’re not familiar with web templates, they’re how a lot of the internet tries render content consistently without having to rewrite or copy-paste. A lot of rendering systems do it differently, but Hugo’s template system is good example of the general structure that most abide by.

So what happens if we just populate a layouts/home.html file? Just a blank one.

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.
WARN  found no layout file for "html" for kind "section": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
WARN  found no layout file for "html" for kind "page": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.

Neat, what if we just fill in everything it asks for? If you go one by one like I did, the warnings slowly disappear, but you’re still left with a Page Not Found. We’ve come to the point where we can’t just caveman our way through log responses.

Typing the Useful Things First

From the top at the templates page the first thing represented is the base template. This template usually consists of your usual, top-level html tags that define your site. It’s not necessary, but it’s smart to try and render this first. I’ll go with a simple version of the one in the tutorial site. I don’t have a bunch of partials(yet) to insert into my page.

[!note] Partials of… what? Partials are type of template where only a small section of the page is rendered. In a lot of template systems rendering typically starts with the foundational template, like Hugo’s baseof.html. Then, there’s some syntaxt in that which renders the template of the real page you’re trying to show to the user, like home.html. Any template rendered elsewhere that isn’t the real page template is usually referred to as a partial.

<!DOCTYPE html>
<html lang="{{ site.Language.Locale }}" dir="{{ or site.Language.Direction `ltr` }}">
<body>
  <main>
    {{ block "main" . }}
      If you can see this. Something went wrong.
    {{ end }}
  </main>
</body>
</html>

Now to get a page, let’s populate the home.html template. We’ll use the Hugo’s documentation default, because otherwise we’re just going to get a blank page.

{{ define "main" }}
  {{ .Content }}
  {{ range .Site.RegularPages }}
    <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
  {{ end }}
{{ end }}

Which gives us…

a beautiful hugo site

Then, just to get ahead of it, we’ll populate page.html with the bare minimum.

{{ define "main" }}
  {{ .Content }}
{{ end }}

drink it in

Now that’s what I call a fuckin’ website, but the goal will be to one day make it better like the best fuckin’ website. If you’re catching this page on the first day, you’ll probably notice that nothing works. It turns out a lot of layouts provide render hooks to make youre formatting look good, but that will have to be the subject of another post.

Inflicting Your Website Unto the Internet

Now that I have my beautiful project, I just need to do a couple of things. First, we need to take this article out of draft by setting the draft key in the frontmatter to false on the post. This signals to hugo that your content is ready to be included with the rest of your aticles. It’s important to remember that while developing more content, you may need to change other parts of your site. Using drafts lets you hide the posts you aren’t proud of until they’re ready.

Now the moment of truth.

hugo

That’s it. We have a packed public folder, now we need to send it out to be served to the rest of the world. This is where we stretch a bit beyond the realm of hugo into regular old hosting. If you’ve got a box you’re comfortable exposing to the internet and a domain that points to it.

Creating the Digital Bird’s Nest of your Blog(Directories)

Shell into your VPS on a user that has sudo access. Then, make a directory to store your hugo files. The classic hosting location is /var/www, with your site being served as a directory under there(e.g: /var/www/diggit-metal). You can accomplish this with:

sudo mkdir -p /var/www/diggit-metal

This will create a directory that’s owned by root. You’ll want to ensure its got permissions to be written to by the user who be placing files into it(namely, you.).

# bilge is me!
sudo chown bilge:root /var/www/diggit-metal.

This will make it easier for your to update your content, which your proxy should be able to see as long as the files are world readable. Generall, your distro is going to set a sensible umask so that this shouldn’t be an issue.

[bilge@asher diggit-metal]$ ls -lah
total 8.0K
drwxr-xr-x 2 bilge root  4.0K Jun  6 18:47 .     <--/var/www/diggit-metal
drwxr-xr-x 3 root  root  4.0K Jun  6 18:36 ..    <--/var/www
-rw-r--r-- 1 bilge bilge    0 Jun  6 18:47 a.file
       ^--------------------------------------------The world-readable bit for files.
drwxr-xr-x 2 bilge bilge 4.0K Jun  6 18:48 a_dir
       ^-^------------------------------------------The world-readable bit for directories AND the
                                                    execute perm, which allows directory traversal.

Now that we have a place to store our files, we need a web server to host it to the internet.

Caddy’s the Best, Use Caddy to Proxy your Content

Of all the popular web servers I am familiar with, Caddy has to be my favorite. Among its list of features, it boasts automatic SSL, which just works. If you have an endpoint with a dns entry pointing to it, Caddy pretty easily sets up SSL so that your site can operate with HTTPS.

If you’re still on your host, install caddy.

sudo pacman -S caddy

This sets you up with a basic Caddyfile at /etc/caddy/Caddyfile. To get your blog going you’ll need to add an entry for your website. For an entry that responds to the url https://diggit-metal.com and whose files are located at /var/www/diggit-metal, you need to something like this:

diggit-metal.com {
    root /var/www/diggit-metal
    file_server
    encode gzip zstd
}

Then, spin up caddy.

sudo systemctl start caddy

Now, witness greatness.

whoops

Shit, I forgot the files.

rsync, the Proverbial Catapult of Your Content

Hugo’s documentation has a great spread on how to get your files out to the world. We’re going to use the rsync method because:

*Sometimes it’s not simple.

If you didn’t just skip to this part, then you’ll know we’ve already got ssh access set up with the remote machine. So really it’s just a matter of crafting the command that will make it simple, dare I say trivial, to force our blog upon the internet. There’s a great one at the top of hugo’s rsync documentation.

hugo && rsync -avz --delete public/ www-data@ftp.topologix.fr:~/www/

Beautiful. Elegant. This sort of stuff sets off dopamine C4 in my head. If you’re not all that familiar with the shell syntax and the tools:

[!note] What is this internet sorcery There are few moving parts here, but it breaks down like this:

Do we need all of this? Nah. rsync -avz is a common pattern on the internet for transferring files, but the purpose of those flags, the -a flag in particular, is to create a backup of your files. This way when you rsync from the other direction, all of your files are exactly as they were when they left your machine, symlinks and all. Since we’ve set up the directory with the right perms, we only need the -r flag to pull everything over, this is a one way trip after all.

hugo && rsync -rvz --delete public/ bilge@asher:/var/www/diggit-metal/

Only a few changes:

[!note] But I like placing stuff under /home More power to you! But the purpose of /home is to be storage point for either personal or staging files. Even on your own system where there are no compliance officers to wag their fingers at you, you should usually consider storing your internet-facing files under a place like /var. That, and some systems get stuffy when they see files that are in home directories that shouldn’t be.

Where does that put us? On the internet!

the victorious home page

And then, ultimately, the content.

the victorious blog post

Was it Worth it?

Yes! At least I thought it was worth it. There’s so much you can learn by manually building these things, and trully that’s how you can get around to building great things with Hugo. I would even challenge someone in saying that if you’re using something like hugo, you owe it to yourself to give this process a go so that you can at least appreciate some of the heavy lifting that some hugo’s themes do for you. There are some advanced features that you would think would work out of the box, but if you treat it like I do, hugo does not hold your hand.

For me, I intend to do a little bit more building of the features myself. I’d like to cultivate my own theme, and write a bit more about my process getting there.