New Blog

Posted on Jan 22, 2025

I got bored, so I decided to get a domain and host my blog elsewhere with a different framework. I read up on Hugo, 11ty, and Jekyll some more, and decided to go with Hugo since 11ty was overkill and I used Jekyll previously on GitHub pages, so why not try something new? Moreover, I wanted to check out Vercel, so this was a good excuse to do that. Recall the blog was previously on GitHub Pages on top of Jekyll.

Day 1

Installation

This was my plan going in:

Step 1: Snag a domain from Namecheap. omya.games was cheap enough. I wanted omya.gg, but those domains are woefully expensive for a project of this scope. Step 2: Set up DNS. Namecheap prompts you to do this once the payment goes through. Step 3: Install Hugo. I’m on OS X for this install, and we’re starting from zero — well, zero point five, since I did have brew installed, but it was terribly out of date, so. Step 4: Host on Vercel. This turned out to be a blocker. See below.

After getting the domain, I opened the terminal to:

brew update
brew upgrade
brew install git
brew install go
brew install sass/sass/sass

Since I am not building from source and instead using a package manager, we’ll install Hugo with brew install hugo. The other option (aside from building from source) is downloading the binaries, but I wanted to spend more time in the terminal. Which is dumb, because I don’t particularly care for brew as a package manager or the OS X’s terminal. However, using the terminal is in line with the point of this exercise, which is to learn more about development, so here we are.

Another hiccough: Apparently I never installed command tools on this particular Mac, so brew complained about No developer tools installed when trying to install Dart Sass. Shameful. Ran xcode-select --install and went forward with that. Afterward, Dart Sass agreed to be installed. I did run brew reinstall hugo after all of this, as I sort of did it in a weird order the first time around, and wanted Hugo to be built last once all the dependencies (?) were in place. It didn’t complain on initial install, but I’m not a dev, and didn’t want to miss something.

Fresh Hugo Install

Checked the Hugo version with hugo version and found v0.142.0+extended+withdeploy. This is a newer release than v0.128.0, per the docs , so we’re good to go. The docs go on to suggest, “Run these commands to create a Hugo site with the Ananke theme. The next section provides an explanation of each command.” I wanted the Terminal theme instead, so I made that change.

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

To see what each of these commands does, check the (https://gohugo.io/getting-started/quick-start/)[Quick start guide]. I indicated the Terminal repo with git submodule add https://github.com/panr/hugo-theme-terminal.git themes/terminal and changed the theme in the hugo.toml file to match, but everything else was the same. And it worked! Amazing what following the docs and reading error messages can do.

Vercel account creation issue Vercel account creation issue

Adding Content

Next, I ran hugo new content content/posts/my-first-post.md, which adds a new page to the site in the content/posts dir. This is the dir structure of a ~fresh Hugo install. I truncated the content of the themes/terminal and public dirs.

quickstart
├─archetypes/ #empty dir
├─assets/ #empty dir
├─content/
│ └──posts/
│    └──my-first-post.md/
├─data/ #empty dir
├─hugo.toml
├─i18n/ #empty dir
├─layouts/ #empty dir
├─public/
│ └──404.html
│ └──apple-touch-icon.png
│ └──bundle.min.js
│ └──categories/
│ └──css/
│ └──favicon.png
│ └──fonts/
│ └──index.html
│ └──index.xml
│ └──og-image.png
│ └──page/
│ └──sitemap.xml
│ └──tags/
├─static/ #empty dir
└─themes/
  └──terminal/

Diverging From the Docs

Opening the markdown file in nvim shows it has many more values in the front matter than the one shown in the docs, which only has three: title, date, and draft. This file lacks draft but includes dateFormat, author, authorTwitter, cover, tags, keywords, description, showFullContent, readingTime, and hideComments. I do not know why all of these extra values are here, or if I did something improperly. I added draft and set it to true.

I added some markdown text for the body of the post and ran the server (I’d stopped it a while back) with hugo server -D, which makes it include draft content.

First post success First post success

Works fine, but I’m confused about the errant # # at the top and [] at the bottom. I suspect these are artifacts of some of the values in the front matter. Will explore that later.

GitHub

Now’s the part where we come back to the steps at the start of this document. We have Hugo installed locally, but we need to initialize a local git repo so we can push it to GitHub and get started with Vercel. I’ll not go into the details here, but I created an SSH key for the Mac and added it to GitHub and installed GitHub CLI. Had an “a-ha moment” after running gh repo create --public --source=. --push and finding it did not copy over the empty dirs. Perplexity let me know that git does not track empty directories by default, so I ran touch dirName/.gitkeep for all empty dirs (see tree above) and re-pushed. They showed up this time. Neat.

Site Config

nvim’d into hugo.toml to update the values therein (should have done this prior to pushing to GitHub). New values:

baseURL = 'https://omya.games'
languageCode = 'en-us'
title = 'Old Man Yells at Games'
theme = 'terminal'

Pushed. The docs recommend staring the dev server, but it was running this whole time, so… it didn’t seem to matter, as the server took changes in stride and rebuilt the site on each file save. Longest rebuild was 141 ms, shortest was 39 ms. Neat.

Publishing

Now we run hugo which — as they are keen to make a point of — “publishes” the site:

When you publish your site, Hugo creates the entire static site in the public directory in the root of your project. This includes the HTML files, and assets such as images, CSS files, and JavaScript files.

This is not deploying, which is all that web hosting stuff. So:

Vercel

At this point we can use Vercel to interact with the GitHub repo where the blog lives. Or, rather, would be able to use Vercel, if it didn’t have a problem with me logging in via GitHub:

Vercel account creation issue Vercel account creation issue

Sent off email, got an automated reply with a ticket number, and … waited for __. Per their website:

To protect against platform abuse, Vercel employs multiple layers of security and verification during the account signup process. You may receive an error message during signup.

This was probably going to take a while, so in the meantime, I worked on:

  • Moving posts found on GitHub/Jekyll blog and improving them with according to the style guide
  • Creating a new Terminal theme (the author made an excellent resource for this)
  • Adding a param to hugo.toml so it would display the blog’s name instead of the theme name. This was interesting, because in the theme’s logo.html file, it was looking for a param that didn’t exist and defaulted to the theme name. Here’s the logic:

{{ with $.Site.Params.Logo.logoText }}{{ . }}{{ else }}Terminal{{ end }} It was else-ing to “Terminal,” so I added

[params]
  [params.Logo]
    logoText = "My Blog Name"

to the hugo.toml file. Easy fixes are nice.

Since I am waiting on Vercel to get back to me, that concludes the work I am willing to put into this today. Overall, this went way better than I thought it would, and I’m glad — for now, at least — that I chose Hugo. Even if I switch to another SSG later later on, it was good to at least understand the installation and configuration process.

To-do:

  • Add a subhead feature that shows on the index
  • Update the colors
  • Find out how to update Hugo (probably run the update locally, then push)
  • Edit how posts on the homepage are truncated — right now, it’s showing a large amount of content (comparatively speaking), even images, so that must be cut down
  • Configure the DNS
    • Requires Vercel to play ball
  • Find what the # # and [] are for on posts

Day 2

It’s 7:30 am, and no word from Vercel yet, which is to be expected. In the meantime, I’ll tackle some of the to-do list items, starting with…

Homepage Post Truncating

I’m cheating on this one, because I actually did it yesterday but forgot to write about it while I was doing it. The issue was that Hugo was showing way too much for each post on the homepage, even images, which was making look strange and scroll-heavy. ChatGPT suggested updating the index.html file with the following:

{{ range .Pages }}
  <h2><a href="{{ .Permalink }}">{{ .Title }}</a></h2>
  <p>{{ .Content | plain | split "\n" | first }}</p>
{{ end }}

… which did not work. The server complained it didn’t know what plain was, and while I was annoyed the first solution didn’t work, I was able to test it rather quickly, so it wasn’t a time sink. I used both ChatGPT and Perplexity (since ‘Plex was having server issues) and both of them did their best to guess where files would be located, as they didn’t know the Terminal theme that well.

Turned out it wasn’t index.html that I needed to look into, but rather list.html inside /themes/terminal/layouts/_default. In hindsight, this should be been more obvious, but I was learning how Hugo works while I was using it, so. However, turns out that wasn’t the best way to do it, either.

The answer was to use the summary feature inn the front matter:

title: "My Post"
date: 2025-01-22
summary: "This is a custom summary for the post."

I didn’t encounter this during setup, and it turned out this is exactly what I needed. Not having to edit any of the code that came with Hugo was a huge bonus here, as I wanted as close to an out-of-box experience I could get. It took only a few minutes to update the front matter of my old blog posts, and so with this out of the way, two to-do items fell off:

  • Add a subhead feature that shows on the index
  • Edit how posts on the homepage are truncated — right now, it’s showing a large amount of content (comparatively speaking), even images, so that must be cut down

Changing the Default Color

I don’t dislike the orange creme default color that ships with Terminal, and I could live with it, but knowing how to change it is preferable and in line with the exercise. The theme author has page dedicated to customizing the CSS, but I don’t know which filetype to download or where it goes.

Of course, on second look, there’s a tooltip for the Type select element that explains it well enough:

Terminal tooltip Terminal tooltip

It defaults to Standalone, whereas Terminal Theme is the option I needed. I don’t know what FiraCode is, but when you select Terminal Theme, you get additional guidance on where to put the files, which is what I required:

Terminal tooltip Terminal guidance

I had to restart the server after dropping the files into ./static with hugo server --D, but it worked perfectly. Another one down:

  • Update the colors

Updating Hugo

At this point, I have to step back and really consider how Hugo is built. Per the docs,

Hugo Modules are the core building blocks in Hugo.

In the context of keeping the site UTD, I take that to mean, “Hugo modules are what you need to run regular updates for.” Furthermore,

To update or manage versions, you can use hugo mod get.

The -u flag will update all of the modules. I’m going to (likely incorrectly) assume that’s all I need to do in order to update Hugo: Run the update on the local machine and push to GitHub. We’ll see if that’s actually the case later on. Tentatively:

  • Find out how to update Hugo (probably run the update locally, then push)

All that’s left is:

  • Configure the DNS
    • Requires Vercel to play ball
  • Find what the # # and [] are for on posts

I can’t do the first one ’til Vercel gets back to me, and I don’t want to disc Jekyll vs. Hugo until the thing is actually deployed. I can make a graph in Figma, but again, I’d prefer to wait until the project is done, so we’re in a holding pattern for now w/r/t those items.

Hashmarks and Brackets

Hashmarks

Knowing the posts are listed via the list.html module (is this the correct term? “Module?”), I nvim’d into it and found this:

{{ if .Params.tags }}
	<span class="post-tags">
		{{ range .Params.tags }}
		#<a href="{{ (urlize (printf "tags/%s/" . )) | absLangURL }}">
			{{- . -}}
		</a>&nbsp
		{{ end }}
	</span>
{{ end }}

This was below the params for date and author, so I’m almost positive the empt hashmarks on the posts are for tags, which I don’t currently use.

If I had read the logic better, I’d have understood how the if statement works. Additionally, if I had bothered to look at the front matter of my posts, I would have noticed that I do include tags = ["", ""], so that’s on me. I removed the tags param from the posts.

Brackets

Again, found after the post-content block in list.html:

{{ if not .Params.showFullContent }}
	<div>
		<a class="read-more button inline" href="{{ .RelPermalink }}">{{ $.Site.Params.ReadMore }}</a>
	</div>
{{ end }}

Mouse hover shows the bracket link to be the post’s permalink, and the developer console shows the classes as written above, so this must be the same thing. The brackets are from the stylesheet, ::before and ::after. I’d just as soon not edit the stylesheet, so I need to find the (missing) copy for $.Site.Params.ReadMore. I don’t know where that parameter lives, so I asked Perplexity, which pointed to adding the line in hugo.toml:

[params]
ReadMore = "Read More"

I set up the [params] bit previously for logoText, and so:

[params]
  [params.Logo]
    logoText = "Words"
  ReadMore = "Read More"

This did not work. It seems like it should, because it appears to be properly nested. However,

[params]
  ReadMore = "Read More"
  [params.Logo]
    logoText = "Words"

does work, so I don’t know what to make of that. Either way that’s another one off the list.

  • Find what the # # and [] are for on posts

While I waited on the “yay” or “nay” from Vercel, I edited some of the posts and other light tasks.

Day 3

Vercel approved the account, so now I can work on the deployment process. I wasn’t clear on the OOO — connect the GitHub repo to Vercel, or add my domain first — so I asked ‘Plex, which indicated I should add the repo first.

Vercel

Installing Vercel onto my GitHub was simple enough, as was the import. It was troubling that Vercel didn’t detect the repo as a Hugo framework, but instead “Other.” I corrected that and deployed:

Vercel deployment Vercel deployment

I was simultaneously happy and annoyed at this semi-correct, stylesheet-less preview. On this post-depoloyment screen, Vercel gave the option to add a domain, so I did that.

Option to add domain Option to add domain

Following that:

Invalid Vercel configs Invalid Vercel configs

I anticipated this, as I did not set up the DNS on Namecheap. I know next to nothing about how DNS works, much less what an A Record is, so thankfully Vercel provided enough guidance on how to make the updates.

Namecheap

The relevant location to make updates for Vercel was under Advanced DNS. What Vercel calls Name, Namecheap calls Host — this was my assumption, anyway — so I made the change.

(screenshot of after making the advanced dns change to A Record from whatever it was before)

It worked! Now for the wwww. domain.

The only domain listed at Namecheap is omya.games (no www. version) so while Vercel wants a change on that one, I’m iffy on what to do, but since Vercel detects changes made at Namecheap quickly (so far), I added a added a new CNAME Record:

CNAME Record New CNAME Record

Again: It worked! Vercel:

WWW Record! WWW Success

Firefox timed out trying to find the domain, so I went to lunch while it propagated (about 15 mins). It indeed loads without a stylesheet and a problem I anticipated a while ago did in fact show up: All links point to what was the local server (e.g., http://localhost:1313/posts/2024-12-13-odin-2-pro-review/) — this explains the lack of style.

This proved easier than anticipated: I previously edited hugo.toml to add a baseURL with baseURL = "https://omya.games/", so now I just had to re-build with hugo --environment production and push.

Deployment != Rebuilding

Shameful: I kept committing changes to a markdown file on GitHub and wondering why Vercel insisted on showing old content. It never occurred to me, until I looked at the log, that the HTML wasn’t updating because at no point did I rebuild after editing the markdown. According to ‘Plex, writing a GitHub action is the move, so:

name: Deploy Hugo Site
on: 
  push:
    branches: 
      - main  # Triggers on pushes to main branch

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      # Check out the code
      - uses: actions/checkout@v4
        with:
          submodules: recursive  # If you use submodules

      # Cache Hugo dependencies (optional)
      - name: Cache Hugo files
        uses: actions/cache@v3
        with:
          path: |
            ./resources
            ./public
            ./node_modules
          key: ${{ runner.os }}-hugo-${{ hashFiles('**/*.md', '**/*.toml', '**/*.yaml', '**/*.json') }}
          restore-keys: |
            ${{ runner.os }}-hugo-

      # Setup Hugo
      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: 'latest'  # Pin to a specific version if needed for stablility
          extended: true  # For SCSS/SASS support

      # Build the Hugo site
      - name: Build
        run: hugo --minify

      # Deploy to Vercel using CLI
      - name: Install Vercel CLI
        run: npm install -g vercel

      - name: Deploy to Vercel
        run: vercel --prod --token ${{ secrets.VERCEL_TOKEN }} --yes --debug

Took four or five edits, but the above is what finally worked. ChatGPT ended up being more useful than ‘Plex on this one.

Conclusions

Altogether, this took about 10 hours or so to get running perfectly, and while there are definitely some things in Hugo I know nothing about (functions, methods, render hooks, modules, pipes) — mostly because they didn’t come up — I feel fairly confident in how Hugo works. I’m glad I chose to do it via CLI and configure everything myself. Go is meant to be a speedy language, but it’s difficult to tell, as this is a low-intensity project, so. Hugo is great so far, and I’d definitely recommend it to those interested in a SSG.